diff --git a/.hgignore b/.hgignore deleted file mode 100644 index 5681fe96255..00000000000 --- a/.hgignore +++ /dev/null @@ -1,77 +0,0 @@ -# Mercurial's .hgignore files can only be used in the root directory. -# You can still apply these rules by adding -# include:path/to/this/directory/.hgignore to the top-level .hgignore file. - -# Ensure same syntax as in .gitignore can be used -syntax:glob - -# Android generated -bin -gen -libs -obj -lint.xml - -# IntelliJ IDEA & Android Studio -.idea -*.iml -*.ipr -*.iws -classes -gen-external-apklibs -*.li - -# Eclipse -.project -.classpath -.settings -.checkstyle -.cproject - -# Gradle -.gradle -build -buildout -out - -# Maven -target -release.properties -pom.xml.* - -# Ant -ant.properties -local.properties -proguard.cfg -proguard-project.txt - -# Bazel -bazel-bin -bazel-genfiles -bazel-out -bazel-testlogs - -# Other -.DS_Store -cmake-build-debug -dist -jacoco.exec -tmp - -# VP9 extension -extensions/vp9/src/main/jni/libvpx -extensions/vp9/src/main/jni/libvpx_android_configs -extensions/vp9/src/main/jni/libyuv - -# AV1 extension -extensions/av1/src/main/jni/libgav1 -extensions/av1/src/main/jni/cpu_features - -# Opus extension -extensions/opus/src/main/jni/libopus - -# FLAC extension -extensions/flac/src/main/jni/flac - -# FFmpeg extension -extensions/ffmpeg/src/main/jni/ffmpeg diff --git a/README.md b/README.md index 67d52a4cec8..d3c8c5e44c6 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,8 @@ implementation 'com.google.android.exoplayer:exoplayer-dash:2.X.X' implementation 'com.google.android.exoplayer:exoplayer-ui:2.X.X' ``` +When depending on individual modules they must all be the same version. + The available library modules are listed below. Adding a dependency to the full ExoPlayer library is equivalent to adding dependencies on all of the library modules individually. diff --git a/RELEASENOTES.md b/RELEASENOTES.md index fd484db6c8c..b5a922f3d07 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,5 +1,150 @@ # Release notes +### 2.15.0 (2021-08-10) + +* Core Library: + * Add `MediaCodecAdapter.needsReconfiguration` method. + * Add `getSeekBackIncrement`, `seekBack`, `getSeekForwardIncrement`, + `seekForward`, `getMaxSeekToPreviousPosition`, `seekToPrevious` and + `seekToNext` methods to `Player`. + * Rename `Player` methods: + * `hasPrevious` to `hasPreviousWindow`. + * `previous` to `seekToPreviousWindow`. + * `hasNext` to `hasNextWindow`. + * `next` to `seekToNextWindow`. + * Rename `Player` commands: + * `COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM` to + `COMMAND_SEEK_IN_CURRENT_WINDOW`. + * `COMMAND_SEEK_TO_NEXT_MEDIA_ITEM` to `COMMAND_SEEK_TO_NEXT_WINDOW`. + * `COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM` to + `COMMAND_SEEK_TO_PREVIOUS_WINDOW`. + * `COMMAND_SEEK_TO_MEDIA_ITEM` to `COMMAND_SEEK_TO_WINDOW`. + * `COMMAND_GET_MEDIA_ITEMS` to `COMMAND_GET_TIMELINE`. + * Rename `Player.EventFlags` IntDef to `Player.Event`. + * Make `Player` depend on the new `PlaybackException` class instead of + `ExoPlaybackException`: + * `Player.getPlayerError` now returns a `PlaybackException`. + * `Player.Listener.onPlayerError` now receives a `PlaybackException`. + * Add a new listener method `Player.Listener.onPlayerErrorChanged`, + which is equivalent to `onPlayerError` except that it is also called + when the player error becomes `null`. + * `Player` implementations like `ExoPlayer` may use + `PlaybackException` subclasses (like `ExoPlaybackException`), so + users can downcast the `PlaybackException` instance to obtain + implementation-specific fields (like + `ExoPlaybackException.rendererIndex`). + * `PlaybackException` introduces an `errorCode` which identifies the cause + of the failure in order to simplify error handling + ([#1611](https://github.com/google/ExoPlayer/issues/1611)). + * Add a `DefaultMediaDescriptionAdapter` for the + `PlayerNotificationManager`, that makes use of the `Player` + `MediaMetadata` to populate the notification fields. + * Add `@FallbackType` to `LoadErrorHandlingPolicy` to support + customization of the exclusion duration for locations and tracks. + * Change interface of `LoadErrorHandlingPolicy` to support configuring the + behavior of track and location fallback. Location fallback is currently + only supported for DASH manifests with multiple base URLs. + * Restrict use of `AudioTrack.isDirectPlaybackSupported` to TVs, to avoid + listing audio offload encodings as supported for passthrough mode on + mobile devices + ([#9239](https://github.com/google/ExoPlayer/issues/9239)). +* Extractors: + * Add support for DTS-UHD in MP4 + ([#9163](https://github.com/google/ExoPlayer/issues/9163)). +* Text: + * TTML: Inherit the `rubyPosition` value from a containing `` element. + * WebVTT: Add support for CSS `font-size` property + ([#8964](https://github.com/google/ExoPlayer/issues/8964)). +* Ad playback: + * Support changing ad break positions in the player logic + ([#5067](https://github.com/google/ExoPlayer/issues/5067)). + * Support resuming content with an offset after an ad group. +* UI: + * Add `setUseRewindAction` and `setUseFastForwardAction` to + `PlayerNotificationManager`, and `setUseFastForwardActionInCompactView` + and `setUseRewindActionInCompactView` to show the actions in compact + view mode. + * Remove `rewind_increment` and `fastforward_increment` attributes from + `PlayerControlView` and `StyledPlayerControlView`. These increments can + be customized by configuring the `Player` (see `setSeekBackIncrementMs` + and `setSeekForwardIncrementMs` in `SimpleExoPlayer.Builder`), or by + using a `ForwardingPlayer` that overrides `getSeekBackIncrement`, + `seekBack`, `getSeekForwardIncrement` and `seekForward`. The rewind and + fast forward buttons can be disabled by using a `ForwardingPlayer` that + removes `COMMAND_SEEK_BACK` and `COMMAND_SEEK_FORWARD` from the + available commands. + * Update `DefaultControlDispatcher` `getRewindIncrementMs` and + `getFastForwardIncrementMs` to take the player as parameter. +* DASH: + * Add support for multiple base URLs and DVB attributes in the manifest. + Apps that are using `DefaultLoadErrorHandlingPolicy` with such manifests + have base URL fallback automatically enabled + ([#771](https://github.com/google/ExoPlayer/issues/771), + [#7654](https://github.com/google/ExoPlayer/issues/7654)). +* HLS: + * Fix issue that could cause some playbacks to be stuck buffering + ([#8850](https://github.com/google/ExoPlayer/issues/8850), + [#9153](https://github.com/google/ExoPlayer/issues/9153)). + * Report audio track type in + `AnalyticsListener.onDownstreamFormatChanged()` for audio-only + playlists, so that the `PlaybackStatsListener` can derive audio + format-related information + ([#9175](https://github.com/google/ExoPlayer/issues/9175)). +* RTSP: + * Use standard RTSP header names + ([#9182](https://github.com/google/ExoPlayer/issues/9182)). + * Handle an extra semicolon in SDP fmtp attribute + ([#9247](https://github.com/google/ExoPlayer/pull/9247)). + * Fix handling of special characters in the RTSP session ID + ([#9254](https://github.com/google/ExoPlayer/issues/9254)). +* SmoothStreaming: + * Propagate `StreamIndex` element `Name` attribute value as `Format` label + ([#9252](https://github.com/google/ExoPlayer/issues/9252)). +* Cronet extension: + * Add `CronetDataSource.Factory.setRequestPriority` to allow setting the + priority of requests made by `CronetDataSource` instances. +* OkHttp extension: + * Switch to OkHttp 4.9.1. This increases the extension's minimum SDK + version requirement from 16 to 21. +* Remove deprecated symbols: + * Remove `CastPlayer` specific playlist manipulation methods. Use + `setMediaItems`, `addMediaItems`, `removeMediaItem` and `moveMediaItem` + instead. + * Remove `Format.create` methods. Use `Format.Builder` instead. + * Remove `MediaSource.getTag`. Use `MediaSource.getMediaItem` and + `MediaItem.PlaybackProperties.tag` instead. + * Remove `PlaybackPreparer`. UI components that previously had + `setPlaybackPreparer` methods will now call `Player.prepare` by default. + If this behavior is sufficient, use of `PlaybackPreparer` can be removed + from application code without replacement. For custom preparation logic, + use a `ForwardingPlayer` that implements custom preparation logic in + `prepare`. + * Remove `Player.Listener.onTimelineChanged(Timeline, Object, int)`. Use + `Player.Listener.onTimelineChanged(Timeline, int)` instead. The manifest + can be accessed using `Player.getCurrentManifest`. + * Remove `Player.getCurrentTag`. Use `Player.getCurrentMediaItem` and + `MediaItem.PlaybackProperties.tag` instead. + * Remove `Player.getPlaybackError`. Use `Player.getPlayerError` instead. + * Remove `PlayerNotificationManager` constructors and `createWith` + methods. Use `PlayerNotificationManager.Builder` instead. + * Remove `PlayerNotificationManager.setNotificationListener`. Use + `PlayerNotificationManager.Builder.setNotificationListener` instead. + * Remove `PlayerNotificationManager` `setUseNavigationActions` and + `setUseNavigationActionsInCompactView`. Use `setUseNextAction`, + `setUsePreviousAction`, `setUseNextActionInCompactView` and + `setUsePreviousActionInCompactView` instead. + * Remove `setRewindIncrementMs` and `setFastForwardIncrementMs` from UI + components. These increments can be customized by configuring the + `Player` (see `setSeekBackIncrementMs` and `setSeekForwardIncrementMs` + in `SimpleExoPlayer.Builder`), or by using a `ForwardingPlayer` that + overrides `getSeekBackIncrement`, `seekBack`, `getSeekForwardIncrement` + and `seekForward`. The rewind and fast forward buttons can be disabled + by using a `ForwardingPlayer` that removes `COMMAND_SEEK_BACK` and + `COMMAND_SEEK_FORWARD` from the available commands. + * Remove `Timeline.getWindow(int, Window, boolean)`. Use + `Timeline.getWindow(int, Window)` instead, which will always set tags. + ### 2.14.2 (2021-07-20) * Core Library: @@ -37,7 +182,7 @@ `EXT-X-MAP` tag in a media playlist, would not be loaded when encountered during playback ([#9004](https://github.com/google/ExoPlayer/issues/9004)). - * Forward the FRAME-RATE value from the master playlist to renditions. + * Forward the `FRAME-RATE` value from the master playlist to renditions. ([#8960](https://github.com/google/ExoPlayer/issues/8960)). * Fix issue where HLS events would start at positions greater than specified by an `EXT-X-START` tag when placed in a playlist @@ -56,9 +201,10 @@ * Fix handling of emsg messages with an unset duration ([#9123](https://github.com/google/ExoPlayer/issues/9123)). * UI: - * Add `PendingIntent.FLAG_IMMUTABLE` flag when creating a broadcast intent - in `PlayerNotificationManager`. This is required to avoid an error on - Android 12. + * Add `PendingIntent.FLAG_IMMUTABLE` when creating broadcast intents in + `PlayerNotificationManager`. This is required by a + [behaviour change](https://developer.android.com/about/versions/12/behavior-changes-12#pending-intent-mutability) + in Android 12. * Fix focusability of `StyledPlayerView` and `StyledPlayerControlView` popup menus on API levels prior to 26 ([#9061](https://github.com/google/ExoPlayer/issues/9061)). @@ -70,7 +216,7 @@ * Don't propagate `AttributeSet` from `SubtitleView` constructor into `CanvasSubtitleOutput`. Just passing the `Context` is enough, and ensures programmatic changes to the `SubtitleView` will propagate down. -* RTSP +* RTSP: * Fix session description (SDP) parsing to use a HashMap-like behaviour for duplicated attributes. ([#9014](https://github.com/google/ExoPlayer/issues/9014)). diff --git a/build.gradle b/build.gradle index e9a8ce9c68e..3092a9a7c73 100644 --- a/build.gradle +++ b/build.gradle @@ -14,16 +14,17 @@ buildscript { repositories { google() - jcenter() + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:4.0.1' - classpath 'com.google.android.gms:strict-version-matcher-plugin:1.2.1' + classpath 'com.android.tools.build:gradle:4.2.1' + classpath 'com.google.android.gms:strict-version-matcher-plugin:1.2.2' } } allprojects { repositories { google() + mavenCentral() jcenter() } if (it.hasProperty('externalBuildDir')) { diff --git a/constants.gradle b/constants.gradle index 68ce165ecc4..6f8f0602243 100644 --- a/constants.gradle +++ b/constants.gradle @@ -13,38 +13,43 @@ // limitations under the License. project.ext { // ExoPlayer version and version code. - releaseVersion = '2.14.2' - releaseVersionCode = 2014002 + releaseVersion = '2.15.0' + releaseVersionCode = 2015000 minSdkVersion = 16 appTargetSdkVersion = 29 - targetSdkVersion = 28 // TODO: Bump once b/143232359 is resolved. Also fix TODOs in UtilTest. + targetSdkVersion = 30 compileSdkVersion = 30 dexmakerVersion = '2.28.1' junitVersion = '4.13.2' + // Use the same Guava version as the Android repo: + // https://cs.android.com/android/platform/superproject/+/master:external/guava/METADATA guavaVersion = '27.1-android' - mockitoVersion = '2.28.2' + mockitoVersion = '3.4.0' mockWebServerVersion = '3.12.0' - robolectricVersion = '4.5' - checkerframeworkVersion = '3.3.0' + robolectricVersion = '4.6.1' + // Keep this in sync with Google's internal Checker Framework version. + checkerframeworkVersion = '3.5.0' checkerframeworkCompatVersion = '2.5.0' jsr305Version = '3.0.2' - kotlinAnnotationsVersion = '1.3.70' + kotlinAnnotationsVersion = '1.5.20' androidxAnnotationVersion = '1.2.0' - androidxAppCompatVersion = '1.1.0' + androidxAppCompatVersion = '1.3.0' androidxCollectionVersion = '1.1.0' androidxCoreVersion = '1.3.2' androidxFuturesVersion = '1.1.0' - androidxMediaVersion = '1.2.1' - androidxMedia2Version = '1.1.2' - androidxMultidexVersion = '2.0.0' - androidxRecyclerViewVersion = '1.1.0' + androidxMediaVersion = '1.3.1' + androidxMedia2Version = '1.1.3' + androidxMultidexVersion = '2.0.1' + androidxRecyclerViewVersion = '1.2.1' + androidxMaterialVersion = '1.3.0' androidxTestCoreVersion = '1.3.0' - androidxTestJUnitVersion = '1.1.1' + androidxTestJUnitVersion = '1.1.2' androidxTestRunnerVersion = '1.3.0' androidxTestRulesVersion = '1.3.0' androidxTestServicesStorageVersion = '1.3.0' androidxTestTruthVersion = '1.3.0' - truthVersion = '1.0' + truthVersion = '1.1.3' + okhttpVersion = '4.9.1' modulePrefix = ':' if (gradle.ext.has('exoplayerModulePrefix')) { modulePrefix += gradle.ext.exoplayerModulePrefix diff --git a/core_settings.gradle b/core_settings.gradle index 8d262c89dca..ffee74bccf8 100644 --- a/core_settings.gradle +++ b/core_settings.gradle @@ -15,65 +15,67 @@ def rootDir = file(gradle.ext.exoplayerRoot) if (!gradle.ext.has('exoplayerSettingsDir')) { gradle.ext.exoplayerSettingsDir = rootDir.getCanonicalPath() } + def modulePrefix = ':' if (gradle.ext.has('exoplayerModulePrefix')) { modulePrefix += gradle.ext.exoplayerModulePrefix } include modulePrefix + 'library' +project(modulePrefix + 'library').projectDir = new File(rootDir, 'library/all') include modulePrefix + 'library-common' +project(modulePrefix + 'library-common').projectDir = new File(rootDir, 'library/common') include modulePrefix + 'library-core' +project(modulePrefix + 'library-core').projectDir = new File(rootDir, 'library/core') include modulePrefix + 'library-dash' +project(modulePrefix + 'library-dash').projectDir = new File(rootDir, 'library/dash') include modulePrefix + 'library-extractor' +project(modulePrefix + 'library-extractor').projectDir = new File(rootDir, 'library/extractor') include modulePrefix + 'library-hls' +project(modulePrefix + 'library-hls').projectDir = new File(rootDir, 'library/hls') include modulePrefix + 'library-rtsp' +project(modulePrefix + 'library-rtsp').projectDir = new File(rootDir, 'library/rtsp') include modulePrefix + 'library-smoothstreaming' +project(modulePrefix + 'library-smoothstreaming').projectDir = new File(rootDir, 'library/smoothstreaming') include modulePrefix + 'library-transformer' +project(modulePrefix + 'library-transformer').projectDir = new File(rootDir, 'library/transformer') include modulePrefix + 'library-ui' -include modulePrefix + 'robolectricutils' -include modulePrefix + 'testutils' -include modulePrefix + 'testdata' +project(modulePrefix + 'library-ui').projectDir = new File(rootDir, 'library/ui') + include modulePrefix + 'extension-av1' +project(modulePrefix + 'extension-av1').projectDir = new File(rootDir, 'extensions/av1') include modulePrefix + 'extension-ffmpeg' +project(modulePrefix + 'extension-ffmpeg').projectDir = new File(rootDir, 'extensions/ffmpeg') include modulePrefix + 'extension-flac' +project(modulePrefix + 'extension-flac').projectDir = new File(rootDir, 'extensions/flac') include modulePrefix + 'extension-gvr' +project(modulePrefix + 'extension-gvr').projectDir = new File(rootDir, 'extensions/gvr') include modulePrefix + 'extension-ima' +project(modulePrefix + 'extension-ima').projectDir = new File(rootDir, 'extensions/ima') include modulePrefix + 'extension-cast' +project(modulePrefix + 'extension-cast').projectDir = new File(rootDir, 'extensions/cast') include modulePrefix + 'extension-cronet' +project(modulePrefix + 'extension-cronet').projectDir = new File(rootDir, 'extensions/cronet') include modulePrefix + 'extension-mediasession' +project(modulePrefix + 'extension-mediasession').projectDir = new File(rootDir, 'extensions/mediasession') include modulePrefix + 'extension-media2' +project(modulePrefix + 'extension-media2').projectDir = new File(rootDir, 'extensions/media2') include modulePrefix + 'extension-okhttp' +project(modulePrefix + 'extension-okhttp').projectDir = new File(rootDir, 'extensions/okhttp') include modulePrefix + 'extension-opus' +project(modulePrefix + 'extension-opus').projectDir = new File(rootDir, 'extensions/opus') include modulePrefix + 'extension-vp9' +project(modulePrefix + 'extension-vp9').projectDir = new File(rootDir, 'extensions/vp9') include modulePrefix + 'extension-rtmp' +project(modulePrefix + 'extension-rtmp').projectDir = new File(rootDir, 'extensions/rtmp') include modulePrefix + 'extension-leanback' +project(modulePrefix + 'extension-leanback').projectDir = new File(rootDir, 'extensions/leanback') include modulePrefix + 'extension-workmanager' +project(modulePrefix + 'extension-workmanager').projectDir = new File(rootDir, 'extensions/workmanager') -project(modulePrefix + 'library').projectDir = new File(rootDir, 'library/all') -project(modulePrefix + 'library-common').projectDir = new File(rootDir, 'library/common') -project(modulePrefix + 'library-core').projectDir = new File(rootDir, 'library/core') -project(modulePrefix + 'library-dash').projectDir = new File(rootDir, 'library/dash') -project(modulePrefix + 'library-extractor').projectDir = new File(rootDir, 'library/extractor') -project(modulePrefix + 'library-hls').projectDir = new File(rootDir, 'library/hls') -project(modulePrefix + 'library-rtsp').projectDir = new File(rootDir, 'library/rtsp') -project(modulePrefix + 'library-smoothstreaming').projectDir = new File(rootDir, 'library/smoothstreaming') -project(modulePrefix + 'library-transformer').projectDir = new File(rootDir, 'library/transformer') -project(modulePrefix + 'library-ui').projectDir = new File(rootDir, 'library/ui') +include modulePrefix + 'robolectricutils' project(modulePrefix + 'robolectricutils').projectDir = new File(rootDir, 'robolectricutils') -project(modulePrefix + 'testutils').projectDir = new File(rootDir, 'testutils') +include modulePrefix + 'testdata' project(modulePrefix + 'testdata').projectDir = new File(rootDir, 'testdata') -project(modulePrefix + 'extension-av1').projectDir = new File(rootDir, 'extensions/av1') -project(modulePrefix + 'extension-ffmpeg').projectDir = new File(rootDir, 'extensions/ffmpeg') -project(modulePrefix + 'extension-flac').projectDir = new File(rootDir, 'extensions/flac') -project(modulePrefix + 'extension-gvr').projectDir = new File(rootDir, 'extensions/gvr') -project(modulePrefix + 'extension-ima').projectDir = new File(rootDir, 'extensions/ima') -project(modulePrefix + 'extension-cast').projectDir = new File(rootDir, 'extensions/cast') -project(modulePrefix + 'extension-cronet').projectDir = new File(rootDir, 'extensions/cronet') -project(modulePrefix + 'extension-mediasession').projectDir = new File(rootDir, 'extensions/mediasession') -project(modulePrefix + 'extension-media2').projectDir = new File(rootDir, 'extensions/media2') -project(modulePrefix + 'extension-okhttp').projectDir = new File(rootDir, 'extensions/okhttp') -project(modulePrefix + 'extension-opus').projectDir = new File(rootDir, 'extensions/opus') -project(modulePrefix + 'extension-vp9').projectDir = new File(rootDir, 'extensions/vp9') -project(modulePrefix + 'extension-rtmp').projectDir = new File(rootDir, 'extensions/rtmp') -project(modulePrefix + 'extension-leanback').projectDir = new File(rootDir, 'extensions/leanback') -project(modulePrefix + 'extension-workmanager').projectDir = new File(rootDir, 'extensions/workmanager') +include modulePrefix + 'testutils' +project(modulePrefix + 'testutils').projectDir = new File(rootDir, 'testutils') diff --git a/demos/cast/build.gradle b/demos/cast/build.gradle index 8636c71ab0e..2539e777c11 100644 --- a/demos/cast/build.gradle +++ b/demos/cast/build.gradle @@ -61,8 +61,8 @@ dependencies { implementation project(modulePrefix + 'extension-cast') implementation 'androidx.appcompat:appcompat:' + androidxAppCompatVersion implementation 'androidx.multidex:multidex:' + androidxMultidexVersion - implementation 'androidx.recyclerview:recyclerview:1.1.0' - implementation 'com.google.android.material:material:1.2.1' + implementation 'androidx.recyclerview:recyclerview:' + androidxRecyclerViewVersion + implementation 'com.google.android.material:material:' + androidxMaterialVersion } apply plugin: 'com.google.android.gms.strict-version-matcher-plugin' diff --git a/demos/cast/src/main/AndroidManifest.xml b/demos/cast/src/main/AndroidManifest.xml index 6bb16ed734b..ebaab7bb240 100644 --- a/demos/cast/src/main/AndroidManifest.xml +++ b/demos/cast/src/main/AndroidManifest.xml @@ -28,7 +28,7 @@ - - - - diff --git a/demos/main/src/main/java/com/google/android/exoplayer2/demo/DemoUtil.java b/demos/main/src/main/java/com/google/android/exoplayer2/demo/DemoUtil.java index 080387db7e1..2d3f606b8a0 100644 --- a/demos/main/src/main/java/com/google/android/exoplayer2/demo/DemoUtil.java +++ b/demos/main/src/main/java/com/google/android/exoplayer2/demo/DemoUtil.java @@ -23,7 +23,7 @@ import com.google.android.exoplayer2.database.DatabaseProvider; import com.google.android.exoplayer2.database.ExoDatabaseProvider; import com.google.android.exoplayer2.ext.cronet.CronetDataSource; -import com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper; +import com.google.android.exoplayer2.ext.cronet.CronetUtil; import com.google.android.exoplayer2.offline.ActionFileUpgradeUtil; import com.google.android.exoplayer2.offline.DefaultDownloadIndex; import com.google.android.exoplayer2.offline.DownloadManager; @@ -44,6 +44,8 @@ import java.net.CookiePolicy; import java.util.concurrent.Executors; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.chromium.net.CronetEngine; /** Utility methods for the demo app. */ public final class DemoUtil { @@ -102,11 +104,16 @@ public static synchronized HttpDataSource.Factory getHttpDataSourceFactory(Conte if (httpDataSourceFactory == null) { if (USE_CRONET_FOR_NETWORKING) { context = context.getApplicationContext(); - CronetEngineWrapper cronetEngineWrapper = - new CronetEngineWrapper(context, USER_AGENT, /* preferGMSCoreCronet= */ false); - httpDataSourceFactory = - new CronetDataSource.Factory(cronetEngineWrapper, Executors.newSingleThreadExecutor()); - } else { + @Nullable + CronetEngine cronetEngine = + CronetUtil.buildCronetEngine(context, USER_AGENT, /* preferGMSCoreCronet= */ false); + if (cronetEngine != null) { + httpDataSourceFactory = + new CronetDataSource.Factory(cronetEngine, Executors.newSingleThreadExecutor()); + } + } + if (httpDataSourceFactory == null) { + // We don't want to use Cronet, or we failed to instantiate a CronetEngine. CookieManager cookieManager = new CookieManager(); cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER); CookieHandler.setDefault(cookieManager); diff --git a/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java b/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java index 21dee820c9b..48748f2c08b 100644 --- a/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java +++ b/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java @@ -32,8 +32,8 @@ import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.RenderersFactory; import com.google.android.exoplayer2.SimpleExoPlayer; @@ -43,7 +43,6 @@ import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.DecoderInitializationException; import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException; import com.google.android.exoplayer2.offline.DownloadRequest; -import com.google.android.exoplayer2.source.BehindLiveWindowException; import com.google.android.exoplayer2.source.DefaultMediaSourceFactory; import com.google.android.exoplayer2.source.MediaSourceFactory; import com.google.android.exoplayer2.source.TrackGroupArray; @@ -413,21 +412,7 @@ private void showToast(String message) { Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show(); } - private static boolean isBehindLiveWindow(ExoPlaybackException e) { - if (e.type != ExoPlaybackException.TYPE_SOURCE) { - return false; - } - Throwable cause = e.getSourceException(); - while (cause != null) { - if (cause instanceof BehindLiveWindowException) { - return true; - } - cause = cause.getCause(); - } - return false; - } - - private class PlayerEventListener implements Player.EventListener { + private class PlayerEventListener implements Player.Listener { @Override public void onPlaybackStateChanged(@Player.State int playbackState) { @@ -438,8 +423,8 @@ public void onPlaybackStateChanged(@Player.State int playbackState) { } @Override - public void onPlayerError(@NonNull ExoPlaybackException e) { - if (isBehindLiveWindow(e)) { + public void onPlayerError(@NonNull PlaybackException error) { + if (error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) { player.seekToDefaultPosition(); player.prepare(); } else { @@ -470,35 +455,33 @@ public void onTracksChanged( } } - private class PlayerErrorMessageProvider implements ErrorMessageProvider { + private class PlayerErrorMessageProvider implements ErrorMessageProvider { @Override @NonNull - public Pair getErrorMessage(@NonNull ExoPlaybackException e) { + public Pair getErrorMessage(@NonNull PlaybackException e) { String errorString = getString(R.string.error_generic); - if (e.type == ExoPlaybackException.TYPE_RENDERER) { - Exception cause = e.getRendererException(); - if (cause instanceof DecoderInitializationException) { - // Special case for decoder initialization failures. - DecoderInitializationException decoderInitializationException = - (DecoderInitializationException) cause; - if (decoderInitializationException.codecInfo == null) { - if (decoderInitializationException.getCause() instanceof DecoderQueryException) { - errorString = getString(R.string.error_querying_decoders); - } else if (decoderInitializationException.secureDecoderRequired) { - errorString = - getString( - R.string.error_no_secure_decoder, decoderInitializationException.mimeType); - } else { - errorString = - getString(R.string.error_no_decoder, decoderInitializationException.mimeType); - } - } else { + Throwable cause = e.getCause(); + if (cause instanceof DecoderInitializationException) { + // Special case for decoder initialization failures. + DecoderInitializationException decoderInitializationException = + (DecoderInitializationException) cause; + if (decoderInitializationException.codecInfo == null) { + if (decoderInitializationException.getCause() instanceof DecoderQueryException) { + errorString = getString(R.string.error_querying_decoders); + } else if (decoderInitializationException.secureDecoderRequired) { errorString = getString( - R.string.error_instantiating_decoder, - decoderInitializationException.codecInfo.name); + R.string.error_no_secure_decoder, decoderInitializationException.mimeType); + } else { + errorString = + getString(R.string.error_no_decoder, decoderInitializationException.mimeType); } + } else { + errorString = + getString( + R.string.error_instantiating_decoder, + decoderInitializationException.codecInfo.name); } } return Pair.create(0, errorString); diff --git a/demos/main/src/main/java/com/google/android/exoplayer2/demo/SampleChooserActivity.java b/demos/main/src/main/java/com/google/android/exoplayer2/demo/SampleChooserActivity.java index a66a1e03014..c655179fe3a 100644 --- a/demos/main/src/main/java/com/google/android/exoplayer2/demo/SampleChooserActivity.java +++ b/demos/main/src/main/java/com/google/android/exoplayer2/demo/SampleChooserActivity.java @@ -23,7 +23,6 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; import android.content.res.AssetManager; import android.net.Uri; import android.os.AsyncTask; @@ -328,7 +327,8 @@ private void readPlaylistGroup(JsonReader reader, List groups) reader.nextString(); // Ignore. break; default: - throw new ParserException("Unsupported name: " + name); + throw ParserException.createForMalformedManifest( + "Unsupported name: " + name, /* cause= */ null); } } reader.endObject(); @@ -416,7 +416,8 @@ private PlaylistHolder readEntry(JsonReader reader, boolean insidePlaylist) thro reader.endArray(); break; default: - throw new ParserException("Unsupported attribute name: " + name); + throw ParserException.createForMalformedManifest( + "Unsupported attribute name: " + name, /* cause= */ null); } } reader.endObject(); diff --git a/demos/surface/src/main/AndroidManifest.xml b/demos/surface/src/main/AndroidManifest.xml index 5fd28909152..fab5b2070cf 100644 --- a/demos/surface/src/main/AndroidManifest.xml +++ b/demos/surface/src/main/AndroidManifest.xml @@ -15,14 +15,18 @@ --> - + + + + + @@ -38,5 +42,7 @@ + + diff --git a/docs/_data/navigation.yml b/docs/_data/navigation.yml index 612e2fd37ff..de9ea36f995 100644 --- a/docs/_data/navigation.yml +++ b/docs/_data/navigation.yml @@ -45,6 +45,8 @@ en: url: retrieving-metadata.html - title: Live streaming url: live-streaming.html + - title: Network stacks + url: network-stacks.html - title: Debug logging url: debug-logging.html - title: Analytics diff --git a/docs/dash.md b/docs/dash.md index 8b3ef2571ed..01bf698455c 100644 --- a/docs/dash.md +++ b/docs/dash.md @@ -39,7 +39,7 @@ directly to the player instead of a `MediaItem`. ~~~ // Create a data source factory. -DataSource.Factory dataSourceFactory = new DefaultHttpDataSourceFactory(); +DataSource.Factory dataSourceFactory = new DefaultHttpDataSource.Factory(); // Create a DASH media source pointing to a DASH manifest uri. MediaSource mediaSource = new DashMediaSource.Factory(dataSourceFactory) diff --git a/docs/doc/reference/allclasses-index.html b/docs/doc/reference/allclasses-index.html index 41f2dff59c4..661b1989966 100644 --- a/docs/doc/reference/allclasses-index.html +++ b/docs/doc/reference/allclasses-index.html @@ -25,7 +25,7 @@ catch(err) { } //--> -var data = {"i0":2,"i1":32,"i2":2,"i3":2,"i4":2,"i5":2,"i6":2,"i7":2,"i8":32,"i9":2,"i10":2,"i11":2,"i12":2,"i13":2,"i14":2,"i15":2,"i16":2,"i17":2,"i18":2,"i19":2,"i20":2,"i21":2,"i22":2,"i23":2,"i24":2,"i25":2,"i26":2,"i27":2,"i28":2,"i29":2,"i30":2,"i31":2,"i32":2,"i33":2,"i34":2,"i35":2,"i36":2,"i37":2,"i38":2,"i39":2,"i40":2,"i41":2,"i42":2,"i43":2,"i44":2,"i45":1,"i46":2,"i47":2,"i48":1,"i49":2,"i50":2,"i51":1,"i52":2,"i53":2,"i54":2,"i55":2,"i56":2,"i57":2,"i58":32,"i59":2,"i60":2,"i61":32,"i62":1,"i63":1,"i64":2,"i65":8,"i66":32,"i67":2,"i68":32,"i69":2,"i70":1,"i71":2,"i72":2,"i73":2,"i74":2,"i75":1,"i76":2,"i77":32,"i78":2,"i79":1,"i80":32,"i81":2,"i82":2,"i83":2,"i84":2,"i85":2,"i86":2,"i87":1,"i88":32,"i89":2,"i90":2,"i91":8,"i92":2,"i93":2,"i94":2,"i95":2,"i96":2,"i97":1,"i98":1,"i99":1,"i100":2,"i101":8,"i102":1,"i103":2,"i104":1,"i105":8,"i106":8,"i107":1,"i108":32,"i109":8,"i110":8,"i111":2,"i112":2,"i113":1,"i114":1,"i115":2,"i116":2,"i117":2,"i118":2,"i119":2,"i120":2,"i121":2,"i122":2,"i123":2,"i124":2,"i125":8,"i126":2,"i127":2,"i128":2,"i129":2,"i130":2,"i131":1,"i132":2,"i133":1,"i134":2,"i135":1,"i136":1,"i137":2,"i138":2,"i139":2,"i140":2,"i141":2,"i142":2,"i143":2,"i144":2,"i145":32,"i146":32,"i147":32,"i148":32,"i149":32,"i150":32,"i151":32,"i152":32,"i153":32,"i154":32,"i155":32,"i156":32,"i157":32,"i158":32,"i159":32,"i160":32,"i161":32,"i162":32,"i163":32,"i164":32,"i165":32,"i166":32,"i167":32,"i168":1,"i169":8,"i170":1,"i171":2,"i172":2,"i173":2,"i174":8,"i175":2,"i176":2,"i177":2,"i178":32,"i179":1,"i180":2,"i181":32,"i182":2,"i183":2,"i184":1,"i185":1,"i186":2,"i187":2,"i188":1,"i189":1,"i190":2,"i191":2,"i192":32,"i193":2,"i194":2,"i195":2,"i196":2,"i197":2,"i198":2,"i199":2,"i200":2,"i201":2,"i202":1,"i203":1,"i204":1,"i205":2,"i206":2,"i207":2,"i208":1,"i209":1,"i210":2,"i211":2,"i212":8,"i213":32,"i214":1,"i215":2,"i216":2,"i217":2,"i218":2,"i219":2,"i220":2,"i221":1,"i222":2,"i223":2,"i224":2,"i225":1,"i226":2,"i227":2,"i228":8,"i229":1,"i230":2,"i231":1,"i232":2,"i233":2,"i234":2,"i235":8,"i236":2,"i237":2,"i238":32,"i239":2,"i240":2,"i241":32,"i242":2,"i243":32,"i244":32,"i245":32,"i246":1,"i247":1,"i248":2,"i249":2,"i250":2,"i251":2,"i252":8,"i253":2,"i254":2,"i255":1,"i256":2,"i257":2,"i258":8,"i259":1,"i260":2,"i261":1,"i262":2,"i263":1,"i264":1,"i265":1,"i266":1,"i267":2,"i268":2,"i269":2,"i270":2,"i271":8,"i272":2,"i273":2,"i274":2,"i275":32,"i276":32,"i277":2,"i278":1,"i279":2,"i280":2,"i281":2,"i282":8,"i283":2,"i284":32,"i285":8,"i286":2,"i287":32,"i288":32,"i289":2,"i290":8,"i291":2,"i292":2,"i293":1,"i294":2,"i295":8,"i296":32,"i297":2,"i298":2,"i299":2,"i300":2,"i301":2,"i302":2,"i303":2,"i304":2,"i305":2,"i306":2,"i307":2,"i308":2,"i309":2,"i310":2,"i311":2,"i312":2,"i313":2,"i314":8,"i315":32,"i316":2,"i317":2,"i318":2,"i319":2,"i320":2,"i321":2,"i322":2,"i323":2,"i324":2,"i325":2,"i326":2,"i327":2,"i328":2,"i329":2,"i330":2,"i331":2,"i332":2,"i333":2,"i334":1,"i335":2,"i336":2,"i337":32,"i338":2,"i339":2,"i340":2,"i341":2,"i342":2,"i343":2,"i344":2,"i345":2,"i346":2,"i347":2,"i348":2,"i349":2,"i350":2,"i351":2,"i352":2,"i353":32,"i354":2,"i355":2,"i356":32,"i357":1,"i358":2,"i359":2,"i360":32,"i361":32,"i362":2,"i363":1,"i364":1,"i365":1,"i366":1,"i367":8,"i368":2,"i369":1,"i370":8,"i371":1,"i372":2,"i373":1,"i374":2,"i375":2,"i376":2,"i377":2,"i378":8,"i379":2,"i380":2,"i381":2,"i382":1,"i383":8,"i384":32,"i385":1,"i386":2,"i387":1,"i388":1,"i389":1,"i390":2,"i391":2,"i392":2,"i393":2,"i394":2,"i395":2,"i396":1,"i397":2,"i398":2,"i399":2,"i400":2,"i401":1,"i402":2,"i403":2,"i404":2,"i405":1,"i406":32,"i407":2,"i408":8,"i409":32,"i410":1,"i411":1,"i412":2,"i413":1,"i414":2,"i415":2,"i416":2,"i417":2,"i418":2,"i419":2,"i420":2,"i421":2,"i422":2,"i423":2,"i424":1,"i425":1,"i426":2,"i427":2,"i428":32,"i429":2,"i430":1,"i431":1,"i432":1,"i433":1,"i434":2,"i435":8,"i436":32,"i437":1,"i438":1,"i439":1,"i440":2,"i441":1,"i442":1,"i443":1,"i444":1,"i445":2,"i446":2,"i447":2,"i448":8,"i449":32,"i450":1,"i451":2,"i452":1,"i453":1,"i454":32,"i455":2,"i456":2,"i457":2,"i458":1,"i459":2,"i460":1,"i461":1,"i462":1,"i463":2,"i464":2,"i465":2,"i466":2,"i467":2,"i468":2,"i469":2,"i470":2,"i471":2,"i472":2,"i473":2,"i474":2,"i475":2,"i476":2,"i477":2,"i478":2,"i479":2,"i480":2,"i481":2,"i482":2,"i483":2,"i484":2,"i485":8,"i486":2,"i487":2,"i488":2,"i489":2,"i490":2,"i491":1,"i492":2,"i493":2,"i494":2,"i495":2,"i496":2,"i497":2,"i498":2,"i499":2,"i500":2,"i501":1,"i502":2,"i503":2,"i504":2,"i505":2,"i506":8,"i507":2,"i508":2,"i509":2,"i510":8,"i511":2,"i512":2,"i513":32,"i514":1,"i515":2,"i516":2,"i517":2,"i518":2,"i519":2,"i520":8,"i521":2,"i522":2,"i523":32,"i524":32,"i525":2,"i526":2,"i527":2,"i528":2,"i529":2,"i530":2,"i531":2,"i532":2,"i533":2,"i534":2,"i535":2,"i536":2,"i537":2,"i538":2,"i539":2,"i540":2,"i541":32,"i542":2,"i543":2,"i544":2,"i545":2,"i546":8,"i547":2,"i548":2,"i549":2,"i550":2,"i551":2,"i552":2,"i553":2,"i554":2,"i555":2,"i556":2,"i557":1,"i558":1,"i559":2,"i560":2,"i561":1,"i562":2,"i563":1,"i564":2,"i565":2,"i566":2,"i567":2,"i568":1,"i569":2,"i570":2,"i571":2,"i572":32,"i573":2,"i574":2,"i575":2,"i576":2,"i577":2,"i578":2,"i579":32,"i580":2,"i581":2,"i582":8,"i583":1,"i584":1,"i585":1,"i586":1,"i587":8,"i588":8,"i589":1,"i590":2,"i591":2,"i592":2,"i593":2,"i594":1,"i595":1,"i596":2,"i597":8,"i598":1,"i599":8,"i600":32,"i601":8,"i602":8,"i603":2,"i604":2,"i605":2,"i606":2,"i607":2,"i608":2,"i609":2,"i610":2,"i611":1,"i612":2,"i613":2,"i614":2,"i615":8,"i616":2,"i617":2,"i618":2,"i619":2,"i620":2,"i621":2,"i622":2,"i623":2,"i624":8,"i625":1,"i626":2,"i627":2,"i628":2,"i629":2,"i630":2,"i631":2,"i632":2,"i633":2,"i634":2,"i635":1,"i636":1,"i637":1,"i638":1,"i639":2,"i640":1,"i641":1,"i642":2,"i643":1,"i644":8,"i645":1,"i646":2,"i647":1,"i648":2,"i649":2,"i650":2,"i651":2,"i652":2,"i653":2,"i654":2,"i655":2,"i656":2,"i657":1,"i658":2,"i659":2,"i660":2,"i661":32,"i662":2,"i663":2,"i664":1,"i665":1,"i666":1,"i667":2,"i668":1,"i669":1,"i670":2,"i671":8,"i672":2,"i673":2,"i674":8,"i675":1,"i676":2,"i677":8,"i678":8,"i679":2,"i680":2,"i681":1,"i682":8,"i683":2,"i684":2,"i685":2,"i686":2,"i687":2,"i688":2,"i689":2,"i690":2,"i691":2,"i692":1,"i693":1,"i694":2,"i695":2,"i696":2,"i697":32,"i698":2,"i699":2,"i700":2,"i701":2,"i702":1,"i703":1,"i704":2,"i705":1,"i706":2,"i707":2,"i708":1,"i709":1,"i710":1,"i711":2,"i712":1,"i713":1,"i714":32,"i715":1,"i716":1,"i717":1,"i718":1,"i719":1,"i720":2,"i721":1,"i722":1,"i723":2,"i724":1,"i725":2,"i726":2,"i727":8,"i728":32,"i729":2,"i730":1,"i731":1,"i732":1,"i733":2,"i734":1,"i735":2,"i736":2,"i737":2,"i738":2,"i739":2,"i740":2,"i741":32,"i742":2,"i743":32,"i744":2,"i745":2,"i746":2,"i747":2,"i748":2,"i749":2,"i750":2,"i751":2,"i752":1,"i753":32,"i754":2,"i755":2,"i756":2,"i757":32,"i758":2,"i759":2,"i760":2,"i761":2,"i762":2,"i763":2,"i764":2,"i765":8,"i766":2,"i767":2,"i768":2,"i769":1,"i770":2,"i771":2,"i772":2,"i773":2,"i774":8,"i775":2,"i776":1,"i777":2,"i778":2,"i779":2,"i780":2,"i781":2,"i782":2,"i783":2,"i784":2,"i785":2,"i786":2,"i787":1,"i788":1,"i789":1,"i790":2,"i791":2,"i792":2,"i793":2,"i794":2,"i795":1,"i796":1,"i797":32,"i798":2,"i799":2,"i800":32,"i801":32,"i802":1,"i803":2,"i804":1,"i805":32,"i806":32,"i807":32,"i808":2,"i809":32,"i810":32,"i811":32,"i812":2,"i813":1,"i814":1,"i815":2,"i816":1,"i817":2,"i818":1,"i819":1,"i820":2,"i821":2,"i822":1,"i823":1,"i824":1,"i825":32,"i826":32,"i827":2,"i828":32,"i829":2,"i830":2,"i831":2,"i832":2,"i833":8,"i834":2,"i835":2,"i836":2,"i837":2,"i838":2,"i839":1,"i840":1,"i841":2,"i842":2,"i843":2,"i844":2,"i845":2,"i846":2,"i847":2,"i848":2,"i849":2,"i850":2,"i851":2,"i852":8,"i853":1,"i854":32,"i855":32,"i856":1,"i857":1,"i858":32,"i859":32,"i860":32,"i861":32,"i862":2,"i863":1,"i864":2,"i865":2,"i866":32,"i867":2,"i868":2,"i869":2,"i870":2,"i871":32,"i872":2,"i873":1,"i874":2,"i875":2,"i876":1,"i877":2,"i878":2,"i879":2,"i880":2,"i881":2,"i882":2,"i883":2,"i884":2,"i885":1,"i886":1,"i887":2,"i888":2,"i889":2,"i890":8,"i891":2,"i892":2,"i893":2,"i894":1,"i895":8,"i896":1,"i897":32,"i898":32,"i899":1,"i900":1,"i901":2,"i902":1,"i903":2,"i904":2,"i905":2,"i906":2,"i907":2,"i908":2,"i909":2,"i910":2,"i911":2,"i912":2,"i913":2,"i914":2,"i915":2,"i916":1,"i917":1,"i918":2,"i919":1,"i920":2,"i921":1,"i922":1,"i923":2,"i924":1,"i925":2,"i926":1,"i927":1,"i928":1,"i929":1,"i930":2,"i931":2,"i932":1,"i933":2,"i934":2,"i935":2,"i936":2,"i937":2,"i938":2,"i939":2,"i940":2,"i941":2,"i942":2,"i943":2,"i944":2,"i945":2,"i946":2,"i947":2,"i948":2,"i949":2,"i950":2,"i951":2,"i952":2,"i953":2,"i954":2,"i955":1,"i956":2,"i957":2,"i958":1,"i959":1,"i960":1,"i961":1,"i962":1,"i963":1,"i964":1,"i965":1,"i966":1,"i967":2,"i968":2,"i969":1,"i970":2,"i971":2,"i972":2,"i973":2,"i974":2,"i975":2,"i976":2,"i977":2,"i978":2,"i979":1,"i980":1,"i981":2,"i982":2,"i983":2,"i984":2,"i985":2,"i986":8,"i987":2,"i988":2,"i989":2,"i990":2,"i991":2,"i992":2,"i993":2,"i994":2,"i995":2,"i996":1,"i997":1,"i998":1,"i999":2,"i1000":32,"i1001":2,"i1002":1,"i1003":1,"i1004":8,"i1005":1,"i1006":2,"i1007":2,"i1008":2,"i1009":32,"i1010":2,"i1011":2,"i1012":2,"i1013":2,"i1014":1,"i1015":2,"i1016":2,"i1017":2,"i1018":2,"i1019":2,"i1020":2,"i1021":2,"i1022":32,"i1023":2,"i1024":32,"i1025":32,"i1026":2,"i1027":1,"i1028":2,"i1029":2,"i1030":1,"i1031":1,"i1032":2,"i1033":2,"i1034":2,"i1035":2,"i1036":2,"i1037":2,"i1038":1,"i1039":2,"i1040":1,"i1041":2,"i1042":2,"i1043":2,"i1044":2,"i1045":1,"i1046":2,"i1047":2,"i1048":32,"i1049":2,"i1050":2,"i1051":2,"i1052":1,"i1053":1,"i1054":2,"i1055":32,"i1056":1,"i1057":2,"i1058":2,"i1059":1,"i1060":2,"i1061":2,"i1062":2,"i1063":1,"i1064":2,"i1065":1,"i1066":2,"i1067":1,"i1068":2,"i1069":1,"i1070":2,"i1071":2,"i1072":1,"i1073":32,"i1074":2,"i1075":32,"i1076":1,"i1077":2,"i1078":2,"i1079":1,"i1080":32,"i1081":2,"i1082":2,"i1083":2,"i1084":2,"i1085":2,"i1086":8,"i1087":32,"i1088":8,"i1089":8,"i1090":32,"i1091":2,"i1092":2,"i1093":2,"i1094":2,"i1095":2,"i1096":2,"i1097":2,"i1098":2,"i1099":2,"i1100":2,"i1101":1,"i1102":1,"i1103":2,"i1104":1,"i1105":1,"i1106":2,"i1107":2,"i1108":2,"i1109":2,"i1110":2,"i1111":2,"i1112":2,"i1113":2,"i1114":2,"i1115":8,"i1116":2,"i1117":2,"i1118":2,"i1119":2,"i1120":2,"i1121":2,"i1122":2,"i1123":2,"i1124":32,"i1125":32,"i1126":2,"i1127":2,"i1128":2,"i1129":2,"i1130":2,"i1131":2,"i1132":2,"i1133":2,"i1134":1,"i1135":2}; +var data = {"i0":2,"i1":32,"i2":2,"i3":2,"i4":2,"i5":2,"i6":2,"i7":2,"i8":32,"i9":2,"i10":2,"i11":2,"i12":2,"i13":2,"i14":2,"i15":2,"i16":2,"i17":2,"i18":2,"i19":2,"i20":2,"i21":2,"i22":2,"i23":2,"i24":2,"i25":2,"i26":2,"i27":2,"i28":2,"i29":2,"i30":2,"i31":2,"i32":2,"i33":2,"i34":2,"i35":2,"i36":2,"i37":2,"i38":2,"i39":2,"i40":2,"i41":2,"i42":2,"i43":2,"i44":2,"i45":1,"i46":2,"i47":2,"i48":1,"i49":2,"i50":2,"i51":1,"i52":2,"i53":2,"i54":2,"i55":2,"i56":2,"i57":2,"i58":32,"i59":2,"i60":2,"i61":32,"i62":1,"i63":1,"i64":2,"i65":8,"i66":32,"i67":2,"i68":32,"i69":2,"i70":1,"i71":2,"i72":2,"i73":2,"i74":2,"i75":1,"i76":2,"i77":32,"i78":2,"i79":1,"i80":32,"i81":2,"i82":2,"i83":2,"i84":2,"i85":2,"i86":2,"i87":1,"i88":32,"i89":2,"i90":2,"i91":8,"i92":2,"i93":2,"i94":2,"i95":2,"i96":2,"i97":1,"i98":1,"i99":1,"i100":2,"i101":8,"i102":1,"i103":2,"i104":1,"i105":8,"i106":8,"i107":1,"i108":32,"i109":8,"i110":8,"i111":2,"i112":2,"i113":1,"i114":1,"i115":2,"i116":2,"i117":2,"i118":2,"i119":2,"i120":2,"i121":2,"i122":2,"i123":2,"i124":2,"i125":2,"i126":2,"i127":8,"i128":2,"i129":2,"i130":2,"i131":2,"i132":2,"i133":1,"i134":2,"i135":1,"i136":2,"i137":1,"i138":1,"i139":2,"i140":2,"i141":2,"i142":2,"i143":2,"i144":2,"i145":2,"i146":2,"i147":2,"i148":32,"i149":32,"i150":32,"i151":32,"i152":32,"i153":32,"i154":32,"i155":32,"i156":32,"i157":32,"i158":32,"i159":32,"i160":32,"i161":32,"i162":32,"i163":32,"i164":32,"i165":32,"i166":32,"i167":32,"i168":32,"i169":32,"i170":32,"i171":32,"i172":1,"i173":8,"i174":1,"i175":2,"i176":2,"i177":2,"i178":8,"i179":2,"i180":2,"i181":2,"i182":32,"i183":1,"i184":2,"i185":32,"i186":2,"i187":2,"i188":1,"i189":1,"i190":2,"i191":2,"i192":1,"i193":1,"i194":2,"i195":2,"i196":32,"i197":2,"i198":2,"i199":2,"i200":2,"i201":2,"i202":2,"i203":2,"i204":2,"i205":2,"i206":1,"i207":1,"i208":1,"i209":2,"i210":2,"i211":2,"i212":1,"i213":1,"i214":2,"i215":2,"i216":8,"i217":32,"i218":1,"i219":2,"i220":2,"i221":2,"i222":2,"i223":2,"i224":2,"i225":1,"i226":2,"i227":2,"i228":2,"i229":1,"i230":2,"i231":2,"i232":8,"i233":1,"i234":2,"i235":1,"i236":2,"i237":2,"i238":2,"i239":8,"i240":2,"i241":2,"i242":2,"i243":2,"i244":2,"i245":32,"i246":2,"i247":32,"i248":32,"i249":32,"i250":1,"i251":1,"i252":2,"i253":2,"i254":2,"i255":2,"i256":8,"i257":2,"i258":2,"i259":1,"i260":2,"i261":2,"i262":8,"i263":1,"i264":2,"i265":1,"i266":2,"i267":1,"i268":1,"i269":1,"i270":1,"i271":2,"i272":2,"i273":2,"i274":2,"i275":8,"i276":2,"i277":2,"i278":2,"i279":32,"i280":32,"i281":2,"i282":1,"i283":2,"i284":2,"i285":2,"i286":8,"i287":2,"i288":32,"i289":8,"i290":2,"i291":32,"i292":32,"i293":2,"i294":8,"i295":2,"i296":2,"i297":1,"i298":2,"i299":8,"i300":32,"i301":2,"i302":2,"i303":2,"i304":2,"i305":2,"i306":2,"i307":2,"i308":2,"i309":2,"i310":2,"i311":2,"i312":2,"i313":2,"i314":2,"i315":2,"i316":2,"i317":2,"i318":8,"i319":32,"i320":2,"i321":2,"i322":2,"i323":2,"i324":2,"i325":2,"i326":2,"i327":2,"i328":2,"i329":2,"i330":2,"i331":2,"i332":2,"i333":2,"i334":2,"i335":2,"i336":2,"i337":2,"i338":2,"i339":1,"i340":2,"i341":2,"i342":32,"i343":2,"i344":2,"i345":2,"i346":2,"i347":2,"i348":2,"i349":2,"i350":2,"i351":2,"i352":2,"i353":2,"i354":2,"i355":2,"i356":2,"i357":2,"i358":32,"i359":2,"i360":2,"i361":32,"i362":1,"i363":2,"i364":2,"i365":32,"i366":32,"i367":2,"i368":1,"i369":1,"i370":1,"i371":1,"i372":8,"i373":2,"i374":1,"i375":8,"i376":1,"i377":2,"i378":1,"i379":2,"i380":2,"i381":2,"i382":2,"i383":8,"i384":2,"i385":2,"i386":2,"i387":1,"i388":8,"i389":32,"i390":1,"i391":2,"i392":1,"i393":1,"i394":1,"i395":2,"i396":32,"i397":2,"i398":2,"i399":2,"i400":2,"i401":2,"i402":2,"i403":1,"i404":2,"i405":2,"i406":2,"i407":2,"i408":1,"i409":2,"i410":2,"i411":2,"i412":1,"i413":32,"i414":2,"i415":8,"i416":32,"i417":1,"i418":1,"i419":2,"i420":1,"i421":2,"i422":2,"i423":2,"i424":2,"i425":2,"i426":2,"i427":2,"i428":2,"i429":1,"i430":1,"i431":2,"i432":2,"i433":32,"i434":2,"i435":1,"i436":1,"i437":1,"i438":1,"i439":2,"i440":8,"i441":32,"i442":1,"i443":1,"i444":1,"i445":2,"i446":1,"i447":1,"i448":1,"i449":1,"i450":2,"i451":2,"i452":2,"i453":8,"i454":32,"i455":1,"i456":2,"i457":1,"i458":1,"i459":32,"i460":2,"i461":2,"i462":2,"i463":1,"i464":2,"i465":1,"i466":1,"i467":1,"i468":2,"i469":2,"i470":2,"i471":2,"i472":2,"i473":2,"i474":2,"i475":2,"i476":2,"i477":2,"i478":2,"i479":2,"i480":2,"i481":2,"i482":2,"i483":2,"i484":2,"i485":2,"i486":2,"i487":2,"i488":2,"i489":2,"i490":8,"i491":2,"i492":2,"i493":2,"i494":2,"i495":2,"i496":1,"i497":2,"i498":2,"i499":2,"i500":2,"i501":2,"i502":2,"i503":2,"i504":2,"i505":2,"i506":1,"i507":2,"i508":2,"i509":2,"i510":2,"i511":8,"i512":2,"i513":2,"i514":2,"i515":8,"i516":2,"i517":2,"i518":32,"i519":1,"i520":2,"i521":2,"i522":2,"i523":2,"i524":2,"i525":8,"i526":2,"i527":2,"i528":32,"i529":32,"i530":2,"i531":2,"i532":2,"i533":2,"i534":2,"i535":2,"i536":2,"i537":2,"i538":2,"i539":2,"i540":2,"i541":2,"i542":2,"i543":2,"i544":2,"i545":2,"i546":2,"i547":2,"i548":2,"i549":32,"i550":2,"i551":2,"i552":2,"i553":2,"i554":8,"i555":2,"i556":2,"i557":2,"i558":2,"i559":2,"i560":2,"i561":2,"i562":2,"i563":2,"i564":2,"i565":1,"i566":1,"i567":2,"i568":2,"i569":1,"i570":2,"i571":1,"i572":2,"i573":2,"i574":2,"i575":2,"i576":1,"i577":2,"i578":2,"i579":2,"i580":32,"i581":2,"i582":2,"i583":2,"i584":2,"i585":2,"i586":2,"i587":32,"i588":2,"i589":2,"i590":8,"i591":1,"i592":1,"i593":1,"i594":1,"i595":8,"i596":8,"i597":1,"i598":2,"i599":2,"i600":2,"i601":2,"i602":1,"i603":1,"i604":2,"i605":8,"i606":1,"i607":8,"i608":32,"i609":8,"i610":8,"i611":2,"i612":2,"i613":2,"i614":2,"i615":2,"i616":2,"i617":2,"i618":2,"i619":1,"i620":2,"i621":2,"i622":2,"i623":8,"i624":2,"i625":2,"i626":2,"i627":2,"i628":2,"i629":2,"i630":2,"i631":2,"i632":8,"i633":1,"i634":2,"i635":2,"i636":2,"i637":2,"i638":2,"i639":2,"i640":2,"i641":2,"i642":2,"i643":1,"i644":1,"i645":1,"i646":1,"i647":2,"i648":1,"i649":1,"i650":2,"i651":1,"i652":8,"i653":1,"i654":2,"i655":1,"i656":2,"i657":2,"i658":32,"i659":2,"i660":2,"i661":2,"i662":2,"i663":2,"i664":2,"i665":2,"i666":2,"i667":2,"i668":1,"i669":2,"i670":2,"i671":2,"i672":32,"i673":2,"i674":2,"i675":1,"i676":1,"i677":1,"i678":2,"i679":1,"i680":1,"i681":2,"i682":8,"i683":2,"i684":2,"i685":8,"i686":1,"i687":2,"i688":8,"i689":8,"i690":2,"i691":2,"i692":1,"i693":8,"i694":2,"i695":2,"i696":2,"i697":2,"i698":2,"i699":2,"i700":2,"i701":2,"i702":2,"i703":1,"i704":1,"i705":2,"i706":2,"i707":2,"i708":32,"i709":32,"i710":2,"i711":2,"i712":2,"i713":2,"i714":1,"i715":1,"i716":2,"i717":1,"i718":2,"i719":2,"i720":1,"i721":1,"i722":1,"i723":2,"i724":1,"i725":1,"i726":32,"i727":1,"i728":1,"i729":1,"i730":1,"i731":1,"i732":2,"i733":1,"i734":1,"i735":2,"i736":1,"i737":2,"i738":2,"i739":8,"i740":32,"i741":2,"i742":1,"i743":1,"i744":1,"i745":2,"i746":1,"i747":2,"i748":2,"i749":2,"i750":2,"i751":2,"i752":2,"i753":32,"i754":2,"i755":32,"i756":2,"i757":2,"i758":2,"i759":2,"i760":2,"i761":2,"i762":2,"i763":2,"i764":2,"i765":1,"i766":32,"i767":2,"i768":2,"i769":2,"i770":32,"i771":2,"i772":2,"i773":2,"i774":2,"i775":2,"i776":2,"i777":2,"i778":8,"i779":2,"i780":2,"i781":2,"i782":1,"i783":2,"i784":2,"i785":2,"i786":2,"i787":8,"i788":2,"i789":1,"i790":2,"i791":2,"i792":2,"i793":2,"i794":2,"i795":2,"i796":2,"i797":2,"i798":8,"i799":32,"i800":32,"i801":2,"i802":2,"i803":1,"i804":1,"i805":2,"i806":2,"i807":2,"i808":2,"i809":2,"i810":1,"i811":1,"i812":32,"i813":2,"i814":2,"i815":32,"i816":32,"i817":1,"i818":2,"i819":1,"i820":32,"i821":32,"i822":32,"i823":2,"i824":32,"i825":32,"i826":32,"i827":2,"i828":1,"i829":1,"i830":2,"i831":1,"i832":2,"i833":1,"i834":1,"i835":2,"i836":2,"i837":1,"i838":1,"i839":1,"i840":32,"i841":32,"i842":2,"i843":32,"i844":2,"i845":2,"i846":2,"i847":2,"i848":8,"i849":2,"i850":2,"i851":2,"i852":2,"i853":2,"i854":1,"i855":1,"i856":2,"i857":2,"i858":2,"i859":2,"i860":2,"i861":2,"i862":2,"i863":2,"i864":2,"i865":2,"i866":2,"i867":8,"i868":1,"i869":32,"i870":32,"i871":1,"i872":1,"i873":32,"i874":32,"i875":32,"i876":32,"i877":2,"i878":1,"i879":2,"i880":2,"i881":32,"i882":2,"i883":2,"i884":2,"i885":2,"i886":32,"i887":2,"i888":1,"i889":2,"i890":2,"i891":1,"i892":2,"i893":2,"i894":2,"i895":2,"i896":2,"i897":2,"i898":2,"i899":2,"i900":2,"i901":1,"i902":1,"i903":2,"i904":2,"i905":2,"i906":8,"i907":2,"i908":2,"i909":2,"i910":1,"i911":8,"i912":1,"i913":32,"i914":32,"i915":1,"i916":1,"i917":2,"i918":1,"i919":2,"i920":2,"i921":2,"i922":2,"i923":2,"i924":2,"i925":2,"i926":2,"i927":2,"i928":2,"i929":2,"i930":2,"i931":2,"i932":1,"i933":1,"i934":2,"i935":2,"i936":2,"i937":1,"i938":2,"i939":1,"i940":1,"i941":2,"i942":1,"i943":2,"i944":1,"i945":1,"i946":1,"i947":1,"i948":2,"i949":2,"i950":1,"i951":2,"i952":2,"i953":2,"i954":2,"i955":2,"i956":2,"i957":2,"i958":2,"i959":2,"i960":2,"i961":2,"i962":2,"i963":2,"i964":2,"i965":2,"i966":2,"i967":2,"i968":2,"i969":2,"i970":2,"i971":2,"i972":2,"i973":1,"i974":2,"i975":2,"i976":1,"i977":1,"i978":1,"i979":1,"i980":1,"i981":1,"i982":1,"i983":1,"i984":1,"i985":2,"i986":2,"i987":1,"i988":2,"i989":2,"i990":2,"i991":2,"i992":2,"i993":2,"i994":2,"i995":2,"i996":2,"i997":1,"i998":1,"i999":2,"i1000":2,"i1001":2,"i1002":2,"i1003":2,"i1004":8,"i1005":2,"i1006":2,"i1007":2,"i1008":2,"i1009":2,"i1010":2,"i1011":2,"i1012":2,"i1013":2,"i1014":1,"i1015":1,"i1016":1,"i1017":2,"i1018":32,"i1019":2,"i1020":1,"i1021":1,"i1022":8,"i1023":1,"i1024":2,"i1025":2,"i1026":2,"i1027":32,"i1028":2,"i1029":2,"i1030":2,"i1031":2,"i1032":1,"i1033":2,"i1034":2,"i1035":2,"i1036":2,"i1037":2,"i1038":2,"i1039":2,"i1040":32,"i1041":2,"i1042":32,"i1043":32,"i1044":2,"i1045":1,"i1046":2,"i1047":2,"i1048":1,"i1049":1,"i1050":2,"i1051":2,"i1052":2,"i1053":2,"i1054":2,"i1055":2,"i1056":2,"i1057":1,"i1058":2,"i1059":1,"i1060":2,"i1061":2,"i1062":2,"i1063":2,"i1064":1,"i1065":2,"i1066":2,"i1067":32,"i1068":2,"i1069":2,"i1070":2,"i1071":1,"i1072":1,"i1073":2,"i1074":32,"i1075":1,"i1076":2,"i1077":2,"i1078":1,"i1079":2,"i1080":2,"i1081":2,"i1082":1,"i1083":2,"i1084":1,"i1085":2,"i1086":1,"i1087":2,"i1088":1,"i1089":2,"i1090":2,"i1091":1,"i1092":32,"i1093":2,"i1094":32,"i1095":1,"i1096":2,"i1097":2,"i1098":1,"i1099":32,"i1100":2,"i1101":2,"i1102":2,"i1103":2,"i1104":2,"i1105":8,"i1106":32,"i1107":8,"i1108":8,"i1109":32,"i1110":2,"i1111":2,"i1112":2,"i1113":2,"i1114":2,"i1115":2,"i1116":2,"i1117":2,"i1118":2,"i1119":2,"i1120":1,"i1121":1,"i1122":2,"i1123":1,"i1124":1,"i1125":2,"i1126":2,"i1127":2,"i1128":2,"i1129":2,"i1130":2,"i1131":2,"i1132":2,"i1133":2,"i1134":8,"i1135":2,"i1136":2,"i1137":2,"i1138":2,"i1139":2,"i1140":2,"i1141":2,"i1142":32,"i1143":32,"i1144":2,"i1145":2,"i1146":2,"i1147":2,"i1148":2,"i1149":2,"i1150":2,"i1151":2,"i1152":1,"i1153":2}; var tabs = {65535:["t0","All Classes"],1:["t1","Interface Summary"],2:["t2","Class Summary"],8:["t4","Exception Summary"],32:["t6","Annotation Types Summary"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -871,69 +871,81 @@

All Classes

+BaseUrl + +
A base URL, as defined by ISO 23009-1, 2nd edition, 5.6.
+ + + +BaseUrlExclusionList + +
Holds the state of excluded base URLs to be used to select a base URL based on these exclusions.
+ + + BehindLiveWindowException
Thrown when a live playback falls behind the available media window.
- + BinaryFrame
Binary ID3 frame.
- + BinarySearchSeeker
A seeker that supports seeking within a stream by searching for the target frame using binary search.
- + BinarySearchSeeker.BinarySearchSeekMap - + BinarySearchSeeker.DefaultSeekTimestampConverter
A BinarySearchSeeker.SeekTimestampConverter implementation that returns the seek time itself as the timestamp for a seek time position.
- + BinarySearchSeeker.SeekOperationParams
Contains parameters for a pending seek operation by BinarySearchSeeker.
- + BinarySearchSeeker.SeekTimestampConverter
A converter that converts seek time in stream time into target timestamp for the BinarySearchSeeker.
- + BinarySearchSeeker.TimestampSearchResult - + BinarySearchSeeker.TimestampSeeker
A seeker that looks for a given timestamp from an input.
- + Buffer
Base class for buffers with flags.
- + Bundleable
Interface for classes whose instance can be stored in a Bundle by Bundleable.toBundle() and @@ -941,1116 +953,1128 @@

All Classes

Bundleable.Creator.
- + Bundleable.Creator<T extends Bundleable>
Interface for the static CREATOR field of Bundleable classes.
- + +BundleableUtils + +
Utilities for Bundleable.
+ + + BundledChunkExtractor
ChunkExtractor implementation that uses ExoPlayer app-bundled Extractors.
- + BundledExtractorsAdapter
ProgressiveMediaExtractor built on top of Extractor instances, whose implementation classes are bundled in the app.
- + BundledHlsMediaChunkExtractor
HlsMediaChunkExtractor implementation that uses ExoPlayer app-bundled Extractors.
- + BundleListRetriever
A Binder to transfer a list of Bundles across processes by splitting the list into multiple transactions.
- + BundleUtil
Utilities for Bundle.
- + ByteArrayDataSink
A DataSink for writing to a byte array.
- + ByteArrayDataSource
A DataSource for reading from a byte array.
- + C
Defines constants used by the library.
- + C.AudioAllowedCapturePolicy
Capture policies for audio attributes.
- + C.AudioContentType
Content types for audio attributes.
- + C.AudioFlags
Flags for audio attributes.
- + C.AudioFocusGain
Audio focus types.
- + C.AudioUsage
Usage types for audio attributes.
- + C.BufferFlags
Flags which can apply to a buffer containing a media sample.
- + C.ColorRange
Video color range.
- + C.ColorSpace
Video colorspaces.
- + C.ColorTransfer
Video color transfer characteristics.
- + C.ContentType
Represents a streaming or other media type.
- + C.CryptoMode
Crypto modes for a codec.
- + +C.DataType + +
Represents a type of data.
+ + + C.Encoding
Represents an audio encoding, or an invalid or unset value.
- + C.FormatSupport
Level of renderer support for a format.
- + C.NetworkType
Network connection type.
- + C.PcmEncoding
Represents a PCM audio encoding, or an invalid or unset value.
- + C.Projection
Video projection types.
- + C.RoleFlags
Track role flags.
- + C.SelectionFlags
Track selection flags.
- + C.StereoMode
The stereo mode for 360/3D/VR videos.
- + C.StreamType
Stream types for an AudioTrack.
- + C.VideoOutputMode
Video decoder output modes.
- + C.VideoScalingMode
Video scaling modes for MediaCodec-based renderers.
- + C.WakeMode
Mode specifying whether the player should hold a WakeLock and a WifiLock.
- + Cache
A cache that supports partial caching of resources.
- + Cache.CacheException
Thrown when an error is encountered when writing data.
- + Cache.Listener
Listener of Cache events.
- + CacheAsserts
Assertion methods for Cache.
- + CacheAsserts.RequestSet
Defines a set of data requests.
- + CacheDataSink
Writes data into a cache.
- + CacheDataSink.CacheDataSinkException
Thrown when an IOException is encountered when writing data to the sink.
- + CacheDataSink.Factory - + CacheDataSinkFactory Deprecated. - + CacheDataSource
A DataSource that reads and writes a Cache.
- + CacheDataSource.CacheIgnoredReason
Reasons the cache may be ignored.
- + CacheDataSource.EventListener
Listener of CacheDataSource events.
- + CacheDataSource.Factory - + CacheDataSource.Flags
Flags controlling the CacheDataSource's behavior.
- + CacheDataSourceFactory Deprecated. - + CachedRegionTracker
Utility class for efficiently tracking regions of data that are stored in a Cache for a given cache key.
- + CacheEvictor
Evicts data from a Cache.
- + CacheKeyFactory
Factory for cache keys.
- + CacheSpan
Defines a span of data that may or may not be cached (as indicated by CacheSpan.isCached).
- + CacheWriter
Caching related utility methods.
- + CacheWriter.ProgressListener
Receives progress updates during cache operations.
- + CameraMotionListener
Listens camera motion.
- + CameraMotionRenderer
A Renderer that parses the camera motion track.
- + CaptionStyleCompat
A compatibility wrapper for CaptioningManager.CaptionStyle.
- + CaptionStyleCompat.EdgeType
The type of edge, which may be none.
- + CapturingAudioSink
A ForwardingAudioSink that captures configuration, discontinuity and buffer events.
- + CapturingRenderersFactory
A RenderersFactory that captures interactions with the audio and video MediaCodecAdapter instances.
- + CastPlayer
Player implementation that communicates with a Cast receiver app.
- + Cea608Decoder
A SubtitleDecoder for CEA-608 (also known as "line 21 captions" and "EIA-608").
- + Cea708Decoder
A SubtitleDecoder for CEA-708 (also known as "EIA-708").
- + CeaUtil
Utility methods for handling CEA-608/708 messages.
- + ChapterFrame
Chapter information ID3 frame.
- + ChapterTocFrame
Chapter table of contents ID3 frame.
- + Chunk
An abstract base class for Loader.Loadable implementations that load chunks of data required for the playback of streams.
- + ChunkExtractor
Extracts samples and track Formats from chunks.
- + ChunkExtractor.Factory
Creates ChunkExtractor instances.
- + ChunkExtractor.TrackOutputProvider
Provides TrackOutput instances to be written to during extraction.
- + ChunkHolder
Holds a chunk or an indication that the end of the stream has been reached.
- + ChunkIndex
Defines chunks of samples within a media stream.
- + ChunkSampleStream<T extends ChunkSource>
A SampleStream that loads media in Chunks, obtained from a ChunkSource.
- + ChunkSampleStream.ReleaseCallback<T extends ChunkSource>
A callback to be notified when a sample stream has finished being released.
- + ChunkSource
A provider of Chunks for a ChunkSampleStream to load.
- + ClippingMediaPeriod
Wraps a MediaPeriod and clips its SampleStreams to provide a subsequence of their samples.
- + ClippingMediaSource
MediaSource that wraps a source and clips its timeline based on specified start/end positions.
- + ClippingMediaSource.IllegalClippingException
Thrown when a ClippingMediaSource cannot clip its wrapped source.
- + ClippingMediaSource.IllegalClippingException.Reason
The reason clipping failed.
- + Clock
An interface through which system clocks can be read and HandlerWrappers created.
- + CodecSpecificDataUtil
Provides utilities for handling various types of codec-specific data.
- + ColorInfo
Stores color info.
- + ColorParser
Parser for color expressions found in styling formats, e.g.
- + CommentFrame
Comment ID3 frame.
- + CompositeMediaSource<T>
Composite MediaSource consisting of multiple child sources.
- + CompositeSequenceableLoader
A SequenceableLoader that encapsulates multiple other SequenceableLoaders.
- + CompositeSequenceableLoaderFactory
A factory to create composite SequenceableLoaders.
- + ConcatenatingMediaSource
Concatenates multiple MediaSources.
- + ConditionVariable
An interruptible condition variable.
- + ConstantBitrateSeekMap
A SeekMap implementation that assumes the stream has a constant bitrate and consists of multiple independent frames of the same size.
- + Consumer<T>
Represents an operation that accepts a single input argument and returns no result.
- + ContainerMediaChunk
A BaseMediaChunk that uses an Extractor to decode sample data.
- + ContentDataSource
A DataSource for reading from a content URI.
- + ContentDataSource.ContentDataSourceException
Thrown when an IOException is encountered reading from a content URI.
- + ContentMetadata
Interface for an immutable snapshot of keyed metadata.
- + ContentMetadataMutations
Defines multiple mutations on metadata value which are applied atomically.
- + ControlDispatcher - -
Dispatches operations to the Player.
+Deprecated. +
Use a ForwardingPlayer or configure the player to customize operations.
- + CopyOnWriteMultiset<E>
An unordered collection of elements that allows duplicates, but also allows access to a set of unique elements.
- + CronetDataSource
DataSource without intermediate buffer based on Cronet API set using UrlRequest.
- + CronetDataSource.Factory - + CronetDataSource.OpenException
Thrown when an error is encountered when trying to open a CronetDataSource.
- + CronetDataSourceFactory Deprecated. - + CronetEngineWrapper - -
A wrapper class for a CronetEngine.
+Deprecated. +
Use CronetEngine directly.
- -CronetEngineWrapper.CronetEngineSource + +CronetUtil -
Source of CronetEngine.
+
Cronet utility methods.
- + CryptoInfo
Compatibility wrapper for MediaCodec.CryptoInfo.
- + Cue
Contains information about a specific cue, including textual content and formatting data.
- + Cue.AnchorType
The type of anchor, which may be unset.
- + Cue.Builder
A builder for Cue objects.
- + Cue.LineType
The type of line, which may be unset.
- + Cue.TextSizeType
The type of default text size for this cue, which may be unset.
- + Cue.VerticalType
The type of vertical layout for this cue, which may be unset (i.e.
- + DashChunkSource
A ChunkSource for DASH streams.
- + DashChunkSource.Factory
Factory for DashChunkSources.
- + DashDownloader
A downloader for DASH streams.
- + DashManifest
Represents a DASH media presentation description (mpd), as defined by ISO/IEC 23009-1:2014 Section 5.3.1.2.
- + DashManifestParser
A parser of media presentation description files.
- + DashManifestParser.RepresentationInfo
A parsed Representation element.
- + DashManifestStaleException
Thrown when a live playback's manifest is stale and a new manifest could not be loaded.
- + DashMediaSource
A DASH MediaSource.
- + DashMediaSource.Factory
Factory for DashMediaSources.
- + DashSegmentIndex
Indexes the segments within a media stream.
- + DashUtil
Utility methods for DASH streams.
- + DashWrappingSegmentIndex
An implementation of DashSegmentIndex that wraps a ChunkIndex parsed from a media stream.
- + DatabaseIOException
An IOException whose cause is an SQLException.
- + DatabaseProvider
Provides SQLiteDatabase instances to ExoPlayer components, which may read and write tables prefixed with DatabaseProvider.TABLE_PREFIX.
- + DataChunk
A base class for Chunk implementations where the data should be loaded into a byte[] before being consumed.
- + DataReader
Reads bytes from a data stream.
- + DataSchemeDataSource
A DataSource for reading data URLs, as defined by RFC 2397.
- + DataSink
A component to which streams of data can be written.
- + DataSink.Factory
A factory for DataSink instances.
- + DataSource
Reads data from URI-identified resources.
- + DataSource.Factory
A factory for DataSource instances.
- + DataSourceContractTest
A collection of contract tests for DataSource implementations.
- + DataSourceContractTest.FakeTransferListener
A TransferListener that only keeps track of the transferred bytes.
- + DataSourceContractTest.TestResource
Information about a resource that can be used to test the DataSource instance.
- + DataSourceContractTest.TestResource.Builder - + DataSourceException
Used to specify reason of a DataSource error.
- + DataSourceInputStream
Allows data corresponding to a given DataSpec to be read from a DataSource and consumed through an InputStream.
- + DataSpec
Defines a region of data in a resource.
- + DataSpec.Builder
Builds DataSpec instances.
- + DataSpec.Flags
The flags that apply to any request for data.
- + DataSpec.HttpMethod
HTTP methods supported by ExoPlayer HttpDataSources.
- + DebugTextViewHelper
A helper class for periodically updating a TextView with debug information obtained from a SimpleExoPlayer.
- + Decoder<I,​O,​E extends DecoderException>
A media decoder.
- + DecoderAudioRenderer<T extends Decoder<DecoderInputBuffer,​? extends SimpleOutputBuffer,​? extends DecoderException>>
Decodes and renders audio using a Decoder.
- + DecoderCounters
Maintains decoder event counts, for debugging purposes only.
- + DecoderCountersUtil
Assertions for DecoderCounters.
- + DecoderException
Thrown when a Decoder error occurs.
- + DecoderInputBuffer
Holds input for a decoder.
- + DecoderInputBuffer.BufferReplacementMode
The buffer replacement mode.
- + DecoderInputBuffer.InsufficientCapacityException
Thrown when an attempt is made to write into a DecoderInputBuffer whose DecoderInputBuffer.bufferReplacementMode is DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED and who DecoderInputBuffer.data capacity is smaller than required.
- + DecoderReuseEvaluation
The result of an evaluation to determine whether a decoder can be reused for a new input format.
- + DecoderReuseEvaluation.DecoderDiscardReasons
Possible reasons why reuse is not possible.
- + DecoderReuseEvaluation.DecoderReuseResult
Possible outcomes of the evaluation.
- + DecoderVideoRenderer
Decodes and renders video using a Decoder.
- + DecryptionException
Thrown when a non-platform component fails to decrypt data.
- + DefaultAllocator
Default implementation of Allocator.
- + DefaultAudioSink
Plays audio data.
- + DefaultAudioSink.AudioProcessorChain
Provides a chain of audio processors, which are used for any user-defined processing and applying playback parameters (if supported).
- + DefaultAudioSink.DefaultAudioProcessorChain
The default audio processor chain, which applies a (possibly empty) chain of user-defined audio processors followed by SilenceSkippingAudioProcessor and SonicAudioProcessor.
- + DefaultAudioSink.InvalidAudioTrackTimestampException
Thrown when the audio track has provided a spurious timestamp, if DefaultAudioSink.failOnSpuriousAudioTimestamp is set.
- + DefaultAudioSink.OffloadMode
Audio offload mode configuration.
- + DefaultBandwidthMeter
Estimates bandwidth by listening to data transfers.
- + DefaultBandwidthMeter.Builder
Builder for a bandwidth meter.
- + DefaultCastOptionsProvider
A convenience OptionsProvider to target the default cast receiver app.
- + DefaultCompositeSequenceableLoaderFactory
Default implementation of CompositeSequenceableLoaderFactory.
- + DefaultContentMetadata
Default implementation of ContentMetadata.
- + DefaultControlDispatcher - - +Deprecated. +
Use a ForwardingPlayer or configure the player to customize operations.
- + DefaultDashChunkSource
A default DashChunkSource implementation.
- + DefaultDashChunkSource.Factory   - + DefaultDashChunkSource.RepresentationHolder
Holds information about a snapshot of a single Representation.
- + DefaultDashChunkSource.RepresentationSegmentIterator - + DefaultDatabaseProvider
A DatabaseProvider that provides instances obtained from a SQLiteOpenHelper.
- + DefaultDataSource
A DataSource that supports multiple URI schemes.
- + DefaultDataSourceFactory
A DataSource.Factory that produces DefaultDataSource instances that delegate to DefaultHttpDataSources for non-file/asset/content URIs.
- + DefaultDownloaderFactory
Default DownloaderFactory, supporting creation of progressive, DASH, HLS and SmoothStreaming downloaders.
- + DefaultDownloadIndex
A DownloadIndex that uses SQLite to persist Downloads.
- + DefaultDrmSessionManager
A DrmSessionManager that supports playbacks using ExoMediaDrm.
- + DefaultDrmSessionManager.Builder
Builder for DefaultDrmSessionManager instances.
- + DefaultDrmSessionManager.MissingSchemeDataException - + DefaultDrmSessionManager.Mode
Determines the action to be done after a session acquired.
- + DefaultDrmSessionManagerProvider
Default implementation of DrmSessionManagerProvider.
- + DefaultExtractorInput
An ExtractorInput that wraps a DataReader.
- + DefaultExtractorsFactory
An ExtractorsFactory that provides an array of extractors for the following formats: @@ -2075,2032 +2099,2076 @@

All Classes

com.google.android.exoplayer2.ext.flac.FlacExtractor is used.
- + DefaultHlsDataSourceFactory
Default implementation of HlsDataSourceFactory.
- + DefaultHlsExtractorFactory
Default HlsExtractorFactory implementation.
- + DefaultHlsPlaylistParserFactory
Default implementation for HlsPlaylistParserFactory.
- + DefaultHlsPlaylistTracker
Default implementation for HlsPlaylistTracker.
- + DefaultHttpDataSource
An HttpDataSource that uses Android's HttpURLConnection.
- + DefaultHttpDataSource.Factory - + DefaultHttpDataSourceFactory Deprecated. - + DefaultLivePlaybackSpeedControl
A LivePlaybackSpeedControl that adjusts the playback speed using a proportional controller.
- + DefaultLivePlaybackSpeedControl.Builder - + DefaultLoadControl
The default LoadControl implementation.
- + DefaultLoadControl.Builder
Builder for DefaultLoadControl.
- + DefaultLoadErrorHandlingPolicy
Default implementation of LoadErrorHandlingPolicy.
- + +DefaultMediaDescriptionAdapter + + + + + DefaultMediaItemConverter
Default MediaItemConverter implementation.
- + DefaultMediaItemConverter
Default implementation of MediaItemConverter.
- + DefaultMediaSourceFactory
The default MediaSourceFactory implementation.
- + DefaultMediaSourceFactory.AdsLoaderProvider
Provides AdsLoader instances for media items that have ad tag URIs.
- + DefaultPlaybackSessionManager
Default PlaybackSessionManager which instantiates a new session for each window in the timeline and also for each ad within the windows.
- + DefaultRenderersFactory
Default RenderersFactory implementation.
- + DefaultRenderersFactory.ExtensionRendererMode
Modes for using extension renderers.
- + DefaultRenderersFactoryAsserts
Assertions for DefaultRenderersFactory.
- + DefaultRtpPayloadReaderFactory
Default RtpPayloadReader.Factory implementation.
- + DefaultSsChunkSource
A default SsChunkSource implementation.
- + DefaultSsChunkSource.Factory   - + DefaultTimeBar
A time bar that shows a current position, buffered position, duration and ad markers.
- + DefaultTrackNameProvider - + DefaultTrackSelector
A default TrackSelector suitable for most use cases.
- + DefaultTrackSelector.AudioTrackScore
Represents how well an audio track matches the selection DefaultTrackSelector.Parameters.
- + DefaultTrackSelector.OtherTrackScore
Represents how well any other track (non video, audio or text) matches the selection DefaultTrackSelector.Parameters.
- + DefaultTrackSelector.Parameters -
Extends TrackSelectionParameters by adding fields that are specific to DefaultTrackSelector.
+
Extends DefaultTrackSelector.Parameters by adding fields that are specific to DefaultTrackSelector.
- + DefaultTrackSelector.ParametersBuilder - + DefaultTrackSelector.SelectionOverride
A track selection override.
- + DefaultTrackSelector.TextTrackScore
Represents how well a text track matches the selection DefaultTrackSelector.Parameters.
- + DefaultTrackSelector.VideoTrackScore
Represents how well a video track matches the selection DefaultTrackSelector.Parameters.
- + DefaultTsPayloadReaderFactory
Default TsPayloadReader.Factory implementation.
- + DefaultTsPayloadReaderFactory.Flags
Flags controlling elementary stream readers' behavior.
- + Descriptor
A descriptor, as defined by ISO 23009-1, 2nd edition, 5.8.2.
- + DeviceInfo
Information about the playback device.
- + DeviceInfo.PlaybackType
Types of playback.
- + DeviceListener Deprecated. - + DolbyVisionConfig
Dolby Vision configuration data.
- + Download
Represents state of a download.
- + Download.FailureReason
Failure reasons.
- + Download.State
Download states.
- + DownloadBuilder
Builder for Download.
- + DownloadCursor
Provides random read-write access to the result set returned by a database query.
- + Downloader
Downloads and removes a piece of content.
- + Downloader.ProgressListener
Receives progress updates during download operations.
- + DownloaderFactory
Creates Downloaders for given DownloadRequests.
- + DownloadException
Thrown on an error during downloading.
- + DownloadHelper
A helper for initializing and removing downloads.
- + DownloadHelper.Callback
A callback to be notified when the DownloadHelper is prepared.
- + DownloadHelper.LiveContentUnsupportedException
Thrown at an attempt to download live content.
- + DownloadIndex
An index of Downloads.
- + DownloadManager
Manages downloads.
- + DownloadManager.Listener
Listener for DownloadManager events.
- + DownloadNotificationHelper
Helper for creating download notifications.
- + DownloadProgress
Mutable Download progress.
- + DownloadRequest
Defines content to be downloaded.
- + DownloadRequest.Builder
A builder for download requests.
- + DownloadRequest.UnsupportedRequestException
Thrown when the encoded request data belongs to an unsupported request type.
- + DownloadService
A Service for downloading media.
- + DrmInitData
Initialization data for one or more DRM schemes.
- + DrmInitData.SchemeData
Scheme initialization data.
- + DrmSession
A DRM session.
- + DrmSession.DrmSessionException
Wraps the throwable which is the cause of the error state.
- + DrmSession.State
The state of the DRM session.
- + DrmSessionEventListener
Listener of DrmSessionManager events.
- + DrmSessionEventListener.EventDispatcher
Dispatches events to DrmSessionEventListeners.
- + DrmSessionManager
Manages a DRM session.
- + DrmSessionManager.DrmSessionReference
Represents a single reference count of a DrmSession, while deliberately not giving access to the underlying session.
- + DrmSessionManagerProvider
A provider to obtain a DrmSessionManager suitable for playing the content described by a MediaItem.
- + +DrmUtil + +
DRM-related utility methods.
+ + + +DrmUtil.ErrorSource + +
Identifies the operation which caused a DRM-related error.
+ + + DtsReader
Parses a continuous DTS byte stream and extracts individual samples.
- + DtsUtil
Utility methods for parsing DTS frames.
- + DummyDataSource
A DataSource which provides no data.
- + DummyExoMediaDrm
An ExoMediaDrm that does not support any protection schemes.
- + DummyExtractorOutput
A fake ExtractorOutput implementation.
- + DummyMainThread
Helper class to simulate main/UI thread in tests.
- + DummyMainThread.TestRunnable
Runnable variant which can throw a checked exception.
- + DummySurface
A dummy Surface.
- + DummyTrackOutput
A fake TrackOutput implementation.
- + DumpableFormat
Wraps a Format to allow dumping it.
- + Dumper
Helper utility to dump field values.
- + Dumper.Dumpable
Provides custom dump method.
- + DumpFileAsserts
Helper class to enable assertions based on golden-data dump files.
- + DvbDecoder
A SimpleSubtitleDecoder for DVB subtitles.
- + DvbSubtitleReader
Parses DVB subtitle data and extracts individual frames.
- + EbmlProcessor
Defines EBML element IDs/types and processes events.
- + EbmlProcessor.ElementType
EBML element types.
- + EGLSurfaceTexture
Generates a SurfaceTexture using EGL/GLES functions.
- + EGLSurfaceTexture.GlException
A runtime exception to be thrown if some EGL operations failed.
- + EGLSurfaceTexture.SecureMode
Secure mode to be used by the EGL surface and context.
- + EGLSurfaceTexture.TextureImageListener
Listener to be called when the texture image on SurfaceTexture has been updated.
- + ElementaryStreamReader
Extracts individual samples from an elementary media stream, preserving original order.
- + EmptySampleStream
An empty SampleStream.
- + ErrorMessageProvider<T extends Throwable>
Converts throwables into error codes and user readable error messages.
- + ErrorStateDrmSession
A DrmSession that's in a terminal error state.
- + EventLogger
Logs events from Player and other core components using Log.
- + EventMessage
An Event Message (emsg) as defined in ISO 23009-1.
- + EventMessageDecoder
Decodes data encoded by EventMessageEncoder.
- + EventMessageEncoder
Encodes data that can be decoded by EventMessageDecoder.
- + EventStream
A DASH in-MPD EventStream element, as defined by ISO/IEC 23009-1, 2nd edition, section 5.10.
- + ExoDatabaseProvider
An SQLiteOpenHelper that provides instances of a standalone ExoPlayer database.
- -ExoFlags - -
A set of integer flags.
- - - -ExoFlags.Builder - -
A builder for ExoFlags instances.
- - - + ExoHostedTest
A HostActivity.HostedTest for ExoPlayer playback tests.
- + ExoMediaCrypto
Enables decoding of encrypted data using keys in a DRM session.
- + ExoMediaDrm
Used to obtain keys for decrypting protected media streams.
- + ExoMediaDrm.AppManagedProvider
Provides an ExoMediaDrm instance owned by the app.
- + ExoMediaDrm.KeyRequest
Contains data used to request keys from a license server.
- + ExoMediaDrm.KeyRequest.RequestType
Key request types.
- + ExoMediaDrm.KeyStatus
Defines the status of a key.
- + ExoMediaDrm.OnEventListener
Called when a DRM event occurs.
- + ExoMediaDrm.OnExpirationUpdateListener
Called when a session expiration update occurs.
- + ExoMediaDrm.OnKeyStatusChangeListener
Called when the keys in a DRM session change state.
- + ExoMediaDrm.Provider
Provider for ExoMediaDrm instances.
- + ExoMediaDrm.ProvisionRequest
Contains data to request a certificate from a provisioning server.
- + ExoPlaybackException
Thrown when a non locally recoverable playback failure occurs.
- + ExoPlaybackException.Type
The type of source that produced the error.
- + ExoPlayer
An extensible media player that plays MediaSources.
- + ExoPlayer.AudioComponent
The audio component of an ExoPlayer.
- + ExoPlayer.AudioOffloadListener
A listener for audio offload events.
- + ExoPlayer.Builder Deprecated. - + ExoPlayer.DeviceComponent
The device component of an ExoPlayer.
- + ExoPlayer.MetadataComponent
The metadata component of an ExoPlayer.
- + ExoPlayer.TextComponent
The text component of an ExoPlayer.
- + ExoPlayer.VideoComponent
The video component of an ExoPlayer.
- + ExoPlayerLibraryInfo
Information about the ExoPlayer library.
- + ExoPlayerTestRunner
Helper class to run an ExoPlayer test.
- + ExoPlayerTestRunner.Builder
Builder to set-up a ExoPlayerTestRunner.
- + ExoTimeoutException
A timeout of an operation on the ExoPlayer playback thread.
- + ExoTimeoutException.TimeoutOperation
The operation which produced the timeout error.
- + ExoTrackSelection - + ExoTrackSelection.Definition
Contains of a subset of selected tracks belonging to a TrackGroup.
- + ExoTrackSelection.Factory
Factory for ExoTrackSelection instances.
- + Extractor
Extracts media data from a container format.
- + Extractor.ReadResult
Result values that can be returned by Extractor.read(ExtractorInput, PositionHolder).
- + ExtractorAsserts
Assertion methods for Extractor.
- + ExtractorAsserts.AssertionConfig
A config for the assertions made (e.g.
- + ExtractorAsserts.AssertionConfig.Builder
Builder for ExtractorAsserts.AssertionConfig instances.
- + ExtractorAsserts.ExtractorFactory
A factory for Extractor instances.
- + ExtractorAsserts.SimulationConfig
A config of different environments to simulate and extractor behaviours to test.
- + ExtractorInput
Provides data to be consumed by an Extractor.
- + ExtractorOutput
Receives stream level data extracted by an Extractor.
- + ExtractorsFactory
Factory for arrays of Extractor instances.
- + ExtractorUtil
Extractor related utility methods.
- + FailOnCloseDataSink
A DataSink that can simulate caching the bytes being written to it, and then failing to persist them when FailOnCloseDataSink.close() is called.
- + FailOnCloseDataSink.Factory
Factory to create a FailOnCloseDataSink.
- + FakeAdaptiveDataSet
Fake data set emulating the data of an adaptive media source.
- + FakeAdaptiveDataSet.Factory
Factory for FakeAdaptiveDataSets.
- + FakeAdaptiveDataSet.Iterator
MediaChunkIterator for the chunks defined by a fake adaptive data set.
- + FakeAdaptiveMediaPeriod
Fake MediaPeriod that provides tracks from the given TrackGroupArray.
- + FakeAdaptiveMediaSource
Fake MediaSource that provides a given timeline.
- + FakeAudioRenderer - + FakeChunkSource
Fake ChunkSource with adaptive media chunks of a given duration.
- + FakeChunkSource.Factory
Factory for a FakeChunkSource.
- + FakeClock
Fake Clock implementation that allows to advance the time manually to trigger pending timed messages.
- + FakeDataSet
Collection of FakeDataSet.FakeData to be served by a FakeDataSource.
- + FakeDataSet.FakeData
Container of fake data to be served by a FakeDataSource.
- + FakeDataSet.FakeData.Segment
A segment of FakeDataSet.FakeData.
- + FakeDataSource
A fake DataSource capable of simulating various scenarios.
- + FakeDataSource.Factory
Factory to create a FakeDataSource.
- + FakeExoMediaDrm
A fake implementation of ExoMediaDrm for use in tests.
- + FakeExoMediaDrm.Builder
Builder for FakeExoMediaDrm instances.
- + FakeExoMediaDrm.LicenseServer
An license server implementation to interact with FakeExoMediaDrm.
- + FakeExtractorInput
A fake ExtractorInput capable of simulating various scenarios.
- + FakeExtractorInput.Builder
Builder of FakeExtractorInput instances.
- + FakeExtractorInput.SimulatedIOException
Thrown when simulating an IOException.
- + FakeExtractorOutput - + FakeMediaChunk - + FakeMediaChunkIterator - + FakeMediaClockRenderer
Fake abstract Renderer which is also a MediaClock.
- + FakeMediaPeriod
Fake MediaPeriod that provides tracks from the given TrackGroupArray.
- + FakeMediaPeriod.TrackDataFactory
A factory to create the test data for a particular track.
- + FakeMediaSource
Fake MediaSource that provides a given timeline.
- + FakeMediaSource.InitialTimeline
A forwarding timeline to provide an initial timeline for fake multi window sources.
- + FakeRenderer
Fake Renderer that supports any format with the matching track type.
- + FakeSampleStream
Fake SampleStream that outputs a given Format and any amount of items.
- + FakeSampleStream.FakeSampleStreamItem - + FakeShuffleOrder
Fake ShuffleOrder which returns a reverse order.
- + FakeTimeline
Fake Timeline which can be setup to return custom FakeTimeline.TimelineWindowDefinitions.
- + FakeTimeline.TimelineWindowDefinition
Definition used to define a FakeTimeline.
- + FakeTrackOutput
A fake TrackOutput.
- + FakeTrackOutput.Factory
Factory for FakeTrackOutput instances.
- + FakeTrackSelection
A fake ExoTrackSelection that only returns 1 fixed track, and allows querying the number of calls to its methods.
- + FakeTrackSelector - + FakeVideoRenderer - + FfmpegAudioRenderer
Decodes and renders audio using FFmpeg.
- + FfmpegDecoderException
Thrown when an FFmpeg decoder error occurs.
- + FfmpegLibrary
Configures and queries the underlying native library.
- + FileDataSource
A DataSource for reading local files.
- + FileDataSource.Factory - + FileDataSource.FileDataSourceException
Thrown when a FileDataSource encounters an error reading a file.
- + FileDataSourceFactory Deprecated. - + FileTypes
Defines common file type constants and helper methods.
- + FileTypes.Type
File types.
- + FilterableManifest<T>
A manifest that can generate copies of itself including only the streams specified by the given keys.
- + FilteringHlsPlaylistParserFactory
A HlsPlaylistParserFactory that includes only the streams identified by the given stream keys.
- + FilteringManifestParser<T extends FilterableManifest<T>>
A manifest parser that includes only the streams identified by the given stream keys.
- + FixedTrackSelection
A TrackSelection consisting of a single track.
- + FlacConstants
Defines constants used by the FLAC extractor.
- + FlacDecoder
Flac decoder.
- + FlacDecoderException
Thrown when an Flac decoder error occurs.
- + FlacExtractor
Facilitates the extraction of data from the FLAC container format.
- + FlacExtractor
Extracts data from FLAC container format.
- + FlacExtractor.Flags
Flags controlling the behavior of the extractor.
- + FlacExtractor.Flags
Flags controlling the behavior of the extractor.
- + FlacFrameReader
Reads and peeks FLAC frame elements according to the FLAC format specification.
- + FlacFrameReader.SampleNumberHolder
Holds a sample number.
- + FlacLibrary
Configures and queries the underlying native library.
- + FlacMetadataReader
Reads and peeks FLAC stream metadata elements according to the FLAC format specification.
- + FlacMetadataReader.FlacStreamMetadataHolder - + FlacSeekTableSeekMap
A SeekMap implementation for FLAC streams that contain a seek table.
- + FlacStreamMetadata
Holder for FLAC metadata.
- + FlacStreamMetadata.SeekTable
A FLAC seek table.
- + +FlagSet + +
A set of integer flags.
+ + + +FlagSet.Builder + +
A builder for FlagSet instances.
+ + + FlvExtractor
Extracts data from the FLV container format.
- + Format
Represents a media format.
- + Format.Builder
Builds Format instances.
- + FormatHolder
Holds a Format.
- + ForwardingAudioSink
An overridable AudioSink implementation forwarding all methods to another sink.
- + ForwardingExtractorInput
An overridable ExtractorInput implementation forwarding all methods to another input.
- + +ForwardingPlayer + +
A Player that forwards operations to another Player.
+ + + ForwardingTimeline
An overridable Timeline implementation forwarding all methods to another timeline.
- + FragmentedMp4Extractor
Extracts data from the FMP4 container format.
- + FragmentedMp4Extractor.Flags
Flags controlling the behavior of the extractor.
- + FrameworkMediaCrypto
An ExoMediaCrypto implementation that contains the necessary information to build or update a framework MediaCrypto.
- + FrameworkMediaDrm
An ExoMediaDrm implementation that wraps the framework MediaDrm.
- + GaplessInfoHolder
Holder for gapless playback information.
- + Gav1Decoder
Gav1 decoder.
- + Gav1DecoderException
Thrown when a libgav1 decoder error occurs.
- + Gav1Library
Configures and queries the underlying native library.
- + GeobFrame
GEOB (General Encapsulated Object) ID3 frame.
- + GlUtil
GL utilities.
- + GlUtil.Attribute
GL attribute, which can be attached to a buffer with GlUtil.Attribute.setBuffer(float[], int).
- + GlUtil.Uniform
GL uniform, which can be attached to a sampler using GlUtil.Uniform.setSamplerTexId(int, int).
- + GvrAudioProcessor Deprecated.
If you still need this component, please contact us by filing an issue on our issue tracker.
- + H262Reader
Parses a continuous H262 byte stream and extracts individual frames.
- + H263Reader
Parses an ISO/IEC 14496-2 (MPEG-4 Part 2) or ITU-T Recommendation H.263 byte stream and extracts individual frames.
- + H264Reader
Parses a continuous H264 byte stream and extracts individual frames.
- + H265Reader
Parses a continuous H.265 byte stream and extracts individual frames.
- + HandlerWrapper
An interface to call through to a Handler.
- + HandlerWrapper.Message
A message obtained from the handler.
- + HeartRating
A rating expressed as "heart" or "no heart".
- + HevcConfig
HEVC configuration data.
- + HlsDataSourceFactory
Creates DataSources for HLS playlists, encryption and media chunks.
- + HlsDownloader
A downloader for HLS streams.
- + HlsExtractorFactory
Factory for HLS media chunk extractors.
- + HlsManifest
Holds a master playlist along with a snapshot of one of its media playlists.
- + HlsMasterPlaylist
Represents an HLS master playlist.
- + HlsMasterPlaylist.Rendition
A rendition (i.e.
- + HlsMasterPlaylist.Variant
A variant (i.e.
- + HlsMediaChunkExtractor
Extracts samples and track Formats from HlsMediaChunks.
- + HlsMediaPeriod
A MediaPeriod that loads an HLS stream.
- + HlsMediaPlaylist
Represents an HLS media playlist.
- + HlsMediaPlaylist.Part
A media part.
- + HlsMediaPlaylist.PlaylistType
Type of the playlist, as defined by #EXT-X-PLAYLIST-TYPE.
- + HlsMediaPlaylist.RenditionReport
A rendition report for an alternative rendition defined in another media playlist.
- + HlsMediaPlaylist.Segment
Media segment reference.
- + HlsMediaPlaylist.SegmentBase
The base for a HlsMediaPlaylist.Segment or a HlsMediaPlaylist.Part required for playback.
- + HlsMediaPlaylist.ServerControl
Server control attributes.
- + HlsMediaSource
An HLS MediaSource.
- + HlsMediaSource.Factory
Factory for HlsMediaSources.
- + HlsMediaSource.MetadataType
The types of metadata that can be extracted from HLS streams.
- + HlsPlaylist
Represents an HLS playlist.
- + HlsPlaylistParser
HLS playlists parsing logic.
- + HlsPlaylistParser.DeltaUpdateException
Exception thrown when merging a delta update fails.
- + HlsPlaylistParserFactory
Factory for HlsPlaylist parsers.
- + HlsPlaylistTracker
Tracks playlists associated to an HLS stream and provides snapshots.
- + HlsPlaylistTracker.Factory
Factory for HlsPlaylistTracker instances.
- + HlsPlaylistTracker.PlaylistEventListener
Called on playlist loading events.
- + HlsPlaylistTracker.PlaylistResetException
Thrown when the media sequence of a new snapshot indicates the server has reset.
- + HlsPlaylistTracker.PlaylistStuckException
Thrown when a playlist is considered to be stuck due to a server side error.
- + HlsPlaylistTracker.PrimaryPlaylistListener
Listener for primary playlist changes.
- + HlsTrackMetadataEntry
Holds metadata associated to an HLS media track.
- + HlsTrackMetadataEntry.VariantInfo
Holds attributes defined in an EXT-X-STREAM-INF tag.
- + HorizontalTextInVerticalContextSpan
A styling span for horizontal text in a vertical context.
- + HostActivity
A host activity for performing playback tests.
- + HostActivity.HostedTest
Interface for tests that run inside of a HostActivity.
- + HttpDataSource
An HTTP DataSource.
- + HttpDataSource.BaseFactory
Base implementation of HttpDataSource.Factory that sets default request properties.
- + HttpDataSource.CleartextNotPermittedException
Thrown when cleartext HTTP traffic is not permitted.
- + HttpDataSource.Factory
A factory for HttpDataSource instances.
- + HttpDataSource.HttpDataSourceException
Thrown when an error is encountered when trying to read from a HttpDataSource.
- + HttpDataSource.HttpDataSourceException.Type -  + +
The type of operation that produced the error.
+ - + HttpDataSource.InvalidContentTypeException
Thrown when the content type is invalid.
- + HttpDataSource.InvalidResponseCodeException
Thrown when an attempt to open a connection results in a response code not in the 2xx range.
- + HttpDataSource.RequestProperties -
Stores HTTP request properties (aka HTTP headers) and provides methods to modify the headers - in a thread safe way to avoid the potential of creating snapshots of an inconsistent or - unintended state.
+
Stores HTTP request properties (aka HTTP headers) and provides methods to modify the headers in + a thread safe way to avoid the potential of creating snapshots of an inconsistent or unintended + state.
- + HttpDataSourceTestEnv
A JUnit Rule that creates test resources for HttpDataSource contract tests.
- + HttpMediaDrmCallback
A MediaDrmCallback that makes requests using HttpDataSource instances.
- + HttpUtil
Utility methods for HTTP.
- + IcyDecoder
Decodes ICY stream information.
- + IcyHeaders
ICY headers.
- + IcyInfo
ICY in-stream information.
- + Id3Decoder
Decodes ID3 tags.
- + Id3Decoder.FramePredicate
A predicate for determining whether individual frames should be decoded.
- + Id3Frame
Base class for ID3 frames.
- + Id3Peeker
Peeks data from the beginning of an ExtractorInput to determine if there is any ID3 tag.
- + Id3Reader
Parses ID3 data and extracts individual text information frames.
- + IllegalSeekPositionException
Thrown when an attempt is made to seek to a position that does not exist in the player's Timeline.
- + ImaAdsLoader
AdsLoader using the IMA SDK.
- + ImaAdsLoader.Builder
Builder for ImaAdsLoader.
- + IndexSeekMap
A SeekMap implementation based on a mapping between times and positions in the input stream.
- + InitializationChunk
A Chunk that uses an Extractor to decode initialization data for single track.
- + InputReaderAdapterV30
MediaParser.SeekableInputReader implementation wrapping a DataReader.
- + IntArrayQueue
Array-based unbounded queue for int primitives with amortized O(1) add and remove.
- + InternalFrame
Internal ID3 frame that is intended for use by the player.
- + JpegExtractor
Extracts JPEG image using the Exif format.
- + KeysExpiredException
Thrown when the drm keys loaded into an open session expire.
- + LanguageFeatureSpan
Marker interface for span classes that carry language features rather than style information.
- + LatmReader
Parses and extracts samples from an AAC/LATM elementary stream.
- + LeanbackPlayerAdapter
Leanback PlayerAdapter implementation for Player.
- + LeastRecentlyUsedCacheEvictor
Evicts least recently used cache files first.
- + LibflacAudioRenderer
Decodes and renders audio using the native Flac decoder.
- + Libgav1VideoRenderer
Decodes and renders video using libgav1 decoder.
- + LibopusAudioRenderer
Decodes and renders audio using the native Opus decoder.
- + LibraryLoader
Configurable loader for native libraries.
- + LibvpxVideoRenderer
Decodes and renders video using the native VP9 decoder.
- + ListenerSet<T>
A set of listeners.
- + ListenerSet.Event<T>
An event sent to a listener.
- + ListenerSet.IterationFinishedEvent<T>
An event sent to a listener when all other events sent during one Looper message queue iteration were handled by the listener.
- + LivePlaybackSpeedControl
Controls the playback speed while playing live content in order to maintain a steady target live offset.
- + LoadControl
Controls buffering of media.
- + Loader
Manages the background loading of Loader.Loadables.
- + Loader.Callback<T extends Loader.Loadable>
A callback to be notified of Loader events.
- + Loader.Loadable
An object that can be loaded using a Loader.
- + Loader.LoadErrorAction - + Loader.ReleaseCallback
A callback to be notified when a Loader has finished being released.
- + Loader.UnexpectedLoaderException
Thrown when an unexpected exception or error is encountered during loading.
- + LoaderErrorThrower
Conditionally throws errors affecting a Loader.
- + LoaderErrorThrower.Dummy
A LoaderErrorThrower that never throws.
- + LoadErrorHandlingPolicy -
Defines how errors encountered by loaders are handled.
+
A policy that defines how load errors are handled.
- + +LoadErrorHandlingPolicy.FallbackOptions + +
Holds information about the available fallback options.
+ + + +LoadErrorHandlingPolicy.FallbackSelection + +
A selected fallback option.
+ + + +LoadErrorHandlingPolicy.FallbackType + +
Fallback type.
+ + + LoadErrorHandlingPolicy.LoadErrorInfo
Holds information about a load task error.
- + LoadEventInfo
MediaSource load event information.
- + LocalMediaDrmCallback
A MediaDrmCallback that provides a fixed response to key requests.
- + Log
Wrapper around Log which allows to set the log level.
- + LongArray
An append-only, auto-growing long[].
- + LoopingMediaSource Deprecated.
To loop a MediaSource indefinitely, use Player.setRepeatMode(int) instead of this class.
- + MappingTrackSelector
Base class for TrackSelectors that first establish a mapping between TrackGroups @@ -4108,1625 +4176,1667 @@

All Classes

renderer.
- + MappingTrackSelector.MappedTrackInfo
Provides mapped track information for each renderer.
- + MaskingMediaPeriod
Media period that defers calling MediaSource.createPeriod(MediaPeriodId, Allocator, long) on a given source until MaskingMediaPeriod.createPeriod(MediaPeriodId) has been called.
- + MaskingMediaPeriod.PrepareListener
Listener for preparation events.
- + MaskingMediaSource
A MediaSource that masks the Timeline with a placeholder until the actual media structure is known.
- + MaskingMediaSource.PlaceholderTimeline
A timeline with one dynamic window with a period of indeterminate duration.
- + MatroskaExtractor
Extracts data from the Matroska and WebM container formats.
- + MatroskaExtractor.Flags
Flags controlling the behavior of the extractor.
- + MdtaMetadataEntry
Stores extensible metadata with handler type 'mdta'.
- + MediaChunk
An abstract base class for Chunks that contain media samples.
- + MediaChunkIterator
Iterator for media chunk sequences.
- + MediaClock
Tracks the progression of media time.
- + MediaCodecAdapter
Abstracts MediaCodec operations.
- + MediaCodecAdapter.Configuration
Configuration parameters for a MediaCodecAdapter.
- + MediaCodecAdapter.Factory
A factory for MediaCodecAdapter instances.
- + MediaCodecAdapter.OnFrameRenderedListener
Listener to be called when an output frame has rendered on the output surface.
- + MediaCodecAudioRenderer
Decodes and renders audio using MediaCodec and an AudioSink.
- + MediaCodecDecoderException
Thrown when a failure occurs in a MediaCodec decoder.
- + MediaCodecInfo
Information about a MediaCodec for a given mime type.
- + MediaCodecRenderer
An abstract renderer that uses MediaCodec to decode samples for rendering.
- + MediaCodecRenderer.DecoderInitializationException
Thrown when a failure occurs instantiating a decoder.
- + MediaCodecSelector
Selector of MediaCodec instances.
- + MediaCodecUtil
A utility class for querying the available codecs.
- + MediaCodecUtil.DecoderQueryException
Thrown when an error occurs querying the device for its underlying media capabilities.
- + MediaCodecVideoDecoderException
Thrown when a failure occurs in a MediaCodec video decoder.
- + MediaCodecVideoRenderer
Decodes and renders video using MediaCodec.
- + MediaCodecVideoRenderer.CodecMaxValues   - + MediaDrmCallback
Performs ExoMediaDrm key and provisioning requests.
- + MediaDrmCallbackException
Thrown when an error occurs while executing a DRM key or provisioning request.
- + MediaFormatUtil
Helper class containing utility methods for managing MediaFormat instances.
- + MediaItem
Representation of a media item.
- + MediaItem.AdsConfiguration
Configuration for playing back linear ads with a media item.
- + MediaItem.Builder
A builder for MediaItem instances.
- + MediaItem.ClippingProperties
Optionally clips the media item to a custom start and end position.
- + MediaItem.DrmConfiguration
DRM configuration for a media item.
- + MediaItem.LiveConfiguration
Live playback configuration.
- + MediaItem.PlaybackProperties
Properties for local playback.
- + MediaItem.Subtitle
Properties for a text track.
- + MediaItemConverter
Converts between MediaItem and the Cast SDK's MediaQueueItem.
- + MediaItemConverter
Converts between Media2 MediaItem and ExoPlayer MediaItem.
- + MediaLoadData
Descriptor for data being loaded or selected by a MediaSource.
- + MediaMetadata
Metadata of a MediaItem, playlist, or a combination of multiple sources of Metadata.
- + MediaMetadata.Builder
A builder for MediaMetadata instances.
- + MediaMetadata.FolderType
The folder type of the media item.
- + +MediaMetadata.PictureType + +
The picture type of the artwork.
+ + + MediaParserChunkExtractor
ChunkExtractor implemented on top of the platform's MediaParser.
- + MediaParserExtractorAdapter
ProgressiveMediaExtractor implemented on top of the platform's MediaParser.
- + MediaParserHlsMediaChunkExtractor
HlsMediaChunkExtractor implemented on top of the platform's MediaParser.
- + MediaParserUtil
Miscellaneous constants and utility methods related to the MediaParser integration.
- + MediaPeriod
Loads media corresponding to a Timeline.Period, and allows that media to be read.
- + MediaPeriod.Callback
A callback to be notified of MediaPeriod events.
- + MediaPeriodAsserts
Assertion methods for MediaPeriod.
- + MediaPeriodAsserts.FilterableManifestMediaPeriodFactory<T extends FilterableManifest<T>>
Interface to create media periods for testing based on a FilterableManifest.
- + MediaPeriodId
Identifies a specific playback of a Timeline.Period.
- + MediaSessionConnector
Connects a MediaSessionCompat to a Player.
- + MediaSessionConnector.CaptionCallback
Handles requests for enabling or disabling captions.
- + MediaSessionConnector.CommandReceiver
Receiver of media commands sent by a media controller.
- + MediaSessionConnector.CustomActionProvider
Provides a PlaybackStateCompat.CustomAction to be published and handles the action when sent by a media controller.
- + MediaSessionConnector.DefaultMediaMetadataProvider
Provides a default MediaMetadataCompat with properties and extras taken from the MediaDescriptionCompat of the MediaSessionCompat.QueueItem of the active queue item.
- + MediaSessionConnector.MediaButtonEventHandler
Handles a media button event.
- + MediaSessionConnector.MediaMetadataProvider
Provides a MediaMetadataCompat for a given player state.
- + MediaSessionConnector.PlaybackActions
Playback actions supported by the connector.
- + MediaSessionConnector.PlaybackPreparer
Interface to which playback preparation and play actions are delegated.
- + MediaSessionConnector.QueueEditor
Handles media session queue edits.
- + MediaSessionConnector.QueueNavigator
Handles queue navigation actions, and updates the media session queue by calling MediaSessionCompat.setQueue().
- + MediaSessionConnector.RatingCallback
Callback receiving a user rating for the active media item.
- + MediaSource
Defines and provides media to be played by an ExoPlayer.
- + MediaSource.MediaPeriodId
Identifier for a MediaPeriod.
- + MediaSource.MediaSourceCaller
A caller of media sources, which will be notified of source events.
- + MediaSourceEventListener
Interface for callbacks to be notified of MediaSource events.
- + MediaSourceEventListener.EventDispatcher
Dispatches events to MediaSourceEventListeners.
- + MediaSourceFactory
Factory for creating MediaSources from MediaItems.
- + MediaSourceTestRunner
A runner for MediaSource tests.
- + MergingMediaSource
Merges multiple MediaSources.
- + MergingMediaSource.IllegalMergeException
Thrown when a MergingMediaSource cannot merge its sources.
- + MergingMediaSource.IllegalMergeException.Reason
The reason the merge failed.
- + Metadata
A collection of metadata entries.
- + Metadata.Entry
A metadata entry.
- + MetadataDecoder
Decodes metadata from binary data.
- + MetadataDecoderFactory
A factory for MetadataDecoder instances.
- + MetadataInputBuffer - + MetadataOutput
Receives metadata output.
- + MetadataRenderer
A renderer for metadata.
- + MetadataRetriever
Retrieves the static metadata of MediaItems.
- + MimeTypes
Defines common MIME types and helper methods.
- + MlltFrame
MPEG location lookup table frame.
- + MotionPhotoMetadata
Metadata of a motion photo file.
- + Mp3Extractor
Extracts data from the MP3 container format.
- + Mp3Extractor.Flags
Flags controlling the behavior of the extractor.
- + Mp4Extractor
Extracts data from the MP4 container format.
- + Mp4Extractor.Flags
Flags controlling the behavior of the extractor.
- + Mp4WebvttDecoder
A SimpleSubtitleDecoder for Webvtt embedded in a Mp4 container file.
- + MpegAudioReader
Parses a continuous MPEG Audio byte stream and extracts individual frames.
- + MpegAudioUtil
Utility methods for handling MPEG audio streams.
- + MpegAudioUtil.Header
Stores the metadata for an MPEG audio frame.
- + NalUnitUtil
Utility methods for handling H.264/AVC and H.265/HEVC NAL units.
- + NalUnitUtil.PpsData
Holds data parsed from a picture parameter set NAL unit.
- + NalUnitUtil.SpsData
Holds data parsed from a sequence parameter set NAL unit.
- + NetworkTypeObserver
Observer for network type changes.
- + +NetworkTypeObserver.Config + +
Configuration for NetworkTypeObserver.
+ + + NetworkTypeObserver.Listener
A listener for network type changes.
- + NonNullApi
Annotation to declare all type usages in the annotated instance as Nonnull, unless explicitly marked with a nullable annotation.
- + NoOpCacheEvictor
Evictor that doesn't ever evict cache files.
- + NoSampleRenderer
A Renderer implementation whose track type is C.TRACK_TYPE_NONE and does not consume data from its SampleStream.
- + NotificationUtil
Utility methods for displaying Notifications.
- + NotificationUtil.Importance
Notification channel importance levels.
- + NoUidTimeline
A timeline which wraps another timeline and overrides all window and period uids to 0.
- + OfflineLicenseHelper
Helper class to download, renew and release offline licenses.
- + OggExtractor
Extracts data from the Ogg container format.
- + OkHttpDataSource
An HttpDataSource that delegates to Square's Call.Factory.
- + OkHttpDataSource.Factory - + OkHttpDataSourceFactory Deprecated. - + OpusDecoder
Opus decoder.
- + OpusDecoderException
Thrown when an Opus decoder error occurs.
- + OpusLibrary
Configures and queries the underlying native library.
- + OpusUtil
Utility methods for handling Opus audio streams.
- + OutputBuffer
Output buffer decoded by a Decoder.
- + OutputBuffer.Owner<S extends OutputBuffer>
Buffer owner.
- + OutputConsumerAdapterV30
MediaParser.OutputConsumer implementation that redirects output to an ExtractorOutput.
- + ParsableBitArray
Wraps a byte array, providing methods that allow it to be read as a bitstream.
- + ParsableByteArray
Wraps a byte array, providing a set of methods for parsing data from it.
- + ParsableNalUnitBitArray
Wraps a byte array, providing methods that allow it to be read as a NAL unit bitstream.
- + ParserException
Thrown when an error occurs parsing media data and metadata.
- + ParsingLoadable<T>
A Loader.Loadable for objects that can be parsed from binary data using a ParsingLoadable.Parser.
- + ParsingLoadable.Parser<T>
Parses an object from loaded data.
- + PassthroughSectionPayloadReader
A SectionPayloadReader that directly outputs the section bytes as sample data.
- + PercentageRating
A rating expressed as a percentage.
- + Period
Encapsulates media content components over a contiguous period of time.
- + PesReader
Parses PES packet data and extracts samples.
- + PgsDecoder
A SimpleSubtitleDecoder for PGS subtitles.
- + PictureFrame
A picture parsed from a FLAC file.
- + PlatformScheduler
A Scheduler that uses JobScheduler.
- + PlatformScheduler.PlatformSchedulerService
A JobService that starts the target service if the requirements are met.
- + +PlaybackException + +
Thrown when a non locally recoverable playback failure occurs.
+ + + +PlaybackException.ErrorCode + +
Codes that identify causes of player errors.
+ + + +PlaybackException.FieldNumber + +
Identifiers for fields in a Bundle which represents a playback exception.
+ + + PlaybackOutput
Class to capture output from a playback test.
- + PlaybackParameters
Parameters that apply to playback, including speed setting.
- -PlaybackPreparer -Deprecated. -
Use ControlDispatcher instead.
- - - + PlaybackSessionManager
Manager for active playback sessions.
- + PlaybackSessionManager.Listener
A listener for session updates.
- + PlaybackStats
Statistics about playbacks.
- + PlaybackStats.EventTimeAndException
Stores an exception with the event time at which it occurred.
- + PlaybackStats.EventTimeAndFormat
Stores a format with the event time at which it started being used, or null to indicate that no format was used.
- + PlaybackStats.EventTimeAndPlaybackState
Stores a playback state with the event time at which it became active.
- + PlaybackStatsListener
AnalyticsListener to gather PlaybackStats from the player.
- + PlaybackStatsListener.Callback
A listener for PlaybackStats updates.
- + Player
A media player interface defining traditional high-level functionality, such as the ability to play, pause, seek and query properties of the currently playing media.
- + Player.Command
Commands that can be executed on a Player.
- + Player.Commands
A set of commands.
- + Player.Commands.Builder
A builder for Player.Commands instances.
- + Player.DiscontinuityReason
Reasons for position discontinuities.
- -Player.EventFlags + +Player.Event
Events that can be reported via Player.Listener.onEvents(Player, Events).
- + Player.EventListener Deprecated. - + Player.Events - +
A set of events.
- + Player.Listener
Listener of all changes in the Player.
- + Player.MediaItemTransitionReason
Reasons for media item transitions.
- + Player.PlaybackSuppressionReason
Reason why playback is suppressed even though Player.getPlayWhenReady() is true.
- + Player.PlayWhenReadyChangeReason
Reasons for playWhenReady changes.
- + Player.PositionInfo
Position info describing a playback position involved in a discontinuity.
- + Player.RepeatMode
Repeat modes for playback.
- + Player.State
Playback state.
- + Player.TimelineChangeReason
Reasons for timeline changes.
- + PlayerControlView
A view for controlling Player instances.
- + PlayerControlView.ProgressUpdateListener
Listener to be notified when progress has been updated.
- + PlayerControlView.VisibilityListener
Listener to be notified about changes of the visibility of the UI control.
- + PlayerEmsgHandler
Handles all emsg messages from all media tracks for the player.
- + PlayerEmsgHandler.PlayerEmsgCallback
Callbacks for player emsg events encountered during DASH live stream.
- + PlayerMessage
Defines a player message which can be sent with a PlayerMessage.Sender and received by a PlayerMessage.Target.
- + PlayerMessage.Sender
A sender for messages.
- + PlayerMessage.Target
A target for messages.
- + PlayerNotificationManager
Starts, updates and cancels a media style notification reflecting the player state.
- + PlayerNotificationManager.Builder
A builder for PlayerNotificationManager instances.
- + PlayerNotificationManager.CustomActionReceiver
Defines and handles custom actions.
- + PlayerNotificationManager.MediaDescriptionAdapter
An adapter to provide content assets of the media currently playing.
- + PlayerNotificationManager.NotificationListener
A listener for changes to the notification.
- + PlayerNotificationManager.Priority
Priority of the notification (required for API 25 and lower).
- + PlayerNotificationManager.Visibility
Visibility of notification on the lock screen.
- + PlayerView
A high level view for Player media playbacks.
- + PlayerView.ShowBuffering
Determines when the buffering view is shown.
- + PositionHolder
Holds a position in the stream.
- + PriorityDataSource
A DataSource that can be used as part of a task registered with a PriorityTaskManager.
- + PriorityDataSourceFactory
A DataSource.Factory that produces PriorityDataSource instances.
- + PriorityTaskManager
Allows tasks with associated priorities to control how they proceed relative to one another.
- + PriorityTaskManager.PriorityTooLowException
Thrown when task attempts to proceed when another registered task has a higher priority.
- + PrivateCommand
Represents a private command as defined in SCTE35, Section 9.3.6.
- + PrivFrame
PRIV (Private) ID3 frame.
- + ProgramInformation
A parsed program information element.
- + ProgressHolder
Holds a progress percentage.
- + ProgressiveDownloader
A downloader for progressive media streams.
- + ProgressiveMediaExtractor
Extracts the contents of a container file from a progressive media stream.
- + ProgressiveMediaExtractor.Factory
Creates ProgressiveMediaExtractor instances.
- + ProgressiveMediaSource
Provides one period that loads data from a Uri and extracted using an Extractor.
- + ProgressiveMediaSource.Factory - + PsExtractor
Extracts data from the MPEG-2 PS container format.
- + PsshAtomUtil
Utility methods for handling PSSH atoms.
- + RandomizedMp3Decoder
Generates randomized, but correct amount of data on MP3 audio input.
- + RandomTrackSelection
An ExoTrackSelection whose selected track is updated randomly.
- + RandomTrackSelection.Factory
Factory for RandomTrackSelection instances.
- + RangedUri
Defines a range of data located at a reference uri.
- + Rating
A rating for media content.
- + RawCcExtractor
Extracts data from the RawCC container format.
- + RawResourceDataSource
A DataSource for reading a raw resource inside the APK.
- + RawResourceDataSource.RawResourceDataSourceException
Thrown when an IOException is encountered reading from a raw resource.
- + Renderer
Renders media read from a SampleStream.
- + Renderer.State
The renderer states.
- + Renderer.VideoScalingMode Deprecated. - + Renderer.WakeupListener
Some renderers can signal when Renderer.render(long, long) should be called.
- + RendererCapabilities
Defines the capabilities of a Renderer.
- + RendererCapabilities.AdaptiveSupport
Level of renderer support for adaptive format switches.
- + RendererCapabilities.Capabilities
Combined renderer capabilities.
- + RendererCapabilities.FormatSupport Deprecated.
Use C.FormatSupport instead.
- + RendererCapabilities.TunnelingSupport
Level of renderer support for tunneling.
- + RendererConfiguration
The configuration of a Renderer.
- + RenderersFactory
Builds Renderer instances for use by a SimpleExoPlayer.
- + RepeatModeActionProvider
Provides a custom action for toggling repeat modes.
- + RepeatModeUtil
Util class for repeat mode handling.
- + RepeatModeUtil.RepeatToggleModes
Set of repeat toggle modes.
- + Representation
A DASH representation.
- + Representation.MultiSegmentRepresentation
A DASH representation consisting of multiple segments.
- + Representation.SingleSegmentRepresentation
A DASH representation consisting of a single segment.
- + Requirements
Defines a set of device state requirements.
- + Requirements.RequirementFlags
Requirement flags.
- + RequirementsWatcher
Watches whether the Requirements are met and notifies the RequirementsWatcher.Listener on changes.
- + RequirementsWatcher.Listener
Notified when RequirementsWatcher instance first created and on changes whether the Requirements are met.
- + ResolvingDataSource
DataSource wrapper allowing just-in-time resolution of DataSpecs.
- + ResolvingDataSource.Factory - + ResolvingDataSource.Resolver
Resolves DataSpecs.
- + ReusableBufferedOutputStream
This is a subclass of BufferedOutputStream with a ReusableBufferedOutputStream.reset(OutputStream) method that allows an instance to be re-used with another underlying output stream.
- + RobolectricUtil
Utility methods for Robolectric-based tests.
- + RtmpDataSource -
A Real-Time Messaging Protocol (RTMP) DataSource.
+
A Real-Time Messaging Protocol (RTMP) DataSource.
+ + + +RtmpDataSource.Factory + + - + RtmpDataSourceFactory - - +Deprecated. + - + RtpAc3Reader
Parses an AC3 byte stream carried on RTP packets, and extracts AC3 frames.
- + RtpPacket
Represents the header and the payload of an RTP packet.
- + RtpPacket.Builder
Builder class for an RtpPacket
- + RtpPayloadFormat
Represents the payload format used in RTP.
- + RtpPayloadReader
Extracts media samples from the payload of received RTP packets.
- + RtpPayloadReader.Factory
Factory of RtpPayloadReader instances.
- + RtpUtils
Utility methods for RTP.
- + RtspMediaSource
An Rtsp MediaSource
- + RtspMediaSource.Factory
Factory for RtspMediaSource
- + RtspMediaSource.RtspPlaybackException
Thrown when an exception or error is encountered during loading an RTSP stream.
- + RubySpan
A styling span for ruby text.
- + RunnableFutureTask<R,​E extends Exception>
A RunnableFuture that supports additional uninterruptible operations to query whether execution has started and finished.
- + SampleQueue
A queue of media samples.
- + SampleQueue.UpstreamFormatChangedListener
A listener for changes to the upstream format.
- + SampleQueueMappingException
Thrown when it is not possible to map a TrackGroup to a SampleQueue.
- + SampleStream
A stream of media samples (and associated format information).
- + SampleStream.ReadDataResult - + SampleStream.ReadFlags - + Scheduler
Schedules a service to be started in the foreground when some Requirements are met.
- + SectionPayloadReader
Reads section data.
- + SectionReader
Reads section data packets and feeds the whole sections to a given SectionPayloadReader.
- + SeekMap
Maps seek positions (in microseconds) to corresponding positions (byte offsets) in the stream.
- + SeekMap.SeekPoints
Contains one or two SeekPoints.
- + SeekMap.Unseekable
A SeekMap that does not support seeking.
- + SeekParameters
Parameters that apply to seeking.
- + SeekPoint
Defines a seek point in a media stream.
- + SegmentBase
An approximate representation of a SegmentBase manifest element.
- + SegmentBase.MultiSegmentBase
A SegmentBase that consists of multiple segments.
- + SegmentBase.SegmentList
A SegmentBase.MultiSegmentBase that uses a SegmentList to define its segments.
- + SegmentBase.SegmentTemplate
A SegmentBase.MultiSegmentBase that uses a SegmentTemplate to define its segments.
- + SegmentBase.SegmentTimelineElement
Represents a timeline segment from the MPD's SegmentTimeline list.
- + SegmentBase.SingleSegmentBase
A SegmentBase that defines a single segment.
- + SegmentDownloader<M extends FilterableManifest<M>>
Base class for multi segment stream downloaders.
- + SegmentDownloader.Segment
Smallest unit of content to be downloaded.
- + SeiReader
Consumes SEI buffers, outputting contained CEA-608/708 messages to a TrackOutput.
- + SequenceableLoader
A loader that can proceed in approximate synchronization with other loaders.
- + SequenceableLoader.Callback<T extends SequenceableLoader>
A callback to be notified of SequenceableLoader events.
- + +ServerSideInsertedAdsMediaSource + +
A MediaSource for server-side inserted ad breaks.
+ + + +ServerSideInsertedAdsUtil + +
A static utility class with methods to work with server-side inserted ads.
+ + + ServiceDescriptionElement
Represents a service description element.
- + SessionAvailabilityListener
Listener of changes in the cast session availability.
- + SessionCallbackBuilder
Builds a MediaSession.SessionCallback with various collaborators.
- + SessionCallbackBuilder.AllowedCommandProvider
Provides allowed commands for MediaController.
- + SessionCallbackBuilder.CustomCommandProvider
Callbacks for querying what custom commands are supported, and for handling a custom command when a controller sends it.
- + SessionCallbackBuilder.DefaultAllowedCommandProvider
Default implementation of SessionCallbackBuilder.AllowedCommandProvider that behaves as follows: @@ -5737,1289 +5847,1288 @@

All Classes

Controller is in the same package as the session.
- + SessionCallbackBuilder.DisconnectedCallback
Callback for handling controller disconnection.
- + SessionCallbackBuilder.MediaIdMediaItemProvider
A SessionCallbackBuilder.MediaItemProvider that creates media items containing only a media ID.
- + SessionCallbackBuilder.MediaItemProvider
Provides the MediaItem.
- + SessionCallbackBuilder.PostConnectCallback
Callback for handling extra initialization after the connection.
- + SessionCallbackBuilder.RatingCallback
Callback receiving a user rating for a specified media id.
- + SessionCallbackBuilder.SkipCallback
Callback receiving skip backward and skip forward.
- + SessionPlayerConnector
An implementation of SessionPlayer that wraps a given ExoPlayer Player instance.
- + ShadowMediaCodecConfig
A JUnit @Rule to configure Roboelectric's ShadowMediaCodec.
- + ShuffleOrder
Shuffled order of indices.
- + ShuffleOrder.DefaultShuffleOrder
The default ShuffleOrder implementation for random shuffle order.
- + ShuffleOrder.UnshuffledShuffleOrder
A ShuffleOrder implementation which does not shuffle.
- + SilenceMediaSource
Media source with a single period consisting of silent raw audio of a given duration.
- + SilenceMediaSource.Factory
Factory for SilenceMediaSources.
- + SilenceSkippingAudioProcessor
An AudioProcessor that skips silence in the input stream.
- + SimpleCache
A Cache implementation that maintains an in-memory representation.
- + SimpleDecoder<I extends DecoderInputBuffer,​O extends OutputBuffer,​E extends DecoderException>
Base class for Decoders that use their own decode thread and decode each input buffer immediately into a corresponding output buffer.
- + SimpleExoPlayer
An ExoPlayer implementation that uses default Renderer components.
- + SimpleExoPlayer.Builder
A builder for SimpleExoPlayer instances.
- + SimpleMetadataDecoder
A MetadataDecoder base class that validates input buffers and discards any for which Buffer.isDecodeOnly() is true.
- + SimpleOutputBuffer
Buffer for SimpleDecoder output.
- + SimpleSubtitleDecoder
Base class for subtitle parsers that use their own decode thread.
- + SinglePeriodAdTimeline
A Timeline for sources that have ads.
- + SinglePeriodTimeline
A Timeline consisting of a single period and static window.
- + SingleSampleMediaChunk
A BaseMediaChunk for chunks consisting of a single raw sample.
- + SingleSampleMediaSource
Loads data at a given Uri as a single sample belonging to a single MediaPeriod.
- + SingleSampleMediaSource.Factory - + SlidingPercentile
Calculate any percentile over a sliding window of weighted values.
- + SlowMotionData
Holds information about the segments of slow motion playback within a track.
- + SlowMotionData.Segment
Holds information about a single segment of slow motion playback within a track.
- + SmtaMetadataEntry
Stores metadata from the Samsung smta box.
- + SntpClient
Static utility to retrieve the device time offset using SNTP.
- + SntpClient.InitializationCallback - + SonicAudioProcessor
An AudioProcessor that uses the Sonic library to modify audio speed/pitch/sample rate.
- + SpannedSubject
A Truth Subject for assertions on Spanned instances containing text styling.
- + SpannedSubject.AbsoluteSized
Allows assertions about the absolute size of a span.
- + SpannedSubject.Aligned
Allows assertions about the alignment of a span.
- + SpannedSubject.AndSpanFlags
Allows additional assertions to be made on the flags of matching spans.
- + SpannedSubject.Colored
Allows assertions about the color of a span.
- + SpannedSubject.EmphasizedText
Allows assertions about a span's text emphasis mark and its position.
- + SpannedSubject.RelativeSized
Allows assertions about the relative size of a span.
- + SpannedSubject.RubyText
Allows assertions about a span's ruby text and its position.
- + SpannedSubject.Typefaced
Allows assertions about the typeface of a span.
- + SpannedSubject.WithSpanFlags
Allows additional assertions to be made on the flags of matching spans.
- + SpanUtil
Utility methods for Android span styling.
- + SphericalGLSurfaceView
Renders a GL scene in a non-VR Activity that is affected by phone orientation and touch input.
- + SphericalGLSurfaceView.VideoSurfaceListener
Listener for the Surface to which video frames should be rendered.
- + SpliceCommand
Superclass for SCTE35 splice commands.
- + SpliceInfoDecoder
Decodes splice info sections and produces splice commands.
- + SpliceInsertCommand
Represents a splice insert command defined in SCTE35, Section 9.3.3.
- + SpliceInsertCommand.ComponentSplice
Holds splicing information for specific splice insert command components.
- + SpliceNullCommand
Represents a splice null command as defined in SCTE35, Section 9.3.1.
- + SpliceScheduleCommand
Represents a splice schedule command as defined in SCTE35, Section 9.3.2.
- + SpliceScheduleCommand.ComponentSplice
Holds splicing information for specific splice schedule command components.
- + SpliceScheduleCommand.Event
Represents a splice event as contained in a SpliceScheduleCommand.
- + SsaDecoder
A SimpleSubtitleDecoder for SSA/ASS.
- + SsChunkSource
A ChunkSource for SmoothStreaming.
- + SsChunkSource.Factory
Factory for SsChunkSources.
- + SsDownloader
A downloader for SmoothStreaming streams.
- + SsManifest
Represents a SmoothStreaming manifest.
- + SsManifest.ProtectionElement
Represents a protection element containing a single header.
- + SsManifest.StreamElement
Represents a StreamIndex element.
- + SsManifestParser
Parses SmoothStreaming client manifests.
- + SsManifestParser.MissingFieldException
Thrown if a required field is missing.
- + SsMediaSource
A SmoothStreaming MediaSource.
- + SsMediaSource.Factory
Factory for SsMediaSource.
- + StandaloneMediaClock
A MediaClock whose position advances with real time based on the playback parameters when started.
- + StarRating
A rating expressed as a fractional number of stars.
- + StartOffsetExtractorOutput
An extractor output that wraps another extractor output and applies a give start byte offset to seek positions.
- + StatsDataSource
DataSource wrapper which keeps track of bytes transferred, redirected uris, and response headers.
- + StreamKey
A key for a subset of media which can be separately loaded (a "stream").
- + StubExoPlayer
An abstract ExoPlayer implementation that throws UnsupportedOperationException from every method.
- + StyledPlayerControlView
A view for controlling Player instances.
- + StyledPlayerControlView.OnFullScreenModeChangedListener
Listener to be invoked to inform the fullscreen mode is changed.
- + StyledPlayerControlView.ProgressUpdateListener
Listener to be notified when progress has been updated.
- + StyledPlayerControlView.VisibilityListener
Listener to be notified about changes of the visibility of the UI control.
- + StyledPlayerView
A high level view for Player media playbacks.
- + StyledPlayerView.ShowBuffering
Determines when the buffering view is shown.
- + SubripDecoder
A SimpleSubtitleDecoder for SubRip.
- + Subtitle
A subtitle consisting of timed Cues.
- + SubtitleDecoder - + SubtitleDecoderException
Thrown when an error occurs decoding subtitle data.
- + SubtitleDecoderFactory
A factory for SubtitleDecoder instances.
- + SubtitleInputBuffer - + SubtitleOutputBuffer
Base class for SubtitleDecoder output buffers.
- + SubtitleView
A view for displaying subtitle Cues.
- + SubtitleView.ViewType
The type of View to use to display subtitles.
- + SynchronousMediaCodecAdapter
A MediaCodecAdapter that operates the underlying MediaCodec in synchronous mode.
- + SynchronousMediaCodecAdapter.Factory
A factory for SynchronousMediaCodecAdapter instances.
- + SystemClock
The standard implementation of Clock, an instance of which is available via Clock.DEFAULT.
- + TeeAudioProcessor
Audio processor that outputs its input unmodified and also outputs its input to a given sink.
- + TeeAudioProcessor.AudioBufferSink
A sink for audio buffers handled by the audio processor.
- + TeeAudioProcessor.WavFileAudioBufferSink
A sink for audio buffers that writes output audio as .wav files with a given path prefix.
- + TeeDataSource
Tees data into a DataSink as the data is read.
- + TestDownloadManagerListener
Allows tests to block for, and assert properties of, calls from a DownloadManager to its DownloadManager.Listener.
- + TestExoPlayerBuilder
A builder of SimpleExoPlayer instances for testing.
- + TestPlayerRunHelper
Helper methods to block the calling thread until the provided SimpleExoPlayer instance reaches a particular state.
- + TestUtil
Utility methods for tests.
- + TextAnnotation
Properties of a text annotation (i.e.
- + TextAnnotation.Position
The possible positions of the annotation text relative to the base text.
- + TextEmphasisSpan
A styling span for text emphasis marks.
- + TextEmphasisSpan.MarkFill
The possible mark fills that can be used.
- + TextEmphasisSpan.MarkShape
The possible mark shapes that can be used.
- + TextInformationFrame
Text information ID3 frame.
- + TextOutput
Receives text output.
- + TextRenderer
A renderer for text.
- + ThumbRating
A rating expressed as "thumbs up" or "thumbs down".
- + TimeBar
Interface for time bar views that can display a playback position, buffered position, duration and ad markers, and that have a listener for scrubbing (seeking) events.
- + TimeBar.OnScrubListener
Listener for scrubbing events.
- + TimedValueQueue<V>
A utility class to keep a queue of values with timestamps.
- + Timeline
A flexible representation of the structure of media.
- + Timeline.Period
Holds information about a period in a Timeline.
- + +Timeline.RemotableTimeline + +
A concrete class of Timeline to restore a Timeline instance from a Bundle sent by another process via IBinder.
+ + + Timeline.Window
Holds information about a window in a Timeline.
- + TimelineAsserts
Assertion methods for Timeline.
- + TimelineQueueEditor - + TimelineQueueEditor.MediaDescriptionConverter
Converts a MediaDescriptionCompat to a MediaItem.
- + TimelineQueueEditor.MediaIdEqualityChecker
Media description comparator comparing the media IDs.
- + TimelineQueueEditor.QueueDataAdapter
Adapter to get MediaDescriptionCompat of items in the queue and to notify the - application about changes in the queue to sync the data structure backing the - MediaSessionConnector.
+ application about changes in the queue to sync the data structure backing the MediaSessionConnector. - + TimelineQueueNavigator
An abstract implementation of the MediaSessionConnector.QueueNavigator that maps the windows of a Player's Timeline to the media session queue.
- + TimeSignalCommand
Represents a time signal command as defined in SCTE35, Section 9.3.4.
- + TimestampAdjuster -
Offsets timestamps according to an initial sample timestamp offset.
+
Adjusts and offsets sample timestamps.
- + TimestampAdjusterProvider
Provides TimestampAdjuster instances for use during HLS playbacks.
- + TimeToFirstByteEstimator
Provides an estimate of the time to first byte of a transfer.
- + TraceUtil
Calls through to Trace methods on supported API levels.
- + Track
Encapsulates information describing an MP4 track.
- + Track.Transformation
The transformation to apply to samples in the track, if any.
- + TrackEncryptionBox
Encapsulates information parsed from a track encryption (tenc) box or sample group description (sgpd) box in an MP4 stream.
- + TrackGroup
Defines an immutable group of tracks identified by their format identity.
- + TrackGroupArray
An immutable array of TrackGroups.
- + TrackNameProvider
Converts Formats to user readable track names.
- + TrackOutput
Receives track level data extracted by an Extractor.
- + TrackOutput.CryptoData
Holds data required to decrypt a sample.
- + TrackOutput.SampleDataPart
Defines the part of the sample data to which a call to TrackOutput.sampleData(com.google.android.exoplayer2.upstream.DataReader, int, boolean) corresponds.
- + TrackSelection
A track selection consisting of a static subset of selected tracks belonging to a TrackGroup.
- + TrackSelectionArray
An array of TrackSelections.
- + TrackSelectionDialogBuilder
Builder for a dialog with a TrackSelectionView.
- + TrackSelectionDialogBuilder.DialogCallback
Callback which is invoked when a track selection has been made.
- + TrackSelectionParameters
Constraint parameters for track selection.
- + TrackSelectionParameters.Builder - + TrackSelectionUtil
Track selection related utility methods.
- + TrackSelectionUtil.AdaptiveTrackSelectionFactory
Functional interface to create a single adaptive track selection.
- + TrackSelectionView
A view for making track selections.
- + TrackSelectionView.TrackSelectionListener
Listener for changes to the selected tracks.
- + TrackSelector
The component of an ExoPlayer responsible for selecting tracks to be consumed by each of the player's Renderers.
- + TrackSelector.InvalidationListener
Notified when selections previously made by a TrackSelector are no longer valid.
- + TrackSelectorResult
The result of a TrackSelector operation.
- + TransferListener
A listener of data transfer events.
- + Transformer
A transformer to transform media inputs.
- + Transformer.Builder
A builder for Transformer instances.
- + Transformer.Listener
A listener for the transformation events.
- + Transformer.ProgressState
Progress state.
- + TsExtractor
Extracts data from the MPEG-2 TS container format.
- + TsExtractor.Mode
Modes for the extractor.
- + TsPayloadReader
Parses TS packet payload data.
- + TsPayloadReader.DvbSubtitleInfo
Holds information about a DVB subtitle, as defined in ETSI EN 300 468 V1.11.1 section 6.2.41.
- + TsPayloadReader.EsInfo
Holds information associated with a PMT entry.
- + TsPayloadReader.Factory
Factory of TsPayloadReader instances.
- + TsPayloadReader.Flags
Contextual flags indicating the presence of indicators in the TS packet or PES packet headers.
- + TsPayloadReader.TrackIdGenerator
Generates track ids for initializing TsPayloadReaders' TrackOutputs.
- + TsUtil
Utilities method for extracting MPEG-TS streams.
- + TtmlDecoder
A SimpleSubtitleDecoder for TTML supporting the DFXP presentation profile.
- + Tx3gDecoder - + UdpDataSource
A UDP DataSource.
- + UdpDataSource.UdpDataSourceException
Thrown when an error is encountered when trying to read from a UdpDataSource.
- + UnknownNull
Annotation for specifying unknown nullness.
- + UnrecognizedInputFormatException
Thrown if the input format was not recognized.
- + UnsupportedDrmException
Thrown when the requested DRM scheme is not supported.
- + UnsupportedDrmException.Reason
The reason for the exception.
- + UnsupportedMediaCrypto
ExoMediaCrypto type that cannot be used to handle any type of protected content.
- + UriUtil
Utility methods for manipulating URIs.
- + UrlLinkFrame
Url link ID3 frame.
- + UrlTemplate
A template from which URLs can be built.
- + UtcTimingElement
Represents a UTCTiming element.
- + Util
Miscellaneous utility methods.
- + VersionTable
Utility methods for accessing versions of ExoPlayer database components.
- + VideoDecoderGLSurfaceView
GLSurfaceView implementing VideoDecoderOutputBufferRenderer for rendering VideoDecoderOutputBuffers.
- + VideoDecoderInputBuffer
Input buffer to a video decoder.
- + VideoDecoderOutputBuffer
Video decoder output buffer containing video frame data.
- + VideoDecoderOutputBufferRenderer - + VideoFrameMetadataListener
A listener for metadata corresponding to video frames being rendered.
- + VideoFrameReleaseHelper
Helps a video Renderer release frames to a Surface.
- + VideoListener Deprecated. - + VideoRendererEventListener
Listener of video Renderer events.
- + VideoRendererEventListener.EventDispatcher
Dispatches events to a VideoRendererEventListener.
- + VideoSize
Represents the video size.
- + VorbisBitArray
Wraps a byte array, providing methods that allow it to be read as a Vorbis bitstream.
- + VorbisComment
A vorbis comment.
- + VorbisUtil
Utility methods for parsing Vorbis streams.
- + VorbisUtil.CommentHeader
Vorbis comment header.
- + VorbisUtil.Mode
Vorbis setup header modes.
- + VorbisUtil.VorbisIdHeader
Vorbis identification header.
- + VpxDecoder
Vpx decoder.
- + VpxDecoderException
Thrown when a libvpx decoder error occurs.
- + VpxLibrary
Configures and queries the underlying native library.
- -VpxOutputBuffer -Deprecated. - - - - + WavExtractor
Extracts data from WAV byte streams.
- + WavUtil
Utilities for handling WAVE files.
- + WebServerDispatcher
A Dispatcher for MockWebServer that allows per-path customisation of the static data served.
- + WebServerDispatcher.Resource
A resource served by WebServerDispatcher.
- + WebServerDispatcher.Resource.Builder - + WebvttCssStyle
Style object of a Css style block in a Webvtt file.
- + WebvttCssStyle.FontSizeUnit
Font size unit enum.
- + WebvttCssStyle.StyleFlags
Style flag enum.
- + WebvttCueInfo
A representation of a WebVTT cue.
- + WebvttCueParser
Parser for WebVTT cues.
- + WebvttDecoder
A SimpleSubtitleDecoder for WebVTT.
- + WebvttExtractor
A special purpose extractor for WebVTT content in HLS.
- + WebvttParserUtil
Utility methods for parsing WebVTT data.
- + WidevineUtil
Utility methods for Widevine.
- + WorkManagerScheduler
A Scheduler that uses WorkManager.
- + WorkManagerScheduler.SchedulerWorker
A Worker that starts the target service if the requirements are met.
- + WritableDownloadIndex
A writable index of Downloads.
- + XmlPullParserUtil
XmlPullParser utility methods.
diff --git a/docs/doc/reference/allclasses.html b/docs/doc/reference/allclasses.html index b5bc931fd66..288afe5bcf4 100644 --- a/docs/doc/reference/allclasses.html +++ b/docs/doc/reference/allclasses.html @@ -144,6 +144,8 @@

All Classes

  • BasePlayer
  • BaseRenderer
  • BaseTrackSelection
  • +
  • BaseUrl
  • +
  • BaseUrlExclusionList
  • BehindLiveWindowException
  • BinaryFrame
  • BinarySearchSeeker
  • @@ -156,6 +158,7 @@

    All Classes

  • Buffer
  • Bundleable
  • Bundleable.Creator
  • +
  • BundleableUtils
  • BundledChunkExtractor
  • BundledExtractorsAdapter
  • BundledHlsMediaChunkExtractor
  • @@ -175,6 +178,7 @@

    All Classes

  • C.ColorTransfer
  • C.ContentType
  • C.CryptoMode
  • +
  • C.DataType
  • C.Encoding
  • C.FormatSupport
  • C.NetworkType
  • @@ -257,7 +261,7 @@

    All Classes

  • CronetDataSource.OpenException
  • CronetDataSourceFactory
  • CronetEngineWrapper
  • -
  • CronetEngineWrapper.CronetEngineSource
  • +
  • CronetUtil
  • CryptoInfo
  • Cue
  • Cue.AnchorType
  • @@ -350,6 +354,7 @@

    All Classes

  • DefaultLoadControl
  • DefaultLoadControl.Builder
  • DefaultLoadErrorHandlingPolicy
  • +
  • DefaultMediaDescriptionAdapter
  • DefaultMediaItemConverter
  • DefaultMediaItemConverter
  • DefaultMediaSourceFactory
  • @@ -409,6 +414,8 @@

    All Classes

  • DrmSessionManager
  • DrmSessionManager.DrmSessionReference
  • DrmSessionManagerProvider
  • +
  • DrmUtil
  • +
  • DrmUtil.ErrorSource
  • DtsReader
  • DtsUtil
  • DummyDataSource
  • @@ -440,8 +447,6 @@

    All Classes

  • EventMessageEncoder
  • EventStream
  • ExoDatabaseProvider
  • -
  • ExoFlags
  • -
  • ExoFlags.Builder
  • ExoHostedTest
  • ExoMediaCrypto
  • ExoMediaDrm
  • @@ -552,12 +557,15 @@

    All Classes

  • FlacSeekTableSeekMap
  • FlacStreamMetadata
  • FlacStreamMetadata.SeekTable
  • +
  • FlagSet
  • +
  • FlagSet.Builder
  • FlvExtractor
  • Format
  • Format.Builder
  • FormatHolder
  • ForwardingAudioSink
  • ForwardingExtractorInput
  • +
  • ForwardingPlayer
  • ForwardingTimeline
  • FragmentedMp4Extractor
  • FragmentedMp4Extractor.Flags
  • @@ -667,6 +675,9 @@

    All Classes

  • LoaderErrorThrower
  • LoaderErrorThrower.Dummy
  • LoadErrorHandlingPolicy
  • +
  • LoadErrorHandlingPolicy.FallbackOptions
  • +
  • LoadErrorHandlingPolicy.FallbackSelection
  • +
  • LoadErrorHandlingPolicy.FallbackType
  • LoadErrorHandlingPolicy.LoadErrorInfo
  • LoadEventInfo
  • LocalMediaDrmCallback
  • @@ -717,6 +728,7 @@

    All Classes

  • MediaMetadata
  • MediaMetadata.Builder
  • MediaMetadata.FolderType
  • +
  • MediaMetadata.PictureType
  • MediaParserChunkExtractor
  • MediaParserExtractorAdapter
  • MediaParserHlsMediaChunkExtractor
  • @@ -771,6 +783,7 @@

    All Classes

  • NalUnitUtil.PpsData
  • NalUnitUtil.SpsData
  • NetworkTypeObserver
  • +
  • NetworkTypeObserver.Config
  • NetworkTypeObserver.Listener
  • NonNullApi
  • NoOpCacheEvictor
  • @@ -804,9 +817,11 @@

    All Classes

  • PictureFrame
  • PlatformScheduler
  • PlatformScheduler.PlatformSchedulerService
  • +
  • PlaybackException
  • +
  • PlaybackException.ErrorCode
  • +
  • PlaybackException.FieldNumber
  • PlaybackOutput
  • PlaybackParameters
  • -
  • PlaybackPreparer
  • PlaybackSessionManager
  • PlaybackSessionManager.Listener
  • PlaybackStats
  • @@ -820,7 +835,7 @@

    All Classes

  • Player.Commands
  • Player.Commands.Builder
  • Player.DiscontinuityReason
  • -
  • Player.EventFlags
  • +
  • Player.Event
  • Player.EventListener
  • Player.Events
  • Player.Listener
  • @@ -899,6 +914,7 @@

    All Classes

  • ReusableBufferedOutputStream
  • RobolectricUtil
  • RtmpDataSource
  • +
  • RtmpDataSource.Factory
  • RtmpDataSourceFactory
  • RtpAc3Reader
  • RtpPacket
  • @@ -937,6 +953,8 @@

    All Classes

  • SeiReader
  • SequenceableLoader
  • SequenceableLoader.Callback
  • +
  • ServerSideInsertedAdsMediaSource
  • +
  • ServerSideInsertedAdsUtil
  • ServiceDescriptionElement
  • SessionAvailabilityListener
  • SessionCallbackBuilder
  • @@ -1054,6 +1072,7 @@

    All Classes

  • TimedValueQueue
  • Timeline
  • Timeline.Period
  • +
  • Timeline.RemotableTimeline
  • Timeline.Window
  • TimelineAsserts
  • TimelineQueueEditor
  • @@ -1136,7 +1155,6 @@

    All Classes

  • VpxDecoder
  • VpxDecoderException
  • VpxLibrary
  • -
  • VpxOutputBuffer
  • WavExtractor
  • WavUtil
  • WebServerDispatcher
  • diff --git a/docs/doc/reference/com/google/android/exoplayer2/AbstractConcatenatedTimeline.html b/docs/doc/reference/com/google/android/exoplayer2/AbstractConcatenatedTimeline.html index f953bef48f3..460a9366973 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/AbstractConcatenatedTimeline.html +++ b/docs/doc/reference/com/google/android/exoplayer2/AbstractConcatenatedTimeline.html @@ -159,7 +159,7 @@

    Nested Class Summary

    Nested classes/interfaces inherited from class com.google.android.exoplayer2.Timeline

    -Timeline.Period, Timeline.Window +Timeline.Period, Timeline.RemotableTimeline, Timeline.Window @@ -189,7 +189,7 @@

    Field Summary

    Fields inherited from interface com.google.android.exoplayer2.Player

    -COMMAND_ADJUST_DEVICE_VOLUME, COMMAND_CHANGE_MEDIA_ITEMS, COMMAND_GET_AUDIO_ATTRIBUTES, COMMAND_GET_CURRENT_MEDIA_ITEM, COMMAND_GET_DEVICE_VOLUME, COMMAND_GET_MEDIA_ITEMS, COMMAND_GET_MEDIA_ITEMS_METADATA, COMMAND_GET_TEXT, COMMAND_GET_VOLUME, COMMAND_PLAY_PAUSE, COMMAND_PREPARE_STOP, COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, COMMAND_SEEK_TO_DEFAULT_POSITION, COMMAND_SEEK_TO_MEDIA_ITEM, COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM, COMMAND_SET_DEVICE_VOLUME, COMMAND_SET_REPEAT_MODE, COMMAND_SET_SHUFFLE_MODE, COMMAND_SET_SPEED_AND_PITCH, COMMAND_SET_VIDEO_SURFACE, COMMAND_SET_VOLUME, DISCONTINUITY_REASON_AUTO_TRANSITION, DISCONTINUITY_REASON_INTERNAL, DISCONTINUITY_REASON_REMOVE, DISCONTINUITY_REASON_SEEK, DISCONTINUITY_REASON_SEEK_ADJUSTMENT, DISCONTINUITY_REASON_SKIP, EVENT_AVAILABLE_COMMANDS_CHANGED, EVENT_IS_LOADING_CHANGED, EVENT_IS_PLAYING_CHANGED, EVENT_MEDIA_ITEM_TRANSITION, EVENT_MEDIA_METADATA_CHANGED, EVENT_PLAY_WHEN_READY_CHANGED, EVENT_PLAYBACK_PARAMETERS_CHANGED, EVENT_PLAYBACK_STATE_CHANGED, EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED, EVENT_PLAYER_ERROR, EVENT_POSITION_DISCONTINUITY, EVENT_REPEAT_MODE_CHANGED, EVENT_SHUFFLE_MODE_ENABLED_CHANGED, EVENT_STATIC_METADATA_CHANGED, EVENT_TIMELINE_CHANGED, EVENT_TRACKS_CHANGED, MEDIA_ITEM_TRANSITION_REASON_AUTO, MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED, MEDIA_ITEM_TRANSITION_REASON_REPEAT, MEDIA_ITEM_TRANSITION_REASON_SEEK, PLAY_WHEN_READY_CHANGE_REASON_AUDIO_BECOMING_NOISY, PLAY_WHEN_READY_CHANGE_REASON_AUDIO_FOCUS_LOSS, PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM, PLAY_WHEN_READY_CHANGE_REASON_REMOTE, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST, PLAYBACK_SUPPRESSION_REASON_NONE, PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS, REPEAT_MODE_ALL, REPEAT_MODE_OFF, REPEAT_MODE_ONE, STATE_BUFFERING, STATE_ENDED, STATE_IDLE, STATE_READY, TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED, TIMELINE_CHANGE_REASON_SOURCE_UPDATE +COMMAND_ADJUST_DEVICE_VOLUME, COMMAND_CHANGE_MEDIA_ITEMS, COMMAND_GET_AUDIO_ATTRIBUTES, COMMAND_GET_CURRENT_MEDIA_ITEM, COMMAND_GET_DEVICE_VOLUME, COMMAND_GET_MEDIA_ITEMS_METADATA, COMMAND_GET_TEXT, COMMAND_GET_TIMELINE, COMMAND_GET_VOLUME, COMMAND_INVALID, COMMAND_PLAY_PAUSE, COMMAND_PREPARE_STOP, COMMAND_SEEK_BACK, COMMAND_SEEK_FORWARD, COMMAND_SEEK_IN_CURRENT_WINDOW, COMMAND_SEEK_TO_DEFAULT_POSITION, COMMAND_SEEK_TO_NEXT, COMMAND_SEEK_TO_NEXT_WINDOW, COMMAND_SEEK_TO_PREVIOUS, COMMAND_SEEK_TO_PREVIOUS_WINDOW, COMMAND_SEEK_TO_WINDOW, COMMAND_SET_DEVICE_VOLUME, COMMAND_SET_MEDIA_ITEMS_METADATA, COMMAND_SET_REPEAT_MODE, COMMAND_SET_SHUFFLE_MODE, COMMAND_SET_SPEED_AND_PITCH, COMMAND_SET_VIDEO_SURFACE, COMMAND_SET_VOLUME, DISCONTINUITY_REASON_AUTO_TRANSITION, DISCONTINUITY_REASON_INTERNAL, DISCONTINUITY_REASON_REMOVE, DISCONTINUITY_REASON_SEEK, DISCONTINUITY_REASON_SEEK_ADJUSTMENT, DISCONTINUITY_REASON_SKIP, EVENT_AVAILABLE_COMMANDS_CHANGED, EVENT_IS_LOADING_CHANGED, EVENT_IS_PLAYING_CHANGED, EVENT_MAX_SEEK_TO_PREVIOUS_POSITION_CHANGED, EVENT_MEDIA_ITEM_TRANSITION, EVENT_MEDIA_METADATA_CHANGED, EVENT_PLAY_WHEN_READY_CHANGED, EVENT_PLAYBACK_PARAMETERS_CHANGED, EVENT_PLAYBACK_STATE_CHANGED, EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED, EVENT_PLAYER_ERROR, EVENT_PLAYLIST_METADATA_CHANGED, EVENT_POSITION_DISCONTINUITY, EVENT_REPEAT_MODE_CHANGED, EVENT_SEEK_BACK_INCREMENT_CHANGED, EVENT_SEEK_FORWARD_INCREMENT_CHANGED, EVENT_SHUFFLE_MODE_ENABLED_CHANGED, EVENT_STATIC_METADATA_CHANGED, EVENT_TIMELINE_CHANGED, EVENT_TRACKS_CHANGED, MEDIA_ITEM_TRANSITION_REASON_AUTO, MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED, MEDIA_ITEM_TRANSITION_REASON_REPEAT, MEDIA_ITEM_TRANSITION_REASON_SEEK, PLAY_WHEN_READY_CHANGE_REASON_AUDIO_BECOMING_NOISY, PLAY_WHEN_READY_CHANGE_REASON_AUDIO_FOCUS_LOSS, PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM, PLAY_WHEN_READY_CHANGE_REASON_REMOTE, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST, PLAYBACK_SUPPRESSION_REASON_NONE, PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS, REPEAT_MODE_ALL, REPEAT_MODE_OFF, REPEAT_MODE_ONE, STATE_BUFFERING, STATE_ENDED, STATE_IDLE, STATE_READY, TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED, TIMELINE_CHANGE_REASON_SOURCE_UPDATE @@ -204,10 +204,12 @@

    Constructor Summary

    - + + + @@ -261,7 +263,9 @@

    Method Summary

    - + @@ -303,65 +307,60 @@

    Method Summary

    - - - - - - + - + + + + + + - - + + - - + + - + - + @@ -438,8 +436,7 @@

    Method Summary

    @@ -451,26 +448,70 @@

    Method Summary

    + + + + + + + + + + - + - + - + + + + + + + + + + + + + + + + + + + + + - + @@ -486,7 +527,7 @@

    Method Summary

    Clears the playlist and adds the specified MediaItem.
    - + @@ -494,7 +535,7 @@

    Method Summary

    Clears the playlist and adds the specified MediaItem.
    - + - + - + - + - + int errorCode) @@ -352,7 +353,7 @@

    Method Summary

    + Object message) @@ -565,8 +566,8 @@

    BaseRenderer

    public BaseRenderer​(int trackType)
    Parameters:
    -
    trackType - The track type that the renderer handles. One of the C - TRACK_TYPE_* constants.
    +
    trackType - The track type that the renderer handles. One of the C + TRACK_TYPE_* constants.
    @@ -721,9 +722,8 @@

    start

    Description copied from interface: Renderer
    Starts the renderer, meaning that calls to Renderer.render(long, long) will cause media to be rendered. -

    - This method may be called when the renderer is in the following states: - Renderer.STATE_ENABLED.

    + +

    This method may be called when the renderer is in the following states: Renderer.STATE_ENABLED.

    Specified by:
    start in interface Renderer
    @@ -786,9 +786,8 @@

    hasReadStreamToEnd

    public final boolean hasReadStreamToEnd()
    Description copied from interface: Renderer
    Returns whether the renderer has read the current SampleStream to the end. -

    - This method may be called when the renderer is in the following states: - Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

    + +

    This method may be called when the renderer is in the following states: Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

    Specified by:
    hasReadStreamToEnd in interface Renderer
    @@ -803,8 +802,7 @@

    hasReadStreamToEnd

    getReadingPositionUs

    public final long getReadingPositionUs()
    Description copied from interface: Renderer
    -
    Returns the renderer time up to which the renderer has read samples from the current SampleStream, in microseconds, or C.TIME_END_OF_SOURCE if the renderer has read the - current SampleStream to the end. +
    Returns the renderer time up to which the renderer has read samples, in microseconds, or C.TIME_END_OF_SOURCE if the renderer has read the current SampleStream to the end.

    This method may be called when the renderer is in the following states: Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

    @@ -823,9 +821,8 @@

    setCurrentStreamFinal

    Description copied from interface: Renderer
    Signals to the renderer that the current SampleStream will be the final one supplied before it is next disabled or reset. -

    - This method may be called when the renderer is in the following states: - Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

    + +

    This method may be called when the renderer is in the following states: Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

    Specified by:
    setCurrentStreamFinal in interface Renderer
    @@ -859,9 +856,8 @@

    maybeThrowStreamError

    Description copied from interface: Renderer
    Throws an error that's preventing the renderer from reading from its SampleStream. Does nothing if no such error exists. -

    - This method may be called when the renderer is in the following states: - Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

    + +

    This method may be called when the renderer is in the following states: Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

    Specified by:
    maybeThrowStreamError in interface Renderer
    @@ -881,12 +877,11 @@

    resetPosition

    throws ExoPlaybackException
    Description copied from interface: Renderer
    Signals to the renderer that a position discontinuity has occurred. -

    - After a position discontinuity, the renderer's SampleStream is guaranteed to provide + +

    After a position discontinuity, the renderer's SampleStream is guaranteed to provide samples starting from a key frame. -

    - This method may be called when the renderer is in the following states: - Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

    + +

    This method may be called when the renderer is in the following states: Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

    Specified by:
    resetPosition in interface Renderer
    @@ -923,9 +918,8 @@

    disable

    public final void disable()
    Description copied from interface: Renderer
    Disable the renderer, transitioning it to the Renderer.STATE_DISABLED state. -

    - This method may be called when the renderer is in the following states: - Renderer.STATE_ENABLED.

    + +

    This method may be called when the renderer is in the following states: Renderer.STATE_ENABLED.

    Specified by:
    disable in interface Renderer
    @@ -981,7 +975,7 @@

    supportsMixedMimeTypeAdaptation

    handleMessage

    public void handleMessage​(int messageType,
                               @Nullable
    -                          Object payload)
    +                          Object message)
                        throws ExoPlaybackException
    Description copied from interface: PlayerMessage.Target
    Handles a message delivered to the target.
    @@ -990,7 +984,7 @@

    handleMessage

    handleMessage in interface PlayerMessage.Target
    Parameters:
    messageType - The message type.
    -
    payload - The message payload.
    +
    message - The message payload.
    Throws:
    ExoPlaybackException - If an error occurred whilst handling the message. Should only be thrown by targets that handle messages on the playback thread.
    @@ -1078,8 +1072,8 @@

    onStarted

    protected void onStarted()
                       throws ExoPlaybackException
    Called when the renderer is started. -

    - The default implementation is a no-op.

    + +

    The default implementation is a no-op.

    Throws:
    ExoPlaybackException - If an error occurs.
    @@ -1106,8 +1100,8 @@

    onStopped

    onDisabled

    protected void onDisabled()
    Called when the renderer is disabled. -

    - The default implementation is a no-op.

    + +

    The default implementation is a no-op. @@ -1176,7 +1170,7 @@

    getIndex

    Returns the index of the renderer within the player.
    -
    + - +
      @@ -1203,7 +1204,9 @@

      createRendererException

      protected final ExoPlaybackException createRendererException​(Throwable cause,
                                                                    @Nullable
                                                                    Format format,
      -                                                             boolean isRecoverable)
      + boolean isRecoverable, + @ErrorCode + int errorCode)
      Creates an ExoPlaybackException of type ExoPlaybackException.TYPE_RENDERER for this renderer.
      @@ -1211,6 +1214,10 @@

      createRendererException

      cause - The cause of the exception.
      format - The current format used by the renderer. May be null.
      isRecoverable - If the error is recoverable by disabling and re-enabling the renderer.
      +
      errorCode - A PlaybackException.ErrorCode to identify the cause of the playback + failure.
      +
      Returns:
      +
      The created instance.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/Bundleable.html b/docs/doc/reference/com/google/android/exoplayer2/Bundleable.html index 9958edb4f22..604d17d2910 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/Bundleable.html +++ b/docs/doc/reference/com/google/android/exoplayer2/Bundleable.html @@ -122,7 +122,7 @@

    Interface Bundleable

  • All Known Implementing Classes:
    -
    AbstractConcatenatedTimeline, AdPlaybackState, AdPlaybackState.AdGroup, AudioAttributes, DeviceInfo, ExoPlaybackException, FakeMediaSource.InitialTimeline, FakeTimeline, ForwardingTimeline, HeartRating, MaskingMediaSource.PlaceholderTimeline, MediaItem, MediaItem.ClippingProperties, MediaItem.LiveConfiguration, MediaMetadata, NoUidTimeline, PercentageRating, PlaybackParameters, Player.PositionInfo, Rating, SinglePeriodAdTimeline, SinglePeriodTimeline, StarRating, ThumbRating, Timeline, Timeline.Period, Timeline.Window, VideoSize
    +
    AbstractConcatenatedTimeline, AdPlaybackState, AdPlaybackState.AdGroup, AudioAttributes, Cue, DeviceInfo, ExoPlaybackException, FakeMediaSource.InitialTimeline, FakeTimeline, ForwardingTimeline, HeartRating, MaskingMediaSource.PlaceholderTimeline, MediaItem, MediaItem.ClippingProperties, MediaItem.LiveConfiguration, MediaMetadata, NoUidTimeline, PercentageRating, PlaybackException, PlaybackParameters, Player.Commands, Player.PositionInfo, Rating, SinglePeriodAdTimeline, SinglePeriodTimeline, StarRating, ThumbRating, Timeline, Timeline.Period, Timeline.RemotableTimeline, Timeline.Window, VideoSize

    public interface Bundleable
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/CronetEngineWrapper.CronetEngineSource.html b/docs/doc/reference/com/google/android/exoplayer2/C.DataType.html similarity index 67% rename from docs/doc/reference/com/google/android/exoplayer2/ext/cronet/CronetEngineWrapper.CronetEngineSource.html rename to docs/doc/reference/com/google/android/exoplayer2/C.DataType.html index ac5f3b8df97..cf3775891dd 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/CronetEngineWrapper.CronetEngineSource.html +++ b/docs/doc/reference/com/google/android/exoplayer2/C.DataType.html @@ -2,30 +2,30 @@ -CronetEngineWrapper.CronetEngineSource (ExoPlayer library) +C.DataType (ExoPlayer library) - - - - - + + + + + - - + +
  • Constructors 
    ConstructorModifierConstructor Description
    protected BasePlayer()  
    protected Player.Commands getAvailableCommands​(Player.Commands permanentAvailableCommands)  +
    Returns the Player.Commands available in the player.
    +
    int
    ObjectgetCurrentTag() - -
    MediaItem getMediaItemAt​(int index)
    Returns the MediaItem at the given index.
    int getMediaItemCount()
    Returns the number of media items in the playlist.
    int getNextWindowIndex() -
    Returns the index of the window that will be played if Player.next() is called, which may - depend on the current repeat mode and whether shuffle mode is enabled.
    +
    Returns the index of the window that will be played if Player.seekToNextWindow() is called, + which may depend on the current repeat mode and whether shuffle mode is enabled.
    +
    intgetPreviousWindowIndex() +
    Returns the index of the window that will be played if Player.seekToPreviousWindow() is + called, which may depend on the current repeat mode and whether shuffle mode is enabled.
    ExoPlaybackExceptiongetPlaybackError()booleanhasNext() -
    Deprecated. - -
    +
    Deprecated.
    intgetPreviousWindowIndex()booleanhasNextWindow() -
    Returns the index of the window that will be played if Player.previous() is called, which may - depend on the current repeat mode and whether shuffle mode is enabled.
    +
    Returns whether a next window exists, which may depend on the current repeat mode and whether + shuffle mode is enabled.
    booleanhasNext()hasPrevious() -
    Returns whether a next window exists, which may depend on the current repeat mode and whether - shuffle mode is enabled.
    +
    Deprecated.
    booleanhasPrevious()hasPreviousWindow()
    Returns whether a previous window exists, which may depend on the current repeat mode and whether shuffle mode is enabled.
    @@ -416,8 +415,7 @@

    Method Summary

    void next() -
    Seeks to the default position of the next window, which may depend on the current repeat mode - and whether shuffle mode is enabled.
    +
    Deprecated.
    void previous() -
    Seeks to the default position of the previous window, which may depend on the current repeat - mode and whether shuffle mode is enabled.
    +
    Deprecated.
    voidseekBack() +
    Seeks back in the current window by Player.getSeekBackIncrement() milliseconds.
    +
    voidseekForward() +
    Seeks forward in the current window by Player.getSeekForwardIncrement() milliseconds.
    +
    void seekTo​(long positionMs)
    Seeks to a position specified in milliseconds in the current window.
    void seekToDefaultPosition()
    Seeks to the default position associated with the current window.
    void seekToDefaultPosition​(int windowIndex)
    Seeks to the default position associated with the specified window.
    voidseekToNext() +
    Seeks to a later position in the current or next window (if available).
    +
    voidseekToNextWindow() +
    Seeks to the default position of the next window, which may depend on the current repeat mode + and whether shuffle mode is enabled.
    +
    voidseekToPrevious() +
    Seeks to an earlier position in the current or previous window (if available).
    +
    voidseekToPreviousWindow() +
    Seeks to the default position of the previous window, which may depend on the current repeat + mode and whether shuffle mode is enabled.
    +
    void setMediaItem​(MediaItem mediaItem) @@ -478,7 +519,7 @@

    Method Summary

    default position.
    void setMediaItem​(MediaItem mediaItem, boolean resetPosition)
    void setMediaItem​(MediaItem mediaItem, long startPositionMs)
    void setMediaItems​(List<MediaItem> mediaItems) @@ -502,14 +543,14 @@

    Method Summary

    the default position.
    void setPlaybackSpeed​(float speed)
    Changes the rate at which playback occurs.
    void stop() @@ -529,7 +570,7 @@

    Methods inherited from class java.lang.Player

    -addListener, addListener, addMediaItems, clearVideoSurface, clearVideoSurface, clearVideoSurfaceHolder, clearVideoSurfaceView, clearVideoTextureView, decreaseDeviceVolume, getApplicationLooper, getAudioAttributes, getAvailableCommands, getBufferedPosition, getContentBufferedPosition, getContentPosition, getCurrentAdGroupIndex, getCurrentAdIndexInAdGroup, getCurrentCues, getCurrentPeriodIndex, getCurrentPosition, getCurrentStaticMetadata, getCurrentTimeline, getCurrentTrackGroups, getCurrentTrackSelections, getCurrentWindowIndex, getDeviceInfo, getDeviceVolume, getDuration, getMediaMetadata, getPlaybackParameters, getPlaybackState, getPlaybackSuppressionReason, getPlayerError, getPlayWhenReady, getRepeatMode, getShuffleModeEnabled, getTotalBufferedDuration, getVideoSize, getVolume, increaseDeviceVolume, isDeviceMuted, isLoading, isPlayingAd, moveMediaItems, prepare, release, removeListener, removeListener, removeMediaItems, seekTo, setDeviceMuted, setDeviceVolume, setMediaItems, setMediaItems, setPlaybackParameters, setPlayWhenReady, setRepeatMode, setShuffleModeEnabled, setVideoSurface, setVideoSurfaceHolder, setVideoSurfaceView, setVideoTextureView, setVolume, stop +addListener, addListener, addMediaItems, clearVideoSurface, clearVideoSurface, clearVideoSurfaceHolder, clearVideoSurfaceView, clearVideoTextureView, decreaseDeviceVolume, getApplicationLooper, getAudioAttributes, getAvailableCommands, getBufferedPosition, getContentBufferedPosition, getContentPosition, getCurrentAdGroupIndex, getCurrentAdIndexInAdGroup, getCurrentCues, getCurrentPeriodIndex, getCurrentPosition, getCurrentStaticMetadata, getCurrentTimeline, getCurrentTrackGroups, getCurrentTrackSelections, getCurrentWindowIndex, getDeviceInfo, getDeviceVolume, getDuration, getMaxSeekToPreviousPosition, getMediaMetadata, getPlaybackParameters, getPlaybackState, getPlaybackSuppressionReason, getPlayerError, getPlaylistMetadata, getPlayWhenReady, getRepeatMode, getSeekBackIncrement, getSeekForwardIncrement, getShuffleModeEnabled, getTotalBufferedDuration, getVideoSize, getVolume, increaseDeviceVolume, isDeviceMuted, isLoading, isPlayingAd, moveMediaItems, prepare, release, removeListener, removeListener, removeMediaItems, seekTo, setDeviceMuted, setDeviceVolume, setMediaItems, setMediaItems, setPlaybackParameters, setPlaylistMetadata, setPlayWhenReady, setRepeatMode, setShuffleModeEnabled, setVideoSurface, setVideoSurfaceHolder, setVideoSurfaceView, setVideoTextureView, setVolume, stop @@ -572,7 +613,7 @@

    Constructor Detail

    • BasePlayer

      -
      public BasePlayer()
      +
      protected BasePlayer()
    @@ -780,11 +821,12 @@

    isCommandAvailable

    This method does not execute the command. -

    Executing a command that is not available (for example, calling Player.next() if Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM is unavailable) will neither throw an exception nor generate - a Player.getPlayerError() player error}. +

    Executing a command that is not available (for example, calling Player.seekToNextWindow() + if Player.COMMAND_SEEK_TO_NEXT_WINDOW is unavailable) will neither throw an exception nor + generate a Player.getPlayerError() player error}. -

    Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM and Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM - are unavailable if there is no such MediaItem. +

    Player.COMMAND_SEEK_TO_PREVIOUS_WINDOW and Player.COMMAND_SEEK_TO_NEXT_WINDOW are + unavailable if there is no such MediaItem.

    Specified by:
    isCommandAvailable in interface Player
    @@ -797,24 +839,6 @@

    isCommandAvailable

    - - - - @@ -928,14 +952,59 @@

    seekTo

    + + + + + + + +
    • hasPrevious

      -
      public final boolean hasPrevious()
      -
      Description copied from interface: Player
      +
      @Deprecated
      +public final boolean hasPrevious()
      +
      Deprecated.
      +
      +
      Specified by:
      +
      hasPrevious in interface Player
      +
      +
    • +
    + + + +
      +
    • +

      hasPreviousWindow

      +
      public final boolean hasPreviousWindow()
      +
      Description copied from interface: Player
      Returns whether a previous window exists, which may depend on the current repeat mode and whether shuffle mode is enabled. @@ -944,7 +1013,7 @@

      hasPrevious

      details.
      Specified by:
      -
      hasPrevious in interface Player
      +
      hasPreviousWindow in interface Player
    @@ -954,18 +1023,60 @@

    hasPrevious

    • previous

      -
      public final void previous()
      -
      Description copied from interface: Player
      +
      @Deprecated
      +public final void previous()
      +
      Deprecated.
      +
      +
      Specified by:
      +
      previous in interface Player
      +
      +
    • +
    + + + + + + + +
      +
    • +

      seekToPrevious

      +
      public final void seekToPrevious()
      +
      Description copied from interface: Player
      +
      Seeks to an earlier position in the current or previous window (if available). More precisely: + +
      +
      +
      Specified by:
      +
      seekToPrevious in interface Player
    @@ -975,8 +1086,23 @@

    previous

    • hasNext

      -
      public final boolean hasNext()
      -
      Description copied from interface: Player
      +
      @Deprecated
      +public final boolean hasNext()
      +
      Deprecated.
      +
      +
      Specified by:
      +
      hasNext in interface Player
      +
      +
    • +
    + + + +
      +
    • +

      hasNextWindow

      +
      public final boolean hasNextWindow()
      +
      Description copied from interface: Player
      Returns whether a next window exists, which may depend on the current repeat mode and whether shuffle mode is enabled. @@ -985,7 +1111,7 @@

      hasNext

      details.
      Specified by:
      -
      hasNext in interface Player
      +
      hasNextWindow in interface Player
    @@ -995,17 +1121,56 @@

    hasNext

    • next

      -
      public final void next()
      -
      Description copied from interface: Player
      +
      @Deprecated
      +public final void next()
      +
      Deprecated.
      +
      +
      Specified by:
      +
      next in interface Player
      +
      +
    • +
    + + + + + + + +
      +
    • +

      seekToNext

      +
      public final void seekToNext()
      +
      Description copied from interface: Player
      +
      Seeks to a later position in the current or next window (if available). More precisely: + +
        +
      • If the timeline is empty or seeking is not possible, does nothing. +
      • Otherwise, if a next window exists, seeks to the default + position of the next window. +
      • Otherwise, if the current window is live and has not + ended, seeks to the live edge of the current window. +
      • Otherwise, does nothing. +
      +
      +
      Specified by:
      +
      seekToNext in interface Player
    @@ -1061,8 +1226,8 @@

    stop

    getNextWindowIndex

    public final int getNextWindowIndex()
    Description copied from interface: Player
    -
    Returns the index of the window that will be played if Player.next() is called, which may - depend on the current repeat mode and whether shuffle mode is enabled. Returns C.INDEX_UNSET if Player.hasNext() is false. +
    Returns the index of the window that will be played if Player.seekToNextWindow() is called, + which may depend on the current repeat mode and whether shuffle mode is enabled. Returns C.INDEX_UNSET if Player.hasNextWindow() is false.

    Note: When the repeat mode is Player.REPEAT_MODE_ONE, this method behaves the same as when the current repeat mode is Player.REPEAT_MODE_OFF. See Player.REPEAT_MODE_ONE for more @@ -1081,8 +1246,9 @@

    getNextWindowIndex

    getPreviousWindowIndex

    public final int getPreviousWindowIndex()
    Description copied from interface: Player
    -
    Returns the index of the window that will be played if Player.previous() is called, which may - depend on the current repeat mode and whether shuffle mode is enabled. Returns C.INDEX_UNSET if Player.hasPrevious() is false. +
    Returns the index of the window that will be played if Player.seekToPreviousWindow() is + called, which may depend on the current repeat mode and whether shuffle mode is enabled. + Returns C.INDEX_UNSET if Player.hasPreviousWindow() is false.

    Note: When the repeat mode is Player.REPEAT_MODE_ONE, this method behaves the same as when the current repeat mode is Player.REPEAT_MODE_OFF. See Player.REPEAT_MODE_ONE for more @@ -1093,25 +1259,6 @@

    getPreviousWindowIndex

    - - - - @@ -1293,6 +1440,13 @@

    getContentDuration

  • getAvailableCommands

    protected Player.Commands getAvailableCommands​(Player.Commands permanentAvailableCommands)
    +
    Returns the Player.Commands available in the player.
    +
    +
    Parameters:
    +
    permanentAvailableCommands - The commands permanently available in the player.
    +
    Returns:
    +
    The available Player.Commands.
    +
  • diff --git a/docs/doc/reference/com/google/android/exoplayer2/BaseRenderer.html b/docs/doc/reference/com/google/android/exoplayer2/BaseRenderer.html index 15fd370cd3a..98a6bf450f5 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/BaseRenderer.html +++ b/docs/doc/reference/com/google/android/exoplayer2/BaseRenderer.html @@ -232,8 +232,10 @@

    Method Summary

    protected ExoPlaybackExceptioncreateRendererException​(Throwable cause, - Format format)createRendererException​(Throwable cause, + Format format, + boolean isRecoverable, + int errorCode)
    Creates an ExoPlaybackException of type ExoPlaybackException.TYPE_RENDERER for this renderer.
    @@ -241,9 +243,9 @@

    Method Summary

    protected ExoPlaybackExceptioncreateRendererException​(Throwable cause, +createRendererException​(Throwable cause, Format format, - boolean isRecoverable)
    Creates an ExoPlaybackException of type ExoPlaybackException.TYPE_RENDERER for this renderer.
    @@ -317,8 +319,7 @@

    Method Summary

    long getReadingPositionUs() -
    Returns the renderer time up to which the renderer has read samples from the current SampleStream, in microseconds, or C.TIME_END_OF_SOURCE if the renderer has read the - current SampleStream to the end.
    +
    Returns the renderer time up to which the renderer has read samples, in microseconds, or C.TIME_END_OF_SOURCE if the renderer has read the current SampleStream to the end.
    void handleMessage​(int messageType, - Object payload)
    Handles a message delivered to the target.
    + + + + + + + + + +
    Constructors 
    ConstructorDescription
    ForwardingPlayer​(Player player) +
    Creates a new instance that forwards all operations to player.
    +
    + + + + +
    + +
    + + + +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          ForwardingPlayer

          +
          public ForwardingPlayer​(Player player)
          +
          Creates a new instance that forwards all operations to player.
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getApplicationLooper

          +
          public Looper getApplicationLooper()
          +
          Description copied from interface: Player
          +
          Returns the Looper associated with the application thread that's used to access the + player and on which player events are received.
          +
          +
          Specified by:
          +
          getApplicationLooper in interface Player
          +
          +
        • +
        + + + +
          +
        • +

          addListener

          +
          public void addListener​(Player.EventListener listener)
          +
          Description copied from interface: Player
          +
          Registers a listener to receive events from the player. + +

          The listener's methods will be called on the thread that was used to construct the player. + However, if the thread used to construct the player does not have a Looper, then the + listener will be called on the main thread.

          +
          +
          Specified by:
          +
          addListener in interface Player
          +
          Parameters:
          +
          listener - The listener to register.
          +
          +
        • +
        + + + +
          +
        • +

          addListener

          +
          public void addListener​(Player.Listener listener)
          +
          Description copied from interface: Player
          +
          Registers a listener to receive all events from the player. + +

          The listener's methods will be called on the thread that was used to construct the player. + However, if the thread used to construct the player does not have a Looper, then the + listener will be called on the main thread.

          +
          +
          Specified by:
          +
          addListener in interface Player
          +
          Parameters:
          +
          listener - The listener to register.
          +
          +
        • +
        + + + + + + + +
          +
        • +

          removeListener

          +
          public void removeListener​(Player.Listener listener)
          +
          Description copied from interface: Player
          +
          Unregister a listener registered through Player.addListener(Listener). The listener will no + longer receive events.
          +
          +
          Specified by:
          +
          removeListener in interface Player
          +
          Parameters:
          +
          listener - The listener to unregister.
          +
          +
        • +
        + + + +
          +
        • +

          setMediaItems

          +
          public void setMediaItems​(List<MediaItem> mediaItems)
          +
          Description copied from interface: Player
          +
          Clears the playlist, adds the specified MediaItems and resets the position to + the default position.
          +
          +
          Specified by:
          +
          setMediaItems in interface Player
          +
          Parameters:
          +
          mediaItems - The new MediaItems.
          +
          +
        • +
        + + + + + + + +
          +
        • +

          setMediaItems

          +
          public void setMediaItems​(List<MediaItem> mediaItems,
          +                          int startWindowIndex,
          +                          long startPositionMs)
          +
          Description copied from interface: Player
          +
          Clears the playlist and adds the specified MediaItems.
          +
          +
          Specified by:
          +
          setMediaItems in interface Player
          +
          Parameters:
          +
          mediaItems - The new MediaItems.
          +
          startWindowIndex - The window index to start playback from. If C.INDEX_UNSET is + passed, the current position is not reset.
          +
          startPositionMs - The position in milliseconds to start playback from. If C.TIME_UNSET is passed, the default position of the given window is used. In any case, if + startWindowIndex is set to C.INDEX_UNSET, this parameter is ignored and the + position is not reset at all.
          +
          +
        • +
        + + + +
          +
        • +

          setMediaItem

          +
          public void setMediaItem​(MediaItem mediaItem)
          +
          Description copied from interface: Player
          +
          Clears the playlist, adds the specified MediaItem and resets the position to the + default position.
          +
          +
          Specified by:
          +
          setMediaItem in interface Player
          +
          Parameters:
          +
          mediaItem - The new MediaItem.
          +
          +
        • +
        + + + +
          +
        • +

          setMediaItem

          +
          public void setMediaItem​(MediaItem mediaItem,
          +                         long startPositionMs)
          +
          Description copied from interface: Player
          +
          Clears the playlist and adds the specified MediaItem.
          +
          +
          Specified by:
          +
          setMediaItem in interface Player
          +
          Parameters:
          +
          mediaItem - The new MediaItem.
          +
          startPositionMs - The position in milliseconds to start playback from.
          +
          +
        • +
        + + + + + + + +
          +
        • +

          addMediaItem

          +
          public void addMediaItem​(MediaItem mediaItem)
          +
          Description copied from interface: Player
          +
          Adds a media item to the end of the playlist.
          +
          +
          Specified by:
          +
          addMediaItem in interface Player
          +
          Parameters:
          +
          mediaItem - The MediaItem to add.
          +
          +
        • +
        + + + +
          +
        • +

          addMediaItem

          +
          public void addMediaItem​(int index,
          +                         MediaItem mediaItem)
          +
          Description copied from interface: Player
          +
          Adds a media item at the given index of the playlist.
          +
          +
          Specified by:
          +
          addMediaItem in interface Player
          +
          Parameters:
          +
          index - The index at which to add the media item. If the index is larger than the size of + the playlist, the media item is added to the end of the playlist.
          +
          mediaItem - The MediaItem to add.
          +
          +
        • +
        + + + +
          +
        • +

          addMediaItems

          +
          public void addMediaItems​(List<MediaItem> mediaItems)
          +
          Description copied from interface: Player
          +
          Adds a list of media items to the end of the playlist.
          +
          +
          Specified by:
          +
          addMediaItems in interface Player
          +
          Parameters:
          +
          mediaItems - The MediaItems to add.
          +
          +
        • +
        + + + +
          +
        • +

          addMediaItems

          +
          public void addMediaItems​(int index,
          +                          List<MediaItem> mediaItems)
          +
          Description copied from interface: Player
          +
          Adds a list of media items at the given index of the playlist.
          +
          +
          Specified by:
          +
          addMediaItems in interface Player
          +
          Parameters:
          +
          index - The index at which to add the media items. If the index is larger than the size of + the playlist, the media items are added to the end of the playlist.
          +
          mediaItems - The MediaItems to add.
          +
          +
        • +
        + + + +
          +
        • +

          moveMediaItem

          +
          public void moveMediaItem​(int currentIndex,
          +                          int newIndex)
          +
          Description copied from interface: Player
          +
          Moves the media item at the current index to the new index.
          +
          +
          Specified by:
          +
          moveMediaItem in interface Player
          +
          Parameters:
          +
          currentIndex - The current index of the media item to move.
          +
          newIndex - The new index of the media item. If the new index is larger than the size of + the playlist the item is moved to the end of the playlist.
          +
          +
        • +
        + + + +
          +
        • +

          moveMediaItems

          +
          public void moveMediaItems​(int fromIndex,
          +                           int toIndex,
          +                           int newIndex)
          +
          Description copied from interface: Player
          +
          Moves the media item range to the new index.
          +
          +
          Specified by:
          +
          moveMediaItems in interface Player
          +
          Parameters:
          +
          fromIndex - The start of the range to move.
          +
          toIndex - The first item not to be included in the range (exclusive).
          +
          newIndex - The new index of the first media item of the range. If the new index is larger + than the size of the remaining playlist after removing the range, the range is moved to the + end of the playlist.
          +
          +
        • +
        + + + +
          +
        • +

          removeMediaItem

          +
          public void removeMediaItem​(int index)
          +
          Description copied from interface: Player
          +
          Removes the media item at the given index of the playlist.
          +
          +
          Specified by:
          +
          removeMediaItem in interface Player
          +
          Parameters:
          +
          index - The index at which to remove the media item.
          +
          +
        • +
        + + + +
          +
        • +

          removeMediaItems

          +
          public void removeMediaItems​(int fromIndex,
          +                             int toIndex)
          +
          Description copied from interface: Player
          +
          Removes a range of media items from the playlist.
          +
          +
          Specified by:
          +
          removeMediaItems in interface Player
          +
          Parameters:
          +
          fromIndex - The index at which to start removing media items.
          +
          toIndex - The index of the first item to be kept (exclusive). If the index is larger than + the size of the playlist, media items to the end of the playlist are removed.
          +
          +
        • +
        + + + +
          +
        • +

          clearMediaItems

          +
          public void clearMediaItems()
          +
          Description copied from interface: Player
          +
          Clears the playlist.
          +
          +
          Specified by:
          +
          clearMediaItems in interface Player
          +
          +
        • +
        + + + + + + + + + + + +
          +
        • +

          prepare

          +
          public void prepare()
          +
          Description copied from interface: Player
          +
          Prepares the player.
          +
          +
          Specified by:
          +
          prepare in interface Player
          +
          +
        • +
        + + + + + + + + + + + + + + + + + + + + + + + +
          +
        • +

          pause

          +
          public void pause()
          +
          Description copied from interface: Player
          +
          Pauses playback. Equivalent to setPlayWhenReady(false).
          +
          +
          Specified by:
          +
          pause in interface Player
          +
          +
        • +
        + + + +
          +
        • +

          setPlayWhenReady

          +
          public void setPlayWhenReady​(boolean playWhenReady)
          +
          Description copied from interface: Player
          +
          Sets whether playback should proceed when Player.getPlaybackState() == Player.STATE_READY. + +

          If the player is already in the ready state then this method pauses and resumes playback.

          +
          +
          Specified by:
          +
          setPlayWhenReady in interface Player
          +
          Parameters:
          +
          playWhenReady - Whether playback should proceed when ready.
          +
          +
        • +
        + + + + + + + +
          +
        • +

          setRepeatMode

          +
          public void setRepeatMode​(@RepeatMode
          +                          int repeatMode)
          +
          Description copied from interface: Player
          +
          Sets the Player.RepeatMode to be used for playback.
          +
          +
          Specified by:
          +
          setRepeatMode in interface Player
          +
          Parameters:
          +
          repeatMode - The repeat mode.
          +
          +
        • +
        + + + + + + + +
          +
        • +

          setShuffleModeEnabled

          +
          public void setShuffleModeEnabled​(boolean shuffleModeEnabled)
          +
          Description copied from interface: Player
          +
          Sets whether shuffling of windows is enabled.
          +
          +
          Specified by:
          +
          setShuffleModeEnabled in interface Player
          +
          Parameters:
          +
          shuffleModeEnabled - Whether shuffling is enabled.
          +
          +
        • +
        + + + + + + + + + + + +
          +
        • +

          seekToDefaultPosition

          +
          public void seekToDefaultPosition()
          +
          Description copied from interface: Player
          +
          Seeks to the default position associated with the current window. The position can depend on + the type of media being played. For live streams it will typically be the live edge of the + window. For other streams it will typically be the start of the window.
          +
          +
          Specified by:
          +
          seekToDefaultPosition in interface Player
          +
          +
        • +
        + + + +
          +
        • +

          seekToDefaultPosition

          +
          public void seekToDefaultPosition​(int windowIndex)
          +
          Description copied from interface: Player
          +
          Seeks to the default position associated with the specified window. The position can depend on + the type of media being played. For live streams it will typically be the live edge of the + window. For other streams it will typically be the start of the window.
          +
          +
          Specified by:
          +
          seekToDefaultPosition in interface Player
          +
          Parameters:
          +
          windowIndex - The index of the window whose associated default position should be seeked + to.
          +
          +
        • +
        + + + +
          +
        • +

          seekTo

          +
          public void seekTo​(long positionMs)
          +
          Description copied from interface: Player
          +
          Seeks to a position specified in milliseconds in the current window.
          +
          +
          Specified by:
          +
          seekTo in interface Player
          +
          Parameters:
          +
          positionMs - The seek position in the current window, or C.TIME_UNSET to seek to + the window's default position.
          +
          +
        • +
        + + + +
          +
        • +

          seekTo

          +
          public void seekTo​(int windowIndex,
          +                   long positionMs)
          +
          Description copied from interface: Player
          +
          Seeks to a position specified in milliseconds in the specified window.
          +
          +
          Specified by:
          +
          seekTo in interface Player
          +
          Parameters:
          +
          windowIndex - The index of the window.
          +
          positionMs - The seek position in the specified window, or C.TIME_UNSET to seek to + the window's default position.
          +
          +
        • +
        + + + + + + + + + + + + + + + + + + + + + + + +
          +
        • +

          hasPreviousWindow

          +
          public boolean hasPreviousWindow()
          +
          Description copied from interface: Player
          +
          Returns whether a previous window exists, which may depend on the current repeat mode and + whether shuffle mode is enabled. + +

          Note: When the repeat mode is Player.REPEAT_MODE_ONE, this method behaves the same as when + the current repeat mode is Player.REPEAT_MODE_OFF. See Player.REPEAT_MODE_ONE for more + details.

          +
          +
          Specified by:
          +
          hasPreviousWindow in interface Player
          +
          +
        • +
        + + + + + + + + + + + +
          +
        • +

          seekToPrevious

          +
          public void seekToPrevious()
          +
          Description copied from interface: Player
          +
          Seeks to an earlier position in the current or previous window (if available). More precisely: + +
          +
          +
          Specified by:
          +
          seekToPrevious in interface Player
          +
          +
        • +
        + + + + + + + + + + + +
          +
        • +

          hasNextWindow

          +
          public boolean hasNextWindow()
          +
          Description copied from interface: Player
          +
          Returns whether a next window exists, which may depend on the current repeat mode and whether + shuffle mode is enabled. + +

          Note: When the repeat mode is Player.REPEAT_MODE_ONE, this method behaves the same as when + the current repeat mode is Player.REPEAT_MODE_OFF. See Player.REPEAT_MODE_ONE for more + details.

          +
          +
          Specified by:
          +
          hasNextWindow in interface Player
          +
          +
        • +
        + + + +
          +
        • +

          next

          +
          @Deprecated
          +public void next()
          +
          Deprecated.
          +
          +
          Specified by:
          +
          next in interface Player
          +
          +
        • +
        + + + + + + + +
          +
        • +

          seekToNext

          +
          public void seekToNext()
          +
          Description copied from interface: Player
          +
          Seeks to a later position in the current or next window (if available). More precisely: + +
            +
          • If the timeline is empty or seeking is not possible, does nothing. +
          • Otherwise, if a next window exists, seeks to the default + position of the next window. +
          • Otherwise, if the current window is live and has not + ended, seeks to the live edge of the current window. +
          • Otherwise, does nothing. +
          +
          +
          Specified by:
          +
          seekToNext in interface Player
          +
          +
        • +
        + + + + + + + +
          +
        • +

          setPlaybackSpeed

          +
          public void setPlaybackSpeed​(float speed)
          +
          Description copied from interface: Player
          +
          Changes the rate at which playback occurs. The pitch is not changed. + +

          This is equivalent to + setPlaybackParameters(getPlaybackParameters().withSpeed(speed)).

          +
          +
          Specified by:
          +
          setPlaybackSpeed in interface Player
          +
          Parameters:
          +
          speed - The linear factor by which playback will be sped up. Must be higher than 0. 1 is + normal speed, 2 is twice as fast, 0.5 is half normal speed...
          +
          +
        • +
        + + + + + + + +
          +
        • +

          stop

          +
          public void stop()
          +
          Description copied from interface: Player
          +
          Stops playback without resetting the player. Use Player.pause() rather than this method if + the intention is to pause playback. + +

          Calling this method will cause the playback state to transition to Player.STATE_IDLE. The + player instance can still be used, and Player.release() must still be called on the player if + it's no longer required. + +

          Calling this method does not clear the playlist, reset the playback position or the playback + error.

          +
          +
          Specified by:
          +
          stop in interface Player
          +
          +
        • +
        + + + +
          +
        • +

          stop

          +
          public void stop​(boolean reset)
          +
          +
          Specified by:
          +
          stop in interface Player
          +
          +
        • +
        + + + +
          +
        • +

          release

          +
          public void release()
          +
          Description copied from interface: Player
          +
          Releases the player. This method must be called when the player is no longer required. The + player must not be used after calling this method.
          +
          +
          Specified by:
          +
          release in interface Player
          +
          +
        • +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          +
        • +

          getCurrentManifest

          +
          @Nullable
          +public Object getCurrentManifest()
          +
          Description copied from interface: Player
          +
          Returns the current manifest. The type depends on the type of media being played. May be null.
          +
          +
          Specified by:
          +
          getCurrentManifest in interface Player
          +
          +
        • +
        + + + + + + + +
          +
        • +

          getCurrentPeriodIndex

          +
          public int getCurrentPeriodIndex()
          +
          Description copied from interface: Player
          +
          Returns the index of the period currently being played.
          +
          +
          Specified by:
          +
          getCurrentPeriodIndex in interface Player
          +
          +
        • +
        + + + + + + + + + + + + + + + + + + + +
          +
        • +

          getMediaItemCount

          +
          public int getMediaItemCount()
          +
          Description copied from interface: Player
          +
          Returns the number of media items in the playlist.
          +
          +
          Specified by:
          +
          getMediaItemCount in interface Player
          +
          +
        • +
        + + + + + + + +
          +
        • +

          getDuration

          +
          public long getDuration()
          +
          Description copied from interface: Player
          +
          Returns the duration of the current content window or ad in milliseconds, or C.TIME_UNSET if the duration is not known.
          +
          +
          Specified by:
          +
          getDuration in interface Player
          +
          +
        • +
        + + + +
          +
        • +

          getCurrentPosition

          +
          public long getCurrentPosition()
          +
          Description copied from interface: Player
          +
          Returns the playback position in the current content window or ad, in milliseconds, or the + prospective position in milliseconds if the current timeline is + empty.
          +
          +
          Specified by:
          +
          getCurrentPosition in interface Player
          +
          +
        • +
        + + + +
          +
        • +

          getBufferedPosition

          +
          public long getBufferedPosition()
          +
          Description copied from interface: Player
          +
          Returns an estimate of the position in the current content window or ad up to which data is + buffered, in milliseconds.
          +
          +
          Specified by:
          +
          getBufferedPosition in interface Player
          +
          +
        • +
        + + + +
          +
        • +

          getBufferedPercentage

          +
          public int getBufferedPercentage()
          +
          Description copied from interface: Player
          +
          Returns an estimate of the percentage in the current content window or ad up to which data is + buffered, or 0 if no estimate is available.
          +
          +
          Specified by:
          +
          getBufferedPercentage in interface Player
          +
          +
        • +
        + + + +
          +
        • +

          getTotalBufferedDuration

          +
          public long getTotalBufferedDuration()
          +
          Description copied from interface: Player
          +
          Returns an estimate of the total buffered duration from the current position, in milliseconds. + This includes pre-buffered data for subsequent ads and windows.
          +
          +
          Specified by:
          +
          getTotalBufferedDuration in interface Player
          +
          +
        • +
        + + + + + + + + + + + +
          +
        • +

          getCurrentLiveOffset

          +
          public long getCurrentLiveOffset()
          +
          Description copied from interface: Player
          +
          Returns the offset of the current playback position from the live edge in milliseconds, or + C.TIME_UNSET if the current window isn't live or the + offset is unknown. + +

          The offset is calculated as currentTime - playbackPosition, so should usually be + positive. + +

          Note that this offset may rely on an accurate local time, so this method may return an + incorrect value if the difference between system clock and server clock is unknown.

          +
          +
          Specified by:
          +
          getCurrentLiveOffset in interface Player
          +
          +
        • +
        + + + + + + + +
          +
        • +

          isPlayingAd

          +
          public boolean isPlayingAd()
          +
          Description copied from interface: Player
          +
          Returns whether the player is currently playing an ad.
          +
          +
          Specified by:
          +
          isPlayingAd in interface Player
          +
          +
        • +
        + + + + + + + + + + + +
          +
        • +

          getContentDuration

          +
          public long getContentDuration()
          +
          Description copied from interface: Player
          +
          If Player.isPlayingAd() returns true, returns the duration of the current content + window in milliseconds, or C.TIME_UNSET if the duration is not known. If there is no ad + playing, the returned duration is the same as that returned by Player.getDuration().
          +
          +
          Specified by:
          +
          getContentDuration in interface Player
          +
          +
        • +
        + + + +
          +
        • +

          getContentPosition

          +
          public long getContentPosition()
          +
          Description copied from interface: Player
          +
          If Player.isPlayingAd() returns true, returns the content position that will be + played once all ads in the ad group have finished playing, in milliseconds. If there is no ad + playing, the returned position is the same as that returned by Player.getCurrentPosition().
          +
          +
          Specified by:
          +
          getContentPosition in interface Player
          +
          +
        • +
        + + + +
          +
        • +

          getContentBufferedPosition

          +
          public long getContentBufferedPosition()
          +
          Description copied from interface: Player
          +
          If Player.isPlayingAd() returns true, returns an estimate of the content position in + the current content window up to which data is buffered, in milliseconds. If there is no ad + playing, the returned position is the same as that returned by Player.getBufferedPosition().
          +
          +
          Specified by:
          +
          getContentBufferedPosition in interface Player
          +
          +
        • +
        + + + + + + + +
          +
        • +

          setVolume

          +
          public void setVolume​(float audioVolume)
          +
          Description copied from interface: Player
          +
          Sets the audio volume, with 0 being silence and 1 being unity gain (signal unchanged).
          +
          +
          Specified by:
          +
          setVolume in interface Player
          +
          Parameters:
          +
          audioVolume - Linear output gain to apply to all audio channels.
          +
          +
        • +
        + + + +
          +
        • +

          getVolume

          +
          public float getVolume()
          +
          Description copied from interface: Player
          +
          Returns the audio volume, with 0 being silence and 1 being unity gain (signal unchanged).
          +
          +
          Specified by:
          +
          getVolume in interface Player
          +
          Returns:
          +
          The linear gain applied to all audio channels.
          +
          +
        • +
        + + + + + + + + + + + +
          +
        • +

          clearVideoSurface

          +
          public void clearVideoSurface​(@Nullable
          +                              Surface surface)
          +
          Description copied from interface: Player
          +
          Clears the Surface onto which video is being rendered if it matches the one passed. + Else does nothing.
          +
          +
          Specified by:
          +
          clearVideoSurface in interface Player
          +
          Parameters:
          +
          surface - The surface to clear.
          +
          +
        • +
        + + + + + + + + + + + +
          +
        • +

          clearVideoSurfaceHolder

          +
          public void clearVideoSurfaceHolder​(@Nullable
          +                                    SurfaceHolder surfaceHolder)
          +
          Description copied from interface: Player
          +
          Clears the SurfaceHolder that holds the Surface onto which video is being + rendered if it matches the one passed. Else does nothing.
          +
          +
          Specified by:
          +
          clearVideoSurfaceHolder in interface Player
          +
          Parameters:
          +
          surfaceHolder - The surface holder to clear.
          +
          +
        • +
        + + + + + + + +
          +
        • +

          clearVideoSurfaceView

          +
          public void clearVideoSurfaceView​(@Nullable
          +                                  SurfaceView surfaceView)
          +
          Description copied from interface: Player
          +
          Clears the SurfaceView onto which video is being rendered if it matches the one passed. + Else does nothing.
          +
          +
          Specified by:
          +
          clearVideoSurfaceView in interface Player
          +
          Parameters:
          +
          surfaceView - The texture view to clear.
          +
          +
        • +
        + + + + + + + +
          +
        • +

          clearVideoTextureView

          +
          public void clearVideoTextureView​(@Nullable
          +                                  TextureView textureView)
          +
          Description copied from interface: Player
          +
          Clears the TextureView onto which video is being rendered if it matches the one passed. + Else does nothing.
          +
          +
          Specified by:
          +
          clearVideoTextureView in interface Player
          +
          Parameters:
          +
          textureView - The texture view to clear.
          +
          +
        • +
        + + + +
          +
        • +

          getCurrentCues

          +
          public List<Cue> getCurrentCues()
          +
          Description copied from interface: Player
          +
          Returns the current Cues. This list may be empty.
          +
          +
          Specified by:
          +
          getCurrentCues in interface Player
          +
          +
        • +
        + + + +
          +
        • +

          getDeviceInfo

          +
          public DeviceInfo getDeviceInfo()
          +
          Description copied from interface: Player
          +
          Gets the device information.
          +
          +
          Specified by:
          +
          getDeviceInfo in interface Player
          +
          +
        • +
        + + + + + + + +
          +
        • +

          isDeviceMuted

          +
          public boolean isDeviceMuted()
          +
          Description copied from interface: Player
          +
          Gets whether the device is muted or not.
          +
          +
          Specified by:
          +
          isDeviceMuted in interface Player
          +
          +
        • +
        + + + +
          +
        • +

          setDeviceVolume

          +
          public void setDeviceVolume​(int volume)
          +
          Description copied from interface: Player
          +
          Sets the volume of the device.
          +
          +
          Specified by:
          +
          setDeviceVolume in interface Player
          +
          Parameters:
          +
          volume - The volume to set.
          +
          +
        • +
        + + + +
          +
        • +

          increaseDeviceVolume

          +
          public void increaseDeviceVolume()
          +
          Description copied from interface: Player
          +
          Increases the volume of the device.
          +
          +
          Specified by:
          +
          increaseDeviceVolume in interface Player
          +
          +
        • +
        + + + +
          +
        • +

          decreaseDeviceVolume

          +
          public void decreaseDeviceVolume()
          +
          Description copied from interface: Player
          +
          Decreases the volume of the device.
          +
          +
          Specified by:
          +
          decreaseDeviceVolume in interface Player
          +
          +
        • +
        + + + +
          +
        • +

          setDeviceMuted

          +
          public void setDeviceMuted​(boolean muted)
          +
          Description copied from interface: Player
          +
          Sets the mute state of the device.
          +
          +
          Specified by:
          +
          setDeviceMuted in interface Player
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    + + + + + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/MediaItem.html b/docs/doc/reference/com/google/android/exoplayer2/MediaItem.html index 06057b42ffb..9e476679f9d 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/MediaItem.html +++ b/docs/doc/reference/com/google/android/exoplayer2/MediaItem.html @@ -253,27 +253,34 @@

    Field Summary

    +static MediaItem +EMPTY + +
    Empty MediaItem.
    + + + MediaItem.LiveConfiguration liveConfiguration
    The live playback configuration.
    - + String mediaId
    Identifies the media item.
    - + MediaMetadata mediaMetadata
    The media metadata.
    - + MediaItem.PlaybackProperties playbackProperties @@ -374,6 +381,16 @@

    DEFAULT_MEDIA_ID

    + + + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/MediaMetadata.Builder.html b/docs/doc/reference/com/google/android/exoplayer2/MediaMetadata.Builder.html index a081e3e4eed..cceffedcbff 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/MediaMetadata.Builder.html +++ b/docs/doc/reference/com/google/android/exoplayer2/MediaMetadata.Builder.html @@ -25,8 +25,8 @@ catch(err) { } //--> -var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10}; -var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]}; +var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":42,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10,"i21":10,"i22":10,"i23":10,"i24":10,"i25":10,"i26":10,"i27":10,"i28":10,"i29":10,"i30":10,"i31":10,"i32":10,"i33":10,"i34":10,"i35":42}; +var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"],32:["t6","Deprecated Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; var tableTab = "tableTab"; @@ -171,7 +171,7 @@

    Constructor Summary

    Method Summary

    - + @@ -186,142 +186,254 @@

    Method Summary

    + + + + + - + - + - + - + - + - + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + - + - + - + + + + + + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + - + - + - + + + + + +
    All Methods Instance Methods Concrete Methods All Methods Instance Methods Concrete Methods Deprecated Methods 
    Modifier and Type Method
    MediaMetadata.BuildermaybeSetArtworkData​(byte[] artworkData, + int artworkDataType) +
    Sets the artwork data as a compressed byte array in the event that the associated MediaMetadata.PictureType is MediaMetadata.PICTURE_TYPE_FRONT_COVER, the existing MediaMetadata.PictureType is not + MediaMetadata.PICTURE_TYPE_FRONT_COVER, or the current artworkData is not set.
    +
    MediaMetadata.Builder populateFromMetadata​(Metadata metadata)
    Sets all fields supported by the entries within the Metadata.
    MediaMetadata.Builder populateFromMetadata​(List<Metadata> metadataList)
    Sets all fields supported by the entries within the list of Metadata.
    MediaMetadata.Builder setAlbumArtist​(CharSequence albumArtist)
    Sets the album artist.
    MediaMetadata.Builder setAlbumTitle​(CharSequence albumTitle)
    Sets the album title.
    MediaMetadata.Builder setArtist​(CharSequence artist)
    Sets the artist.
    MediaMetadata.Builder setArtworkData​(byte[] artworkData) -
    Sets the artwork data as a compressed byte array.
    +
    MediaMetadata.BuildersetArtworkData​(byte[] artworkData, + Integer artworkDataType) +
    Sets the artwork data as a compressed byte array with an associated artworkDataType.
    +
    MediaMetadata.Builder setArtworkUri​(Uri artworkUri)
    Sets the artwork Uri.
    MediaMetadata.BuildersetCompilation​(CharSequence compilation) +
    Sets the compilation.
    +
    MediaMetadata.BuildersetComposer​(CharSequence composer) +
    Sets the composer.
    +
    MediaMetadata.BuildersetConductor​(CharSequence conductor) +
    Sets the conductor.
    +
    MediaMetadata.Builder setDescription​(CharSequence description)
    Sets the description.
    MediaMetadata.BuildersetDiscNumber​(Integer discNumber) +
    Sets the disc number.
    +
    MediaMetadata.Builder setDisplayTitle​(CharSequence displayTitle)
    Sets the display title.
    MediaMetadata.Builder setExtras​(Bundle extras)
    Sets the extras Bundle.
    MediaMetadata.Builder setFolderType​(Integer folderType)
    MediaMetadata.BuildersetGenre​(CharSequence genre) +
    Sets the genre.
    +
    MediaMetadata.Builder setIsPlayable​(Boolean isPlayable)
    Sets whether the media is playable.
    MediaMetadata.Builder setMediaUri​(Uri mediaUri)
    Sets the media Uri.
    MediaMetadata.Builder setOverallRating​(Rating overallRating)
    Sets the overall Rating.
    MediaMetadata.BuildersetRecordingDay​(Integer recordingDay) +
    Sets the day of the recording date.
    +
    MediaMetadata.BuildersetRecordingMonth​(Integer recordingMonth) +
    Sets the month of the recording date.
    +
    MediaMetadata.BuildersetRecordingYear​(Integer recordingYear) +
    Sets the year of the recording date.
    +
    MediaMetadata.BuildersetReleaseDay​(Integer releaseDay) +
    Sets the day of the release date.
    +
    MediaMetadata.BuildersetReleaseMonth​(Integer releaseMonth) +
    Sets the month of the release date.
    +
    MediaMetadata.BuildersetReleaseYear​(Integer releaseYear) +
    Sets the year of the release date.
    +
    MediaMetadata.Builder setSubtitle​(CharSequence subtitle)
    Sets the subtitle.
    MediaMetadata.Builder setTitle​(CharSequence title)
    Sets the title.
    MediaMetadata.BuildersetTotalDiscCount​(Integer totalDiscCount) +
    Sets the total number of discs.
    +
    MediaMetadata.Builder setTotalTrackCount​(Integer totalTrackCount)
    Sets the total number of tracks.
    MediaMetadata.Builder setTrackNumber​(Integer trackNumber)
    Sets the track number.
    MediaMetadata.Builder setUserRating​(Rating userRating)
    Sets the user Rating.
    MediaMetadata.BuildersetWriter​(CharSequence writer) +
    Sets the writer.
    +
    MediaMetadata.Builder setYear​(Integer year) -
    Sets the year.
    +
    Deprecated. + +
    @@ -485,9 +597,41 @@

    setOverallRating

    + + + + + + + + @@ -551,9 +695,163 @@

    setIsPlayable

    + + + +
      +
    • +

      setRecordingYear

      +
      public MediaMetadata.Builder setRecordingYear​(@Nullable
      +                                              Integer recordingYear)
      +
      Sets the year of the recording date.
      +
    • +
    + + + +
      +
    • +

      setRecordingMonth

      +
      public MediaMetadata.Builder setRecordingMonth​(@Nullable @IntRange(from=1L,to=12L)
      +                                               Integer recordingMonth)
      +
      Sets the month of the recording date. + +

      Value should be between 1 and 12.

      +
    • +
    + + + +
      +
    • +

      setRecordingDay

      +
      public MediaMetadata.Builder setRecordingDay​(@Nullable @IntRange(from=1L,to=31L)
      +                                             Integer recordingDay)
      +
      Sets the day of the recording date. + +

      Value should be between 1 and 31.

      +
    • +
    + + + +
      +
    • +

      setReleaseYear

      +
      public MediaMetadata.Builder setReleaseYear​(@Nullable
      +                                            Integer releaseYear)
      +
      Sets the year of the release date.
      +
    • +
    + + + +
      +
    • +

      setReleaseMonth

      +
      public MediaMetadata.Builder setReleaseMonth​(@Nullable @IntRange(from=1L,to=12L)
      +                                             Integer releaseMonth)
      +
      Sets the month of the release date. + +

      Value should be between 1 and 12.

      +
    • +
    + + + +
      +
    • +

      setReleaseDay

      +
      public MediaMetadata.Builder setReleaseDay​(@Nullable @IntRange(from=1L,to=31L)
      +                                           Integer releaseDay)
      +
      Sets the day of the release date. + +

      Value should be between 1 and 31.

      +
    • +
    + + + + + + + + + + + + + + + + + + + +
      +
    • +

      setTotalDiscCount

      +
      public MediaMetadata.Builder setTotalDiscCount​(@Nullable
      +                                               Integer totalDiscCount)
      +
      Sets the total number of discs.
      +
    • +
    + + + + + + + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/PlaybackPreparer.html b/docs/doc/reference/com/google/android/exoplayer2/MediaMetadata.PictureType.html similarity index 60% rename from docs/doc/reference/com/google/android/exoplayer2/PlaybackPreparer.html rename to docs/doc/reference/com/google/android/exoplayer2/MediaMetadata.PictureType.html index 5e34c93ac3d..8aa35d1a6e3 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/PlaybackPreparer.html +++ b/docs/doc/reference/com/google/android/exoplayer2/MediaMetadata.PictureType.html @@ -2,7 +2,7 @@ -PlaybackPreparer (ExoPlayer library) +MediaMetadata.PictureType (ExoPlayer library) @@ -19,18 +19,12 @@ @@ -86,16 +80,14 @@
    @@ -114,80 +106,20 @@
    -

    Interface PlaybackPreparer

    +

    Annotation Type MediaMetadata.PictureType

    -
    -
    - -
    -
    -
    @@ -236,16 +168,14 @@

    preparePlayback

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/MediaMetadata.html b/docs/doc/reference/com/google/android/exoplayer2/MediaMetadata.html index 050176afb4e..a8ce3ba8e02 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/MediaMetadata.html +++ b/docs/doc/reference/com/google/android/exoplayer2/MediaMetadata.html @@ -171,6 +171,13 @@

    Nested Class Summary

    The folder type of the media item.
    + +static interface  +
    MediaMetadata.PictureType + +
    The picture type of the artwork.
    + + + + + +
      +
    • +

      PICTURE_TYPE_OTHER

      +
      public static final int PICTURE_TYPE_OTHER
      +
      +
      See Also:
      +
      Constant Field Values
      +
      +
    • +
    + + + +
      +
    • +

      PICTURE_TYPE_FILE_ICON

      +
      public static final int PICTURE_TYPE_FILE_ICON
      +
      +
      See Also:
      +
      Constant Field Values
      +
      +
    • +
    + + + +
      +
    • +

      PICTURE_TYPE_FILE_ICON_OTHER

      +
      public static final int PICTURE_TYPE_FILE_ICON_OTHER
      +
      +
      See Also:
      +
      Constant Field Values
      +
      +
    • +
    + + + +
      +
    • +

      PICTURE_TYPE_FRONT_COVER

      +
      public static final int PICTURE_TYPE_FRONT_COVER
      +
      +
      See Also:
      +
      Constant Field Values
      +
      +
    • +
    + + + +
      +
    • +

      PICTURE_TYPE_BACK_COVER

      +
      public static final int PICTURE_TYPE_BACK_COVER
      +
      +
      See Also:
      +
      Constant Field Values
      +
      +
    • +
    + + + +
      +
    • +

      PICTURE_TYPE_LEAFLET_PAGE

      +
      public static final int PICTURE_TYPE_LEAFLET_PAGE
      +
      +
      See Also:
      +
      Constant Field Values
      +
      +
    • +
    + + + +
      +
    • +

      PICTURE_TYPE_MEDIA

      +
      public static final int PICTURE_TYPE_MEDIA
      +
      +
      See Also:
      +
      Constant Field Values
      +
      +
    • +
    + + + +
      +
    • +

      PICTURE_TYPE_LEAD_ARTIST_PERFORMER

      +
      public static final int PICTURE_TYPE_LEAD_ARTIST_PERFORMER
      +
      +
      See Also:
      +
      Constant Field Values
      +
      +
    • +
    + + + +
      +
    • +

      PICTURE_TYPE_ARTIST_PERFORMER

      +
      public static final int PICTURE_TYPE_ARTIST_PERFORMER
      +
      +
      See Also:
      +
      Constant Field Values
      +
      +
    • +
    + + + +
      +
    • +

      PICTURE_TYPE_CONDUCTOR

      +
      public static final int PICTURE_TYPE_CONDUCTOR
      +
      +
      See Also:
      +
      Constant Field Values
      +
      +
    • +
    + + + +
      +
    • +

      PICTURE_TYPE_BAND_ORCHESTRA

      +
      public static final int PICTURE_TYPE_BAND_ORCHESTRA
      +
      +
      See Also:
      +
      Constant Field Values
      +
      +
    • +
    + + + +
      +
    • +

      PICTURE_TYPE_COMPOSER

      +
      public static final int PICTURE_TYPE_COMPOSER
      +
      +
      See Also:
      +
      Constant Field Values
      +
      +
    • +
    + + + +
      +
    • +

      PICTURE_TYPE_LYRICIST

      +
      public static final int PICTURE_TYPE_LYRICIST
      +
      +
      See Also:
      +
      Constant Field Values
      +
      +
    • +
    + + + +
      +
    • +

      PICTURE_TYPE_RECORDING_LOCATION

      +
      public static final int PICTURE_TYPE_RECORDING_LOCATION
      +
      +
      See Also:
      +
      Constant Field Values
      +
      +
    • +
    + + + +
      +
    • +

      PICTURE_TYPE_DURING_RECORDING

      +
      public static final int PICTURE_TYPE_DURING_RECORDING
      +
      +
      See Also:
      +
      Constant Field Values
      +
      +
    • +
    + + + +
      +
    • +

      PICTURE_TYPE_DURING_PERFORMANCE

      +
      public static final int PICTURE_TYPE_DURING_PERFORMANCE
      +
      +
      See Also:
      +
      Constant Field Values
      +
      +
    • +
    + + + +
      +
    • +

      PICTURE_TYPE_MOVIE_VIDEO_SCREEN_CAPTURE

      +
      public static final int PICTURE_TYPE_MOVIE_VIDEO_SCREEN_CAPTURE
      +
      +
      See Also:
      +
      Constant Field Values
      +
      +
    • +
    + + + +
      +
    • +

      PICTURE_TYPE_A_BRIGHT_COLORED_FISH

      +
      public static final int PICTURE_TYPE_A_BRIGHT_COLORED_FISH
      +
      +
      See Also:
      +
      Constant Field Values
      +
      +
    • +
    + + + +
      +
    • +

      PICTURE_TYPE_ILLUSTRATION

      +
      public static final int PICTURE_TYPE_ILLUSTRATION
      +
      +
      See Also:
      +
      Constant Field Values
      +
      +
    • +
    + +
      +
    • +

      PICTURE_TYPE_BAND_ARTIST_LOGO

      +
      public static final int PICTURE_TYPE_BAND_ARTIST_LOGO
      +
      +
      See Also:
      +
      Constant Field Values
      +
      +
    • +
    + +
      +
    • +

      PICTURE_TYPE_PUBLISHER_STUDIO_LOGO

      +
      public static final int PICTURE_TYPE_PUBLISHER_STUDIO_LOGO
      +
      +
      See Also:
      +
      Constant Field Values
      +
      +
    • +
    @@ -682,6 +1188,18 @@

    artworkData

    Optional artwork data as a compressed byte array.
    + + + + @@ -744,9 +1262,163 @@

    isPlayable

    + + + +
      +
    • +

      recordingYear

      +
      @Nullable
      +public final Integer recordingYear
      +
      Optional year of the recording date.
      +
    • +
    + + + +
      +
    • +

      recordingMonth

      +
      @Nullable
      +public final Integer recordingMonth
      +
      Optional month of the recording date. + +

      Note that there is no guarantee that the month and day are a valid combination.

      +
    • +
    + + + +
      +
    • +

      recordingDay

      +
      @Nullable
      +public final Integer recordingDay
      +
      Optional day of the recording date. + +

      Note that there is no guarantee that the month and day are a valid combination.

      +
    • +
    + + + +
      +
    • +

      releaseYear

      +
      @Nullable
      +public final Integer releaseYear
      +
      Optional year of the release date.
      +
    • +
    + + + +
      +
    • +

      releaseMonth

      +
      @Nullable
      +public final Integer releaseMonth
      +
      Optional month of the release date. + +

      Note that there is no guarantee that the month and day are a valid combination.

      +
    • +
    + + + +
      +
    • +

      releaseDay

      +
      @Nullable
      +public final Integer releaseDay
      +
      Optional day of the release date. + +

      Note that there is no guarantee that the month and day are a valid combination.

      +
    • +
    + + + +
      +
    • +

      writer

      +
      @Nullable
      +public final CharSequence writer
      +
      Optional writer.
      +
    • +
    + + + +
      +
    • +

      composer

      +
      @Nullable
      +public final CharSequence composer
      +
      Optional composer.
      +
    • +
    + + + +
      +
    • +

      conductor

      +
      @Nullable
      +public final CharSequence conductor
      +
      Optional conductor.
      +
    • +
    + + + +
      +
    • +

      discNumber

      +
      @Nullable
      +public final Integer discNumber
      +
      Optional disc number.
      +
    • +
    + + + +
      +
    • +

      totalDiscCount

      +
      @Nullable
      +public final Integer totalDiscCount
      +
      Optional total number of discs.
      +
    • +
    + + + +
      +
    • +

      genre

      +
      @Nullable
      +public final CharSequence genre
      +
      Optional genre.
      +
    • +
    + + + +
      +
    • +

      compilation

      +
      @Nullable
      +public final CharSequence compilation
      +
      Optional compilation.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/NoSampleRenderer.html b/docs/doc/reference/com/google/android/exoplayer2/NoSampleRenderer.html index 2155cf2b7df..36998fa5804 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/NoSampleRenderer.html +++ b/docs/doc/reference/com/google/android/exoplayer2/NoSampleRenderer.html @@ -282,8 +282,7 @@

    Method Summary

    long
    getReadingPositionUs() -
    Returns the renderer time up to which the renderer has read samples from the current SampleStream, in microseconds, or C.TIME_END_OF_SOURCE if the renderer has read the - current SampleStream to the end.
    +
    Returns the renderer time up to which the renderer has read samples, in microseconds, or C.TIME_END_OF_SOURCE if the renderer has read the current SampleStream to the end.
    @@ -309,8 +308,8 @@

    Method Summary

    void -handleMessage​(int what, - Object object) +handleMessage​(int messageType, + Object message)
    Handles a message delivered to the target.
    @@ -668,9 +667,8 @@

    start

    Description copied from interface: Renderer
    Starts the renderer, meaning that calls to Renderer.render(long, long) will cause media to be rendered. -

    - This method may be called when the renderer is in the following states: - Renderer.STATE_ENABLED.

    + +

    This method may be called when the renderer is in the following states: Renderer.STATE_ENABLED.

    Specified by:
    start in interface Renderer
    @@ -733,9 +731,8 @@

    hasReadStreamToEnd

    public final boolean hasReadStreamToEnd()
    Description copied from interface: Renderer
    Returns whether the renderer has read the current SampleStream to the end. -

    - This method may be called when the renderer is in the following states: - Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

    + +

    This method may be called when the renderer is in the following states: Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

    Specified by:
    hasReadStreamToEnd in interface Renderer
    @@ -750,8 +747,7 @@

    hasReadStreamToEnd

    getReadingPositionUs

    public long getReadingPositionUs()
    Description copied from interface: Renderer
    -
    Returns the renderer time up to which the renderer has read samples from the current SampleStream, in microseconds, or C.TIME_END_OF_SOURCE if the renderer has read the - current SampleStream to the end. +
    Returns the renderer time up to which the renderer has read samples, in microseconds, or C.TIME_END_OF_SOURCE if the renderer has read the current SampleStream to the end.

    This method may be called when the renderer is in the following states: Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

    @@ -770,9 +766,8 @@

    setCurrentStreamFinal

    Description copied from interface: Renderer
    Signals to the renderer that the current SampleStream will be the final one supplied before it is next disabled or reset. -

    - This method may be called when the renderer is in the following states: - Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

    + +

    This method may be called when the renderer is in the following states: Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

    Specified by:
    setCurrentStreamFinal in interface Renderer
    @@ -806,9 +801,8 @@

    maybeThrowStreamError

    Description copied from interface: Renderer
    Throws an error that's preventing the renderer from reading from its SampleStream. Does nothing if no such error exists. -

    - This method may be called when the renderer is in the following states: - Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

    + +

    This method may be called when the renderer is in the following states: Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

    Specified by:
    maybeThrowStreamError in interface Renderer
    @@ -828,12 +822,11 @@

    resetPosition

    throws ExoPlaybackException
    Description copied from interface: Renderer
    Signals to the renderer that a position discontinuity has occurred. -

    - After a position discontinuity, the renderer's SampleStream is guaranteed to provide + +

    After a position discontinuity, the renderer's SampleStream is guaranteed to provide samples starting from a key frame. -

    - This method may be called when the renderer is in the following states: - Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

    + +

    This method may be called when the renderer is in the following states: Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

    Specified by:
    resetPosition in interface Renderer
    @@ -870,9 +863,8 @@

    disable

    public final void disable()
    Description copied from interface: Renderer
    Disable the renderer, transitioning it to the Renderer.STATE_DISABLED state. -

    - This method may be called when the renderer is in the following states: - Renderer.STATE_ENABLED.

    + +

    This method may be called when the renderer is in the following states: Renderer.STATE_ENABLED.

    Specified by:
    disable in interface Renderer
    @@ -906,16 +898,15 @@

    isReady

    public boolean isReady()
    Description copied from interface: Renderer
    Whether the renderer is able to immediately render media from the current position. -

    - If the renderer is in the Renderer.STATE_STARTED state then returning true indicates that the - renderer has everything that it needs to continue playback. Returning false indicates that + +

    If the renderer is in the Renderer.STATE_STARTED state then returning true indicates that + the renderer has everything that it needs to continue playback. Returning false indicates that the player should pause until the renderer is ready. -

    - If the renderer is in the Renderer.STATE_ENABLED state then returning true indicates that the - renderer is ready for playback to be started. Returning false indicates that it is not. -

    - This method may be called when the renderer is in the following states: - Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

    + +

    If the renderer is in the Renderer.STATE_ENABLED state then returning true indicates that + the renderer is ready for playback to be started. Returning false indicates that it is not. + +

    This method may be called when the renderer is in the following states: Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

    Specified by:
    isReady in interface Renderer
    @@ -996,9 +987,9 @@

    supportsMixedMimeTypeAdaptation

    • handleMessage

      -
      public void handleMessage​(int what,
      +
      public void handleMessage​(int messageType,
                                 @Nullable
      -                          Object object)
      +                          Object message)
                          throws ExoPlaybackException
      Description copied from interface: PlayerMessage.Target
      Handles a message delivered to the target.
      @@ -1006,8 +997,8 @@

      handleMessage

      Specified by:
      handleMessage in interface PlayerMessage.Target
      Parameters:
      -
      what - The message type.
      -
      object - The message payload.
      +
      messageType - The message type.
      +
      message - The message payload.
      Throws:
      ExoPlaybackException - If an error occurred whilst handling the message. Should only be thrown by targets that handle messages on the playback thread.
      @@ -1023,8 +1014,8 @@

      onEnabled

      protected void onEnabled​(boolean joining)
                         throws ExoPlaybackException
      Called when the renderer is enabled. -

      - The default implementation is a no-op.

      + +

      The default implementation is a no-op.

      Parameters:
      joining - Whether this renderer is being enabled to join an ongoing playback.
      @@ -1042,12 +1033,11 @@

      onRendererOffsetChanged

      protected void onRendererOffsetChanged​(long offsetUs)
                                       throws ExoPlaybackException
      Called when the renderer's offset has been changed. -

      - The default implementation is a no-op.

      + +

      The default implementation is a no-op.

      Parameters:
      -
      offsetUs - The offset that should be subtracted from positionUs in - Renderer.render(long, long) to get the playback position with respect to the media.
      +
      offsetUs - The offset that should be subtracted from positionUs in Renderer.render(long, long) to get the playback position with respect to the media.
      Throws:
      ExoPlaybackException - If an error occurs.
      @@ -1062,11 +1052,10 @@

      onPositionReset

      protected void onPositionReset​(long positionUs,
                                      boolean joining)
                               throws ExoPlaybackException
      -
      Called when the position is reset. This occurs when the renderer is enabled after - onRendererOffsetChanged(long) has been called, and also when a position - discontinuity is encountered. -

      - The default implementation is a no-op.

      +
      Called when the position is reset. This occurs when the renderer is enabled after onRendererOffsetChanged(long) has been called, and also when a position discontinuity is + encountered. + +

      The default implementation is a no-op.

      Parameters:
      positionUs - The new playback position in microseconds.
      @@ -1085,8 +1074,8 @@

      onStarted

      protected void onStarted()
                         throws ExoPlaybackException
      Called when the renderer is started. -

      - The default implementation is a no-op.

      + +

      The default implementation is a no-op.

      Throws:
      ExoPlaybackException - If an error occurs.
      @@ -1113,8 +1102,8 @@

      onStopped

      onDisabled

      protected void onDisabled()
      Called when the renderer is disabled. -

      - The default implementation is a no-op.

      + +

      The default implementation is a no-op.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/ParserException.html b/docs/doc/reference/com/google/android/exoplayer2/ParserException.html index 76298e016ae..32fab394571 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ParserException.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ParserException.html @@ -25,6 +25,12 @@ catch(err) { } //--> +var data = {"i0":9,"i1":9,"i2":9,"i3":9,"i4":9}; +var tabs = {65535:["t0","All Methods"],1:["t1","Static Methods"],8:["t4","Concrete Methods"]}; +var altColor = "altColor"; +var rowColor = "rowColor"; +var tableTab = "tableTab"; +var activeTableTab = "activeTableTab"; var pathtoroot = "../../../../"; var useModuleDirectories = false; loadScripts(document, 'script'); @@ -81,15 +87,15 @@ @@ -159,34 +165,58 @@

    Class ParserException

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/PlaybackException.ErrorCode.html b/docs/doc/reference/com/google/android/exoplayer2/PlaybackException.ErrorCode.html new file mode 100644 index 00000000000..711c99bc913 --- /dev/null +++ b/docs/doc/reference/com/google/android/exoplayer2/PlaybackException.ErrorCode.html @@ -0,0 +1,188 @@ + + + + +PlaybackException.ErrorCode (ExoPlayer library) + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Annotation Type PlaybackException.ErrorCode

    +
    +
    +
    +
      +
    • +
      +
      @Documented
      +@Retention(SOURCE)
      +public static @interface PlaybackException.ErrorCode
      +
      Codes that identify causes of player errors. + +

      This list of errors may be extended in future versions, and Player implementations + may define custom error codes.

      +
    • +
    +
    +
    +
    + +
    + +
    + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/PlaybackException.FieldNumber.html b/docs/doc/reference/com/google/android/exoplayer2/PlaybackException.FieldNumber.html new file mode 100644 index 00000000000..95d5756fe70 --- /dev/null +++ b/docs/doc/reference/com/google/android/exoplayer2/PlaybackException.FieldNumber.html @@ -0,0 +1,189 @@ + + + + +PlaybackException.FieldNumber (ExoPlayer library) + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Annotation Type PlaybackException.FieldNumber

    +
    +
    +
    + +
    +
    +
    + +
    + +
    + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/PlaybackException.html b/docs/doc/reference/com/google/android/exoplayer2/PlaybackException.html new file mode 100644 index 00000000000..3cca1a966f7 --- /dev/null +++ b/docs/doc/reference/com/google/android/exoplayer2/PlaybackException.html @@ -0,0 +1,1394 @@ + + + + +PlaybackException (ExoPlayer library) + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class PlaybackException

    +
    +
    + +
    + +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Field Detail

        + + + +
          +
        • +

          ERROR_CODE_UNSPECIFIED

          +
          public static final int ERROR_CODE_UNSPECIFIED
          +
          Caused by an error whose cause could not be identified.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_REMOTE_ERROR

          +
          public static final int ERROR_CODE_REMOTE_ERROR
          +
          Caused by an unidentified error in a remote Player, which is a Player that runs on a different + host or process.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_BEHIND_LIVE_WINDOW

          +
          public static final int ERROR_CODE_BEHIND_LIVE_WINDOW
          +
          Caused by the loading position falling behind the sliding window of available live content.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_TIMEOUT

          +
          public static final int ERROR_CODE_TIMEOUT
          +
          Caused by a generic timeout.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_FAILED_RUNTIME_CHECK

          +
          public static final int ERROR_CODE_FAILED_RUNTIME_CHECK
          +
          Caused by a failed runtime check. + +

          This can happen when the application fails to comply with the player's API requirements (for + example, by passing invalid arguments), or when the player reaches an invalid state.

          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_IO_UNSPECIFIED

          +
          public static final int ERROR_CODE_IO_UNSPECIFIED
          +
          Caused by an Input/Output error which could not be identified.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_IO_NETWORK_CONNECTION_FAILED

          +
          public static final int ERROR_CODE_IO_NETWORK_CONNECTION_FAILED
          +
          Caused by a network connection failure. + +

          The following is a non-exhaustive list of possible reasons: + +

            +
          • There is no network connectivity (you can check this by querying ConnectivityManager.getActiveNetwork()). +
          • The URL's domain is misspelled or does not exist. +
          • The target host is unreachable. +
          • The server unexpectedly closes the connection. +
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT

          +
          public static final int ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT
          +
          Caused by a network timeout, meaning the server is taking too long to fulfill a request.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE

          +
          public static final int ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE
          +
          Caused by a server returning a resource with an invalid "Content-Type" HTTP header value. + +

          For example, this can happen when the player is expecting a piece of media, but the server + returns a paywall HTML page, with content type "text/html".

          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_IO_BAD_HTTP_STATUS

          +
          public static final int ERROR_CODE_IO_BAD_HTTP_STATUS
          +
          Caused by an HTTP server returning an unexpected HTTP response status code.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_IO_FILE_NOT_FOUND

          +
          public static final int ERROR_CODE_IO_FILE_NOT_FOUND
          +
          Caused by a non-existent file.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_IO_NO_PERMISSION

          +
          public static final int ERROR_CODE_IO_NO_PERMISSION
          +
          Caused by lack of permission to perform an IO operation. For example, lack of permission to + access internet or external storage.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED

          +
          public static final int ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED
          +
          Caused by the player trying to access cleartext HTTP traffic (meaning http:// rather than + https://) when the app's Network Security Configuration does not permit it. + +

          See this corresponding + troubleshooting topic.

          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE

          +
          public static final int ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE
          +
          Caused by reading data out of the data bound.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_PARSING_CONTAINER_MALFORMED

          +
          public static final int ERROR_CODE_PARSING_CONTAINER_MALFORMED
          +
          Caused by a parsing error associated with a media container format bitstream.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_PARSING_MANIFEST_MALFORMED

          +
          public static final int ERROR_CODE_PARSING_MANIFEST_MALFORMED
          +
          Caused by a parsing error associated with a media manifest. Examples of a media manifest are a + DASH or a SmoothStreaming manifest, or an HLS playlist.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_PARSING_CONTAINER_UNSUPPORTED

          +
          public static final int ERROR_CODE_PARSING_CONTAINER_UNSUPPORTED
          +
          Caused by attempting to extract a file with an unsupported media container format, or an + unsupported media container feature.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_PARSING_MANIFEST_UNSUPPORTED

          +
          public static final int ERROR_CODE_PARSING_MANIFEST_UNSUPPORTED
          +
          Caused by an unsupported feature in a media manifest. Examples of a media manifest are a DASH + or a SmoothStreaming manifest, or an HLS playlist.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_DECODER_INIT_FAILED

          +
          public static final int ERROR_CODE_DECODER_INIT_FAILED
          +
          Caused by a decoder initialization failure.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_DECODER_QUERY_FAILED

          +
          public static final int ERROR_CODE_DECODER_QUERY_FAILED
          +
          Caused by a decoder query failure.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_DECODING_FAILED

          +
          public static final int ERROR_CODE_DECODING_FAILED
          +
          Caused by a failure while trying to decode media samples.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_DECODING_FORMAT_EXCEEDS_CAPABILITIES

          +
          public static final int ERROR_CODE_DECODING_FORMAT_EXCEEDS_CAPABILITIES
          +
          Caused by trying to decode content whose format exceeds the capabilities of the device.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_DECODING_FORMAT_UNSUPPORTED

          +
          public static final int ERROR_CODE_DECODING_FORMAT_UNSUPPORTED
          +
          Caused by trying to decode content whose format is not supported.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_AUDIO_TRACK_INIT_FAILED

          +
          public static final int ERROR_CODE_AUDIO_TRACK_INIT_FAILED
          +
          Caused by an AudioTrack initialization failure.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_AUDIO_TRACK_WRITE_FAILED

          +
          public static final int ERROR_CODE_AUDIO_TRACK_WRITE_FAILED
          +
          Caused by an AudioTrack write operation failure.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_DRM_UNSPECIFIED

          +
          public static final int ERROR_CODE_DRM_UNSPECIFIED
          +
          Caused by an unspecified error related to DRM protection.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_DRM_SCHEME_UNSUPPORTED

          +
          public static final int ERROR_CODE_DRM_SCHEME_UNSUPPORTED
          +
          Caused by a chosen DRM protection scheme not being supported by the device. Examples of DRM + protection schemes are ClearKey and Widevine.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_DRM_PROVISIONING_FAILED

          +
          public static final int ERROR_CODE_DRM_PROVISIONING_FAILED
          +
          Caused by a failure while provisioning the device.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_DRM_CONTENT_ERROR

          +
          public static final int ERROR_CODE_DRM_CONTENT_ERROR
          +
          Caused by attempting to play incompatible DRM-protected content. + +

          For example, this can happen when attempting to play a DRM protected stream using a scheme + (like Widevine) for which there is no corresponding license acquisition data (like a pssh box).

          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_DRM_LICENSE_ACQUISITION_FAILED

          +
          public static final int ERROR_CODE_DRM_LICENSE_ACQUISITION_FAILED
          +
          Caused by a failure while trying to obtain a license.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_DRM_DISALLOWED_OPERATION

          +
          public static final int ERROR_CODE_DRM_DISALLOWED_OPERATION
          +
          Caused by an operation being disallowed by a license policy.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_DRM_SYSTEM_ERROR

          +
          public static final int ERROR_CODE_DRM_SYSTEM_ERROR
          +
          Caused by an error in the DRM system.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_DRM_DEVICE_REVOKED

          +
          public static final int ERROR_CODE_DRM_DEVICE_REVOKED
          +
          Caused by the device having revoked DRM privileges.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ERROR_CODE_DRM_LICENSE_EXPIRED

          +
          public static final int ERROR_CODE_DRM_LICENSE_EXPIRED
          +
          Caused by an expired DRM license being loaded into an open DRM session.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          CUSTOM_ERROR_CODE_BASE

          +
          public static final int CUSTOM_ERROR_CODE_BASE
          +
          Player implementations that want to surface custom errors can use error codes greater than this + value, so as to avoid collision with other error codes defined in this class.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          errorCode

          +
          @ErrorCode
          +public final int errorCode
          +
          An error code which identifies the cause of the playback failure.
          +
        • +
        + + + + + + + +
          +
        • +

          FIELD_CUSTOM_ID_BASE

          +
          protected static final int FIELD_CUSTOM_ID_BASE
          +
          Defines a minimum field id value for subclasses to use when implementing toBundle() + and Bundleable.Creator. + +

          Subclasses should obtain their Bundle's field keys by applying a non-negative + offset on this constant and passing the result to keyForField(int).

          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + + +
      • +
      +
      + +
      +
        +
      • + + +

        Constructor Detail

        + + + + + + + +
          +
        • +

          PlaybackException

          +
          protected PlaybackException​(Bundle bundle)
          +
          Creates a new instance using the fields obtained from the given Bundle.
          +
        • +
        + + + +
          +
        • +

          PlaybackException

          +
          protected PlaybackException​(@Nullable
          +                            String message,
          +                            @Nullable
          +                            Throwable cause,
          +                            @ErrorCode
          +                            int errorCode,
          +                            long timestampMs)
          +
          Creates a new instance using the given values.
          +
        • +
        +
      • +
      +
      + +
      + +
      +
    • +
    +
    +
    +
    + + + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/Player.Command.html b/docs/doc/reference/com/google/android/exoplayer2/Player.Command.html index 322e3cd1cfc..d4f499f2679 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/Player.Command.html +++ b/docs/doc/reference/com/google/android/exoplayer2/Player.Command.html @@ -116,7 +116,7 @@

    Annotation Type Player.
    @Documented
     @Retention(SOURCE)
     public static @interface Player.Command
    - + diff --git a/docs/doc/reference/com/google/android/exoplayer2/Player.Commands.Builder.html b/docs/doc/reference/com/google/android/exoplayer2/Player.Commands.Builder.html index e06e16e6e7a..ca5c0339c35 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/Player.Commands.Builder.html +++ b/docs/doc/reference/com/google/android/exoplayer2/Player.Commands.Builder.html @@ -25,7 +25,7 @@ catch(err) { } //--> -var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10}; +var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10}; var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -202,19 +202,48 @@

    Method Summary

    Player.Commands.Builder +addAllCommands() + +
    Adds all existing commands.
    + + + +Player.Commands.Builder addIf​(int command, boolean condition)
    Adds a Player.Command if the provided condition is true.
    - + Player.Commands build()
    Builds a Player.Commands instance.
    + +Player.Commands.Builder +remove​(int command) + +
    Removes a Player.Command.
    + + + +Player.Commands.Builder +removeAll​(int... commands) + +
    Removes commands.
    + + + +Player.Commands.Builder +removeIf​(int command, + boolean condition) + +
    Removes a Player.Command if the provided condition is true.
    + +
    + + + + + + + + + + + + + + + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/Player.Commands.html b/docs/doc/reference/com/google/android/exoplayer2/Player.Commands.html index 779b915356c..7b79b004ecb 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/Player.Commands.html +++ b/docs/doc/reference/com/google/android/exoplayer2/Player.Commands.html @@ -25,7 +25,7 @@ catch(err) { } //--> -var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10}; +var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10}; var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -129,12 +129,17 @@

    Class Player.Commands

    @@ -184,6 +196,13 @@

    Field Summary

    Description +static Bundleable.Creator<Player.Commands> +CREATOR + +
    Object that can restore Player.Commands from a Bundle.
    + + + static Player.Commands EMPTY @@ -209,36 +228,50 @@

    Method Summary

    Description +Player.Commands.Builder +buildUpon() + +
    Returns a Player.Commands.Builder initialized with the values of this instance.
    + + + boolean contains​(int command)
    Returns whether the set of commands contains the specified Player.Command.
    - + boolean equals​(Object obj)   - + int get​(int index)
    Returns the Player.Command at the given index.
    - + int hashCode()   - + int size()
    Returns the number of commands in this set.
    + +Bundle +toBundle() + +
    Returns a Bundle representing the information stored in this object.
    + +
    + + + +
      +
    • +

      toBundle

      +
      public Bundle toBundle()
      +
      Description copied from interface: Bundleable
      +
      Returns a Bundle representing the information stored in this object.
      +
      +
      Specified by:
      +
      toBundle in interface Bundleable
      +
      +
    • +
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/Player.EventFlags.html b/docs/doc/reference/com/google/android/exoplayer2/Player.Event.html similarity index 96% rename from docs/doc/reference/com/google/android/exoplayer2/Player.EventFlags.html rename to docs/doc/reference/com/google/android/exoplayer2/Player.Event.html index 4163538cb5d..51e7f502934 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/Player.EventFlags.html +++ b/docs/doc/reference/com/google/android/exoplayer2/Player.Event.html @@ -2,7 +2,7 @@ -Player.EventFlags (ExoPlayer library) +Player.Event (ExoPlayer library) @@ -19,7 +19,7 @@ + + + + + + + + + +
    + +
    + +
    +
    + +

    Class Timeline.RemotableTimeline

    +
    +
    + +
    + +
    +
    + +
    +
    +
      +
    • + +
      + +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getWindowCount

          +
          public int getWindowCount()
          +
          Description copied from class: Timeline
          +
          Returns the number of windows in the timeline.
          +
          +
          Specified by:
          +
          getWindowCount in class Timeline
          +
          +
        • +
        + + + +
          +
        • +

          getWindow

          +
          public Timeline.Window getWindow​(int windowIndex,
          +                                 Timeline.Window window,
          +                                 long defaultPositionProjectionUs)
          +
          Description copied from class: Timeline
          +
          Populates a Timeline.Window with data for the window at the specified index.
          +
          +
          Specified by:
          +
          getWindow in class Timeline
          +
          Parameters:
          +
          windowIndex - The index of the window.
          +
          window - The Timeline.Window to populate. Must not be null.
          +
          defaultPositionProjectionUs - A duration into the future that the populated window's + default start position should be projected.
          +
          Returns:
          +
          The populated Timeline.Window, for convenience.
          +
          +
        • +
        + + + +
          +
        • +

          getNextWindowIndex

          +
          public int getNextWindowIndex​(int windowIndex,
          +                              @RepeatMode
          +                              int repeatMode,
          +                              boolean shuffleModeEnabled)
          +
          Description copied from class: Timeline
          +
          Returns the index of the window after the window at index windowIndex depending on the + repeatMode and whether shuffling is enabled.
          +
          +
          Overrides:
          +
          getNextWindowIndex in class Timeline
          +
          Parameters:
          +
          windowIndex - Index of a window in the timeline.
          +
          repeatMode - A repeat mode.
          +
          shuffleModeEnabled - Whether shuffling is enabled.
          +
          Returns:
          +
          The index of the next window, or C.INDEX_UNSET if this is the last window.
          +
          +
        • +
        + + + +
          +
        • +

          getPreviousWindowIndex

          +
          public int getPreviousWindowIndex​(int windowIndex,
          +                                  @RepeatMode
          +                                  int repeatMode,
          +                                  boolean shuffleModeEnabled)
          +
          Description copied from class: Timeline
          +
          Returns the index of the window before the window at index windowIndex depending on the + repeatMode and whether shuffling is enabled.
          +
          +
          Overrides:
          +
          getPreviousWindowIndex in class Timeline
          +
          Parameters:
          +
          windowIndex - Index of a window in the timeline.
          +
          repeatMode - A repeat mode.
          +
          shuffleModeEnabled - Whether shuffling is enabled.
          +
          Returns:
          +
          The index of the previous window, or C.INDEX_UNSET if this is the first window.
          +
          +
        • +
        + + + +
          +
        • +

          getLastWindowIndex

          +
          public int getLastWindowIndex​(boolean shuffleModeEnabled)
          +
          Description copied from class: Timeline
          +
          Returns the index of the last window in the playback order depending on whether shuffling is + enabled.
          +
          +
          Overrides:
          +
          getLastWindowIndex in class Timeline
          +
          Parameters:
          +
          shuffleModeEnabled - Whether shuffling is enabled.
          +
          Returns:
          +
          The index of the last window in the playback order, or C.INDEX_UNSET if the + timeline is empty.
          +
          +
        • +
        + + + +
          +
        • +

          getFirstWindowIndex

          +
          public int getFirstWindowIndex​(boolean shuffleModeEnabled)
          +
          Description copied from class: Timeline
          +
          Returns the index of the first window in the playback order depending on whether shuffling is + enabled.
          +
          +
          Overrides:
          +
          getFirstWindowIndex in class Timeline
          +
          Parameters:
          +
          shuffleModeEnabled - Whether shuffling is enabled.
          +
          Returns:
          +
          The index of the first window in the playback order, or C.INDEX_UNSET if the + timeline is empty.
          +
          +
        • +
        + + + +
          +
        • +

          getPeriodCount

          +
          public int getPeriodCount()
          +
          Description copied from class: Timeline
          +
          Returns the number of periods in the timeline.
          +
          +
          Specified by:
          +
          getPeriodCount in class Timeline
          +
          +
        • +
        + + + + + + + +
          +
        • +

          getIndexOfPeriod

          +
          public int getIndexOfPeriod​(Object uid)
          +
          Description copied from class: Timeline
          +
          Returns the index of the period identified by its unique Timeline.Period.uid, or C.INDEX_UNSET if the period is not in the timeline.
          +
          +
          Specified by:
          +
          getIndexOfPeriod in class Timeline
          +
          Parameters:
          +
          uid - A unique identifier for a period.
          +
          Returns:
          +
          The index of the period, or C.INDEX_UNSET if the period was not found.
          +
          +
        • +
        + + + +
          +
        • +

          getUidOfPeriod

          +
          public Object getUidOfPeriod​(int periodIndex)
          +
          Description copied from class: Timeline
          +
          Returns the unique id of the period identified by its index in the timeline.
          +
          +
          Specified by:
          +
          getUidOfPeriod in class Timeline
          +
          Parameters:
          +
          periodIndex - The index of the period.
          +
          Returns:
          +
          The unique id of the period.
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + + + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/Timeline.html b/docs/doc/reference/com/google/android/exoplayer2/Timeline.html index 3b920c7f43f..45d4c5a0570 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/Timeline.html +++ b/docs/doc/reference/com/google/android/exoplayer2/Timeline.html @@ -25,8 +25,8 @@ catch(err) { } //--> -var data = {"i0":10,"i1":10,"i2":6,"i3":10,"i4":10,"i5":10,"i6":10,"i7":6,"i8":10,"i9":6,"i10":10,"i11":10,"i12":10,"i13":6,"i14":10,"i15":42,"i16":6,"i17":6,"i18":10,"i19":10,"i20":10,"i21":10}; -var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],4:["t3","Abstract Methods"],8:["t4","Concrete Methods"],32:["t6","Deprecated Methods"]}; +var data = {"i0":10,"i1":10,"i2":6,"i3":10,"i4":10,"i5":10,"i6":10,"i7":6,"i8":10,"i9":6,"i10":10,"i11":10,"i12":10,"i13":6,"i14":10,"i15":6,"i16":6,"i17":10,"i18":10,"i19":10,"i20":10,"i21":10}; +var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],4:["t3","Abstract Methods"],8:["t4","Concrete Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; var tableTab = "tableTab"; @@ -134,7 +134,7 @@

    Class Timeline

    Direct Known Subclasses:
    -
    AbstractConcatenatedTimeline, FakeTimeline, ForwardingTimeline, MaskingMediaSource.PlaceholderTimeline, SinglePeriodTimeline
    +
    AbstractConcatenatedTimeline, FakeTimeline, ForwardingTimeline, MaskingMediaSource.PlaceholderTimeline, SinglePeriodTimeline, Timeline.RemotableTimeline

    public abstract class Timeline
    @@ -161,7 +161,7 @@ 

    Class Timeline

    The following examples illustrate timelines for various use cases. -

    Single media file or on-demand stream

    +

    Single media file or on-demand stream

    Example timeline for a
  single file @@ -171,7 +171,7 @@

    Single media file or on-demand stream

    playback. The window's default position is typically at the start of the period (indicated by the black dot in the figure above). -

    Playlist of media files or on-demand streams

    +

    Playlist of media files or on-demand streams

    Example timeline for a
  playlist of files @@ -182,7 +182,7 @@

    Playlist of media files or on-demand streams

    (e.g. their durations and whether the window is seekable) will often only become known when the player starts buffering the corresponding file or stream. -

    Live stream with limited availability

    +

    Live stream with limited availability

    Example timeline for
  a live stream with limited availability @@ -195,7 +195,7 @@

    Live stream with limited availability

    changes to the live window. Its default position is typically near to the live edge (indicated by the black dot in the figure above). -

    Live stream with indefinite availability

    +

    Live stream with indefinite availability

    Example timeline
  for a live stream with indefinite availability @@ -204,7 +204,7 @@

    Live stream with indefinite availability

    starts at the beginning of the period to indicate that all of the previously broadcast content can still be played. -

    Live stream with multiple periods

    +

    Live stream with multiple periods

    Example timeline
  for a live stream with multiple periods @@ -214,7 +214,7 @@

    Live stream with multiple periods

    limited availability case, except that the window may span more than one period. Multiple periods are also possible in the indefinite availability case. -

    On-demand stream followed by live stream

    +

    On-demand stream followed by live stream

    Example timeline for an
  on-demand stream followed by a live stream @@ -224,7 +224,7 @@

    On-demand stream followed by live stream

    of the on-demand stream ends, playback of the live stream will start from its default position near the live edge. -

    On-demand stream with mid-roll ads

    +

    On-demand stream with mid-roll ads

    Example
  timeline for an on-demand stream with mid-roll ad groups @@ -260,6 +260,13 @@

    Nested Class Summary

    static class  +Timeline.RemotableTimeline + +
    A concrete class of Timeline to restore a Timeline instance from a Bundle sent by another process via IBinder.
    + + + +static class  Timeline.Window
    Holds information about a window in a Timeline.
    @@ -337,7 +344,7 @@

    Constructor Summary

    Method Summary

    - + @@ -473,17 +480,6 @@

    Method Summary

    - - - - - - + - + - + - + - + + + + +
    All Methods Instance Methods Abstract Methods Concrete Methods Deprecated Methods All Methods Instance Methods Abstract Methods Concrete Methods 
    Modifier and Type Method
    Timeline.WindowgetWindow​(int windowIndex, - Timeline.Window window, - boolean setTag) -
    Deprecated. - -
    -
    abstract Timeline.Window getWindow​(int windowIndex, Timeline.Window window, @@ -492,26 +488,26 @@

    Method Summary

    Populates a Timeline.Window with data for the window at the specified index.
    abstract int getWindowCount()
    Returns the number of windows in the timeline.
    int hashCode()  
    boolean isEmpty()
    Returns whether the timeline is empty.
    boolean isLastPeriod​(int periodIndex, Timeline.Period period, @@ -523,13 +519,17 @@

    Method Summary

    repeatMode
    and whether shuffling is enabled.
    Bundle toBundle()
    Returns a Bundle representing the information stored in this object.
    BundletoBundle​(boolean excludeMediaItems)
    - - - - @@ -983,6 +968,24 @@

    hashCode

    + + + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/analytics/AnalyticsCollector.html b/docs/doc/reference/com/google/android/exoplayer2/analytics/AnalyticsCollector.html index dcf55fd2516..9036aecfbda 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/analytics/AnalyticsCollector.html +++ b/docs/doc/reference/com/google/android/exoplayer2/analytics/AnalyticsCollector.html @@ -25,8 +25,8 @@ catch(err) { } //--> -var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10,"i21":10,"i22":10,"i23":10,"i24":10,"i25":10,"i26":10,"i27":10,"i28":10,"i29":10,"i30":10,"i31":10,"i32":10,"i33":10,"i34":10,"i35":10,"i36":10,"i37":10,"i38":10,"i39":10,"i40":10,"i41":10,"i42":10,"i43":10,"i44":10,"i45":10,"i46":10,"i47":10,"i48":10,"i49":10,"i50":10,"i51":10,"i52":10,"i53":10,"i54":10,"i55":10,"i56":10,"i57":10,"i58":10,"i59":10,"i60":10,"i61":10,"i62":10,"i63":10}; -var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]}; +var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10,"i21":10,"i22":10,"i23":10,"i24":10,"i25":10,"i26":10,"i27":10,"i28":10,"i29":10,"i30":10,"i31":10,"i32":10,"i33":10,"i34":10,"i35":10,"i36":10,"i37":10,"i38":10,"i39":10,"i40":10,"i41":10,"i42":10,"i43":10,"i44":10,"i45":10,"i46":10,"i47":10,"i48":10,"i49":10,"i50":42,"i51":10,"i52":10,"i53":10,"i54":10,"i55":10,"i56":10,"i57":10,"i58":10,"i59":10,"i60":10,"i61":10,"i62":10,"i63":10,"i64":10,"i65":10,"i66":10,"i67":10,"i68":10}; +var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"],32:["t6","Deprecated Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; var tableTab = "tableTab"; @@ -219,7 +219,7 @@

    Constructor Summary

    Method Summary

    - + @@ -340,15 +340,23 @@

    Method Summary

    + + + + + + long bytesTransferred, + long bitrateEstimate) - + - + @@ -365,7 +373,7 @@

    Method Summary

    Called each time keys are loaded.
    - + @@ -373,7 +381,7 @@

    Method Summary

    Called each time offline keys are removed.
    - + @@ -381,7 +389,7 @@

    Method Summary

    Called each time offline keys are restored.
    - + - + - + @@ -407,7 +415,7 @@

    Method Summary

    Called each time a drm session is released.
    - + @@ -415,21 +423,21 @@

    Method Summary

    Called to report the number of frames dropped by the renderer.
    - + - + - + - + - + - + - + + + + + + @@ -480,55 +495,62 @@

    Method Summary

    to the current repeat mode. - + - + - + - + - + - + - + - + - + - + + + + + + @@ -536,7 +558,7 @@

    Method Summary

    Called when the value returned from Player.getPlayWhenReady() changes.
    - + - + @@ -554,40 +576,54 @@

    Method Summary

    renderer was reset, or since the stream being rendered was changed. - + - + + + + + + + + + + + - + - + - + - + @@ -596,7 +632,7 @@

    Method Summary

    rendered. - + @@ -604,7 +640,7 @@

    Method Summary

    Called when the timeline has been refreshed.
    - + @@ -612,7 +648,7 @@

    Method Summary

    Called when the available or selected tracks change.
    - + - + - + - + - + - + - + @@ -667,7 +703,7 @@

    Method Summary

    Called to report the video processing offset of video frames processed by the video renderer.
    - + @@ -675,35 +711,35 @@

    Method Summary

    Called when the format of the media being consumed by the renderer changes.
    - + - + - + - + - + - + @@ -720,7 +756,7 @@

    Method Summary

    Sets the player for which data will be collected.
    - + @@ -755,14 +791,14 @@

    Methods inherited from interface com.google.android.exoplayer2.drm.

    Methods inherited from interface com.google.android.exoplayer2.Player.EventListener

    -onLoadingChanged, onPositionDiscontinuity, onTimelineChanged +onLoadingChanged, onPositionDiscontinuity - - - -
      -
    • -

      onMetadata

      -
      public final void onMetadata​(Metadata metadata)
      -
      Called when there is metadata associated with current playback time.
      -
      -
      Specified by:
      -
      onMetadata in interface MetadataOutput
      -
      Specified by:
      -
      onMetadata in interface Player.Listener
      -
      Parameters:
      -
      metadata - The metadata.
      -
      -
    • -
    @@ -1100,7 +1118,7 @@

    onAudioSinkError

    This method being called does not indicate that playback has failed, or that it will fail. The player may be able to recover from the error. Hence applications should not implement this method to display a user visible error or initiate an application level retry. - Player.Listener.onPlayerError(com.google.android.exoplayer2.ExoPlaybackException) is the appropriate place to implement such behavior. This + Player.Listener.onPlayerError(com.google.android.exoplayer2.PlaybackException) is the appropriate place to implement such behavior. This method is called to provide the application with an opportunity to log the error if it wishes to do so.

    @@ -1124,7 +1142,7 @@

    onAudioCodecError

    This method being called does not indicate that playback has failed, or that it will fail. The player may be able to recover from the error. Hence applications should not implement this method to display a user visible error or initiate an application level retry. - Player.Listener.onPlayerError(com.google.android.exoplayer2.ExoPlaybackException) is the appropriate place to implement such behavior. This + Player.Listener.onPlayerError(com.google.android.exoplayer2.PlaybackException) is the appropriate place to implement such behavior. This method is called to provide the application with an opportunity to log the error if it wishes to do so.

    @@ -1395,7 +1413,7 @@

    onVideoCodecError

    This method being called does not indicate that playback has failed, or that it will fail. The player may be able to recover from the error. Hence applications should not implement this method to display a user visible error or initiate an application level retry. - Player.Listener.onPlayerError(com.google.android.exoplayer2.ExoPlaybackException) is the appropriate place to implement such behavior. This + Player.Listener.onPlayerError(com.google.android.exoplayer2.PlaybackException) is the appropriate place to implement such behavior. This method is called to provide the application with an opportunity to log the error if it wishes to do so.

    @@ -1532,7 +1550,7 @@

    onLoadError

    This method being called does not indicate that playback has failed, or that it will fail. The player may be able to recover from the error. Hence applications should not implement this method to display a user visible error or initiate an application level retry. - Player.Listener.onPlayerError(com.google.android.exoplayer2.ExoPlaybackException) is the appropriate place to implement such behavior. This + Player.Listener.onPlayerError(com.google.android.exoplayer2.PlaybackException) is the appropriate place to implement such behavior. This method is called to provide the application with an opportunity to log the error if it wishes to do so.

    @@ -1688,28 +1706,12 @@

    onTracksChanged

    • onStaticMetadataChanged

      -
      public final void onStaticMetadataChanged​(List<Metadata> metadataList)
      -
      Description copied from interface: Player.EventListener
      -
      Called when the static metadata changes. - -

      The provided metadataList is an immutable list of Metadata instances, - where the elements correspond to the current track - selections, or an empty list if there are no track selections or the selected tracks contain - no static metadata. - -

      The metadata is considered static in the sense that it comes from the tracks' declared - Formats, rather than being timed (or dynamic) metadata, which is represented within a - metadata track. - -

      Player.EventListener.onEvents(Player, Events) will also be called to report this event along with - other events that happen in the same Looper message queue iteration.

      +
      @Deprecated
      +public final void onStaticMetadataChanged​(List<Metadata> metadataList)
      +
      Deprecated.
      Specified by:
      onStaticMetadataChanged in interface Player.EventListener
      -
      Specified by:
      -
      onStaticMetadataChanged in interface Player.Listener
      -
      Parameters:
      -
      metadataList - The static metadata.
    @@ -1735,6 +1737,29 @@

    onIsLoadingChanged

    + + + + @@ -1757,7 +1782,7 @@

    onPlayerStateChanged

  • onPlaybackStateChanged

    public final void onPlaybackStateChanged​(@State
    -                                         int state)
    + int playbackState)
    Description copied from interface: Player.EventListener
    Called when the value returned from Player.getPlaybackState() changes. @@ -1769,7 +1794,7 @@

    onPlaybackStateChanged

    Specified by:
    onPlaybackStateChanged in interface Player.Listener
    Parameters:
    -
    state - The new playback state.
    +
    playbackState - The new playback state.
  • @@ -1888,24 +1913,27 @@

    onShuffleModeEnabledChanged

    - +
    + + + + + + + + + + + + @@ -1978,8 +2071,8 @@

    onMediaMetadataChanged

    Called when the combined MediaMetadata changes.

    The provided MediaMetadata is a combination of the MediaItem.mediaMetadata - and the static and dynamic metadata sourced from Player.EventListener.onStaticMetadataChanged(List) and - MetadataOutput.onMetadata(Metadata). + and the static and dynamic metadata from the track + selections' formats and MetadataOutput.onMetadata(Metadata).

    Player.EventListener.onEvents(Player, Events) will also be called to report this event along with other events that happen in the same Looper message queue iteration.

    @@ -1993,6 +2086,42 @@

    onMediaMetadataChanged

    + + + + + + + + @@ -2013,8 +2142,8 @@

    onSeekProcessed

  • onBandwidthSample

    public final void onBandwidthSample​(int elapsedMs,
    -                                    long bytes,
    -                                    long bitrate)
    + long bytesTransferred, + long bitrateEstimate)
    Description copied from interface: BandwidthMeter.EventListener
    Called periodically to indicate that bytes have been transferred or the estimated bitrate has changed. @@ -2028,8 +2157,8 @@

    onBandwidthSample

    elapsedMs - The time taken to transfer bytesTransferred, in milliseconds. This is at most the elapsed time since the last callback, but may be less if there were periods during which data was not being transferred.
    -
    bytes - The number of bytes transferred since the last callback.
    -
    bitrate - The estimated bitrate in bits/sec.
    +
    bytesTransferred - The number of bytes transferred since the last callback.
    +
    bitrateEstimate - The estimated bitrate in bits/sec.
  • @@ -2092,7 +2221,7 @@

    onDrmSessionManagerError

    This method being called does not indicate that playback has failed, or that it will fail. The player may be able to recover from the error and continue. Hence applications should not implement this method to display a user visible error or initiate an application - level retry (Player.Listener.onPlayerError(com.google.android.exoplayer2.ExoPlaybackException) is the appropriate place to implement such + level retry (Player.Listener.onPlayerError(com.google.android.exoplayer2.PlaybackException) is the appropriate place to implement such behavior). This method is called to provide the application with an opportunity to log the error if it wishes to do so.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/analytics/AnalyticsListener.Events.html b/docs/doc/reference/com/google/android/exoplayer2/analytics/AnalyticsListener.Events.html index ba491abe23c..1dc95dc4657 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/analytics/AnalyticsListener.Events.html +++ b/docs/doc/reference/com/google/android/exoplayer2/analytics/AnalyticsListener.Events.html @@ -156,7 +156,7 @@

    Constructor Summary

    - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + @@ -441,12 +455,19 @@

    Field Summary

    + + + + + - + - + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + DecoderCounters decoderCounters) @@ -647,7 +684,7 @@

    Method Summary

    + DecoderCounters decoderCounters) @@ -708,6 +745,14 @@

    Method Summary

    + + + + + - + - + - + - + - + @@ -771,28 +816,28 @@

    Method Summary

    Called when the downstream format sent to the renderers changed.
    - + - + - + - + - + @@ -809,7 +854,7 @@

    Method Summary

    Called each time a drm session is acquired.
    - + @@ -817,14 +862,14 @@

    Method Summary

    Called when a drm error occurs.
    - + - + - + @@ -841,7 +886,7 @@

    Method Summary

    Called after one or more events occurred.
    - + @@ -849,7 +894,7 @@

    Method Summary

    Called when the player starts or stops loading data from a source.
    - + @@ -857,7 +902,7 @@

    Method Summary

    Called when the player starts or stops playing.
    - + - + - + - + @@ -896,7 +941,7 @@

    Method Summary

    - + - + + + + + + - + @@ -922,7 +976,7 @@

    Method Summary

    Called when the combined MediaMetadata changes.
    - + @@ -930,7 +984,7 @@

    Method Summary

    Called when there is Metadata associated with the current playback time.
    - + @@ -938,7 +992,7 @@

    Method Summary

    Called when the playback parameters changed.
    - + @@ -946,7 +1000,7 @@

    Method Summary

    Called when the playback state changed.
    - + @@ -954,22 +1008,22 @@

    Method Summary

    Called when playback suppression reason changed.
    - + - + - + - + - + + + + + + - + @@ -1000,7 +1062,7 @@

    Method Summary

    - + - + - + @@ -1028,7 +1090,23 @@

    Method Summary

    Called when the repeat mode changed.
    - + + + + + + + + + + + - + - + @@ -1055,7 +1133,7 @@

    Method Summary

    Called when the shuffle mode changed.
    - + @@ -1063,15 +1141,19 @@

    Method Summary

    Called when skipping silences is enabled or disabled in the audio stream.
    - + - + - + @@ -1088,7 +1170,7 @@

    Method Summary

    Called when the timeline changed.
    - + - + @@ -1106,7 +1188,7 @@

    Method Summary

    re-buffered in a different format. - + @@ -1114,7 +1196,7 @@

    Method Summary

    Called when a video decoder encounters an error.
    - + - + - + @@ -1143,23 +1225,23 @@

    Method Summary

    Called when a video renderer releases a decoder.
    - + + DecoderCounters decoderCounters) - + + DecoderCounters decoderCounters) - + - + @@ -1179,7 +1261,7 @@

    Method Summary

    - + - + - + @@ -1210,7 +1292,7 @@

    Method Summary

    there's a change in the size or pixel aspect ratio of the video being rendered. - + @@ -1283,8 +1365,11 @@

    EVENT_TRACKS_CHANGED

    + + + + @@ -1445,6 +1544,62 @@

    EVENT_MEDIA_METADATA_CHANGED

    + + + + + + + + + + + + + + + + @@ -2205,6 +2360,55 @@

    onPlaybackParametersChanged

    + + + +
      +
    • +

      onSeekBackIncrementChanged

      +
      default void onSeekBackIncrementChanged​(AnalyticsListener.EventTime eventTime,
      +                                        long seekBackIncrementMs)
      +
      Called when the seek back increment changed.
      +
      +
      Parameters:
      +
      eventTime - The event time.
      +
      seekBackIncrementMs - The seek back increment, in milliseconds.
      +
      +
    • +
    + + + +
      +
    • +

      onSeekForwardIncrementChanged

      +
      default void onSeekForwardIncrementChanged​(AnalyticsListener.EventTime eventTime,
      +                                           long seekForwardIncrementMs)
      +
      Called when the seek forward increment changed.
      +
      +
      Parameters:
      +
      eventTime - The event time.
      +
      seekForwardIncrementMs - The seek forward increment, in milliseconds.
      +
      +
    • +
    + + + +
      +
    • +

      onMaxSeekToPreviousPositionChanged

      +
      default void onMaxSeekToPreviousPositionChanged​(AnalyticsListener.EventTime eventTime,
      +                                                int maxSeekToPreviousPositionMs)
      +
      Called when the maximum position for which Player.seekToPrevious() seeks to the + previous window changes.
      +
      +
      Parameters:
      +
      eventTime - The event time.
      +
      maxSeekToPreviousPositionMs - The maximum seek to previous position, in milliseconds.
      +
      +
    • +
    @@ -2268,15 +2472,33 @@

    onLoadingChanged

    - + + + +
      +
    • +

      onAvailableCommandsChanged

      +
      default void onAvailableCommandsChanged​(AnalyticsListener.EventTime eventTime,
      +                                        Player.Commands availableCommands)
      +
      Called when the player's available commands changed.
      +
      +
      Parameters:
      +
      eventTime - The event time.
      +
      availableCommands - The available commands.
      +
      +
    • +
    + + + + + @@ -2415,7 +2646,7 @@

    onLoadError

    This method being called does not indicate that playback has failed, or that it will fail. The player may be able to recover from the error. Hence applications should not implement this method to display a user visible error or initiate an application level retry. - Player.Listener.onPlayerError(com.google.android.exoplayer2.ExoPlaybackException) is the appropriate place to implement such behavior. This + Player.Listener.onPlayerError(com.google.android.exoplayer2.PlaybackException) is the appropriate place to implement such behavior. This method is called to provide the application with an opportunity to log the error if it wishes to do so.

    @@ -2567,13 +2798,13 @@

    onDecoderDisabled

  • onAudioEnabled

    default void onAudioEnabled​(AnalyticsListener.EventTime eventTime,
    -                            DecoderCounters counters)
    + DecoderCounters decoderCounters)
    Called when an audio renderer is enabled.
    Parameters:
    eventTime - The event time.
    -
    counters - DecoderCounters that will be updated by the renderer for as long as it - remains enabled.
    +
    decoderCounters - DecoderCounters that will be updated by the renderer for as long + as it remains enabled.
  • @@ -2710,12 +2941,12 @@

    onAudioDecoderReleased

  • onAudioDisabled

    default void onAudioDisabled​(AnalyticsListener.EventTime eventTime,
    -                             DecoderCounters counters)
    + DecoderCounters decoderCounters)
    Called when an audio renderer is disabled.
    Parameters:
    eventTime - The event time.
    -
    counters - DecoderCounters that were updated by the renderer.
    +
    decoderCounters - DecoderCounters that were updated by the renderer.
  • @@ -2780,7 +3011,7 @@

    onAudioSinkError

    This method being called does not indicate that playback has failed, or that it will fail. The player may be able to recover from the error. Hence applications should not implement this method to display a user visible error or initiate an application level retry. - Player.Listener.onPlayerError(com.google.android.exoplayer2.ExoPlaybackException) is the appropriate place to implement such behavior. This + Player.Listener.onPlayerError(com.google.android.exoplayer2.PlaybackException) is the appropriate place to implement such behavior. This method is called to provide the application with an opportunity to log the error if it wishes to do so.

    @@ -2803,7 +3034,7 @@

    onAudioCodecError

    This method being called does not indicate that playback has failed, or that it will fail. The player may be able to recover from the error. Hence applications should not implement this method to display a user visible error or initiate an application level retry. - Player.Listener.onPlayerError(com.google.android.exoplayer2.ExoPlaybackException) is the appropriate place to implement such behavior. This + Player.Listener.onPlayerError(com.google.android.exoplayer2.PlaybackException) is the appropriate place to implement such behavior. This method is called to provide the application with an opportunity to log the error if it wishes to do so.

    @@ -2837,13 +3068,13 @@

    onVolumeChanged

  • onVideoEnabled

    default void onVideoEnabled​(AnalyticsListener.EventTime eventTime,
    -                            DecoderCounters counters)
    + DecoderCounters decoderCounters)
    Called when a video renderer is enabled.
    Parameters:
    eventTime - The event time.
    -
    counters - DecoderCounters that will be updated by the renderer for as long as it - remains enabled.
    +
    decoderCounters - DecoderCounters that will be updated by the renderer for as long + as it remains enabled.
  • @@ -2961,12 +3192,12 @@

    onVideoDecoderReleased

  • onVideoDisabled

    default void onVideoDisabled​(AnalyticsListener.EventTime eventTime,
    -                             DecoderCounters counters)
    + DecoderCounters decoderCounters)
    Called when a video renderer is disabled.
    Parameters:
    eventTime - The event time.
    -
    counters - DecoderCounters that were updated by the renderer.
    +
    decoderCounters - DecoderCounters that were updated by the renderer.
  • @@ -3009,7 +3240,7 @@

    onVideoCodecError

    This method being called does not indicate that playback has failed, or that it will fail. The player may be able to recover from the error. Hence applications should not implement this method to display a user visible error or initiate an application level retry. - Player.Listener.onPlayerError(com.google.android.exoplayer2.ExoPlaybackException) is the appropriate place to implement such behavior. This + Player.Listener.onPlayerError(com.google.android.exoplayer2.PlaybackException) is the appropriate place to implement such behavior. This method is called to provide the application with an opportunity to log the error if it wishes to do so.

    @@ -3151,7 +3382,7 @@

    onDrmSessionManagerError

    This method being called does not indicate that playback has failed, or that it will fail. The player may be able to recover from the error. Hence applications should not implement this method to display a user visible error or initiate an application level retry. - Player.Listener.onPlayerError(com.google.android.exoplayer2.ExoPlaybackException) is the appropriate place to implement such behavior. This + Player.Listener.onPlayerError(com.google.android.exoplayer2.PlaybackException) is the appropriate place to implement such behavior. This method is called to provide the application with an opportunity to log the error if it wishes to do so.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/analytics/PlaybackStatsListener.html b/docs/doc/reference/com/google/android/exoplayer2/analytics/PlaybackStatsListener.html index 037acf1a8cb..f2a47b03917 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/analytics/PlaybackStatsListener.html +++ b/docs/doc/reference/com/google/android/exoplayer2/analytics/PlaybackStatsListener.html @@ -193,7 +193,7 @@

    Field Summary

    Fields inherited from interface com.google.android.exoplayer2.analytics.AnalyticsListener

    -EVENT_AUDIO_ATTRIBUTES_CHANGED, EVENT_AUDIO_CODEC_ERROR, EVENT_AUDIO_DECODER_INITIALIZED, EVENT_AUDIO_DECODER_RELEASED, EVENT_AUDIO_DISABLED, EVENT_AUDIO_ENABLED, EVENT_AUDIO_INPUT_FORMAT_CHANGED, EVENT_AUDIO_POSITION_ADVANCING, EVENT_AUDIO_SESSION_ID, EVENT_AUDIO_SINK_ERROR, EVENT_AUDIO_UNDERRUN, EVENT_BANDWIDTH_ESTIMATE, EVENT_DOWNSTREAM_FORMAT_CHANGED, EVENT_DRM_KEYS_LOADED, EVENT_DRM_KEYS_REMOVED, EVENT_DRM_KEYS_RESTORED, EVENT_DRM_SESSION_ACQUIRED, EVENT_DRM_SESSION_MANAGER_ERROR, EVENT_DRM_SESSION_RELEASED, EVENT_DROPPED_VIDEO_FRAMES, EVENT_IS_LOADING_CHANGED, EVENT_IS_PLAYING_CHANGED, EVENT_LOAD_CANCELED, EVENT_LOAD_COMPLETED, EVENT_LOAD_ERROR, EVENT_LOAD_STARTED, EVENT_MEDIA_ITEM_TRANSITION, EVENT_MEDIA_METADATA_CHANGED, EVENT_METADATA, EVENT_PLAY_WHEN_READY_CHANGED, EVENT_PLAYBACK_PARAMETERS_CHANGED, EVENT_PLAYBACK_STATE_CHANGED, EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED, EVENT_PLAYER_ERROR, EVENT_PLAYER_RELEASED, EVENT_POSITION_DISCONTINUITY, EVENT_RENDERED_FIRST_FRAME, EVENT_REPEAT_MODE_CHANGED, EVENT_SHUFFLE_MODE_ENABLED_CHANGED, EVENT_SKIP_SILENCE_ENABLED_CHANGED, EVENT_STATIC_METADATA_CHANGED, EVENT_SURFACE_SIZE_CHANGED, EVENT_TIMELINE_CHANGED, EVENT_TRACKS_CHANGED, EVENT_UPSTREAM_DISCARDED, EVENT_VIDEO_CODEC_ERROR, EVENT_VIDEO_DECODER_INITIALIZED, EVENT_VIDEO_DECODER_RELEASED, EVENT_VIDEO_DISABLED, EVENT_VIDEO_ENABLED, EVENT_VIDEO_FRAME_PROCESSING_OFFSET, EVENT_VIDEO_INPUT_FORMAT_CHANGED, EVENT_VIDEO_SIZE_CHANGED, EVENT_VOLUME_CHANGED +EVENT_AUDIO_ATTRIBUTES_CHANGED, EVENT_AUDIO_CODEC_ERROR, EVENT_AUDIO_DECODER_INITIALIZED, EVENT_AUDIO_DECODER_RELEASED, EVENT_AUDIO_DISABLED, EVENT_AUDIO_ENABLED, EVENT_AUDIO_INPUT_FORMAT_CHANGED, EVENT_AUDIO_POSITION_ADVANCING, EVENT_AUDIO_SESSION_ID, EVENT_AUDIO_SINK_ERROR, EVENT_AUDIO_UNDERRUN, EVENT_AVAILABLE_COMMANDS_CHANGED, EVENT_BANDWIDTH_ESTIMATE, EVENT_DOWNSTREAM_FORMAT_CHANGED, EVENT_DRM_KEYS_LOADED, EVENT_DRM_KEYS_REMOVED, EVENT_DRM_KEYS_RESTORED, EVENT_DRM_SESSION_ACQUIRED, EVENT_DRM_SESSION_MANAGER_ERROR, EVENT_DRM_SESSION_RELEASED, EVENT_DROPPED_VIDEO_FRAMES, EVENT_IS_LOADING_CHANGED, EVENT_IS_PLAYING_CHANGED, EVENT_LOAD_CANCELED, EVENT_LOAD_COMPLETED, EVENT_LOAD_ERROR, EVENT_LOAD_STARTED, EVENT_MAX_SEEK_TO_PREVIOUS_POSITION_CHANGED, EVENT_MEDIA_ITEM_TRANSITION, EVENT_MEDIA_METADATA_CHANGED, EVENT_METADATA, EVENT_PLAY_WHEN_READY_CHANGED, EVENT_PLAYBACK_PARAMETERS_CHANGED, EVENT_PLAYBACK_STATE_CHANGED, EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED, EVENT_PLAYER_ERROR, EVENT_PLAYER_RELEASED, EVENT_PLAYLIST_METADATA_CHANGED, EVENT_POSITION_DISCONTINUITY, EVENT_RENDERED_FIRST_FRAME, EVENT_REPEAT_MODE_CHANGED, EVENT_SEEK_BACK_INCREMENT_CHANGED, EVENT_SEEK_FORWARD_INCREMENT_CHANGED, EVENT_SHUFFLE_MODE_ENABLED_CHANGED, EVENT_SKIP_SILENCE_ENABLED_CHANGED, EVENT_STATIC_METADATA_CHANGED, EVENT_SURFACE_SIZE_CHANGED, EVENT_TIMELINE_CHANGED, EVENT_TRACKS_CHANGED, EVENT_UPSTREAM_DISCARDED, EVENT_VIDEO_CODEC_ERROR, EVENT_VIDEO_DECODER_INITIALIZED, EVENT_VIDEO_DECODER_RELEASED, EVENT_VIDEO_DISABLED, EVENT_VIDEO_ENABLED, EVENT_VIDEO_FRAME_PROCESSING_OFFSET, EVENT_VIDEO_INPUT_FORMAT_CHANGED, EVENT_VIDEO_SIZE_CHANGED, EVENT_VOLUME_CHANGED @@ -255,8 +255,8 @@

    Method Summary

    + String contentSessionId, + String adSessionId) @@ -318,8 +318,8 @@

    Method Summary

    + String sessionId) @@ -336,7 +336,7 @@

    Method Summary

    + String sessionId) @@ -344,8 +344,8 @@

    Method Summary

    + String sessionId, + boolean automaticTransitionToNextPlayback) @@ -372,7 +372,7 @@

    Methods inherited from class java.lang.AnalyticsListener

    -onAudioAttributesChanged, onAudioCodecError, onAudioDecoderInitialized, onAudioDecoderInitialized, onAudioDecoderReleased, onAudioDisabled, onAudioEnabled, onAudioInputFormatChanged, onAudioInputFormatChanged, onAudioPositionAdvancing, onAudioSessionIdChanged, onAudioSinkError, onAudioUnderrun, onDecoderDisabled, onDecoderEnabled, onDecoderInitialized, onDecoderInputFormatChanged, onDrmKeysLoaded, onDrmKeysRemoved, onDrmKeysRestored, onDrmSessionAcquired, onDrmSessionAcquired, onDrmSessionReleased, onIsLoadingChanged, onIsPlayingChanged, onLoadCanceled, onLoadCompleted, onLoadingChanged, onLoadStarted, onMediaItemTransition, onMediaMetadataChanged, onMetadata, onPlaybackParametersChanged, onPlaybackStateChanged, onPlaybackSuppressionReasonChanged, onPlayerError, onPlayerReleased, onPlayerStateChanged, onPlayWhenReadyChanged, onPositionDiscontinuity, onRenderedFirstFrame, onRepeatModeChanged, onSeekProcessed, onSeekStarted, onShuffleModeChanged, onSkipSilenceEnabledChanged, onStaticMetadataChanged, onSurfaceSizeChanged, onTimelineChanged, onTracksChanged, onUpstreamDiscarded, onVideoCodecError, onVideoDecoderInitialized, onVideoDecoderInitialized, onVideoDecoderReleased, onVideoDisabled, onVideoEnabled, onVideoFrameProcessingOffset, onVideoInputFormatChanged, onVideoInputFormatChanged, onVideoSizeChanged, onVolumeChanged +onAudioAttributesChanged, onAudioCodecError, onAudioDecoderInitialized, onAudioDecoderInitialized, onAudioDecoderReleased, onAudioDisabled, onAudioEnabled, onAudioInputFormatChanged, onAudioInputFormatChanged, onAudioPositionAdvancing, onAudioSessionIdChanged, onAudioSinkError, onAudioUnderrun, onAvailableCommandsChanged, onDecoderDisabled, onDecoderEnabled, onDecoderInitialized, onDecoderInputFormatChanged, onDrmKeysLoaded, onDrmKeysRemoved, onDrmKeysRestored, onDrmSessionAcquired, onDrmSessionAcquired, onDrmSessionReleased, onIsLoadingChanged, onIsPlayingChanged, onLoadCanceled, onLoadCompleted, onLoadingChanged, onLoadStarted, onMaxSeekToPreviousPositionChanged, onMediaItemTransition, onMediaMetadataChanged, onMetadata, onPlaybackParametersChanged, onPlaybackStateChanged, onPlaybackSuppressionReasonChanged, onPlayerError, onPlayerReleased, onPlayerStateChanged, onPlaylistMetadataChanged, onPlayWhenReadyChanged, onPositionDiscontinuity, onRenderedFirstFrame, onRepeatModeChanged, onSeekBackIncrementChanged, onSeekForwardIncrementChanged, onSeekProcessed, onSeekStarted, onShuffleModeChanged, onSkipSilenceEnabledChanged, onStaticMetadataChanged, onSurfaceSizeChanged, onTimelineChanged, onTracksChanged, onUpstreamDiscarded, onVideoCodecError, onVideoDecoderInitialized, onVideoDecoderInitialized, onVideoDecoderReleased, onVideoDisabled, onVideoEnabled, onVideoFrameProcessingOffset, onVideoInputFormatChanged, onVideoInputFormatChanged, onVideoSizeChanged, onVolumeChanged @@ -458,7 +458,7 @@

    getPlaybackStats

  • onSessionCreated

    public void onSessionCreated​(AnalyticsListener.EventTime eventTime,
    -                             String session)
    + String sessionId)
    Description copied from interface: PlaybackSessionManager.Listener
    Called when a new session is created as a result of PlaybackSessionManager.updateSessions(EventTime).
    @@ -466,7 +466,7 @@

    onSessionCreated

    onSessionCreated in interface PlaybackSessionManager.Listener
    Parameters:
    eventTime - The AnalyticsListener.EventTime at which the session is created.
    -
    session - The identifier of the new session.
    +
    sessionId - The identifier of the new session.
  • @@ -477,7 +477,7 @@

    onSessionCreated

  • onSessionActive

    public void onSessionActive​(AnalyticsListener.EventTime eventTime,
    -                            String session)
    + String sessionId)
    Description copied from interface: PlaybackSessionManager.Listener
    Called when a session becomes active, i.e. playing in the foreground.
    @@ -485,7 +485,7 @@

    onSessionActive

    onSessionActive in interface PlaybackSessionManager.Listener
    Parameters:
    eventTime - The AnalyticsListener.EventTime at which the session becomes active.
    -
    session - The identifier of the session.
    +
    sessionId - The identifier of the session.
  • @@ -496,8 +496,8 @@

    onSessionActive

  • onAdPlaybackStarted

    public void onAdPlaybackStarted​(AnalyticsListener.EventTime eventTime,
    -                                String contentSession,
    -                                String adSession)
    + String contentSessionId, + String adSessionId)
    Description copied from interface: PlaybackSessionManager.Listener
    Called when a session is interrupted by ad playback.
    @@ -505,8 +505,8 @@

    onAdPlaybackStarted

    onAdPlaybackStarted in interface PlaybackSessionManager.Listener
    Parameters:
    eventTime - The AnalyticsListener.EventTime at which the ad playback starts.
    -
    contentSession - The session identifier of the content session.
    -
    adSession - The identifier of the ad session.
    +
    contentSessionId - The session identifier of the content session.
    +
    adSessionId - The identifier of the ad session.
  • @@ -517,8 +517,8 @@

    onAdPlaybackStarted

  • onSessionFinished

    public void onSessionFinished​(AnalyticsListener.EventTime eventTime,
    -                              String session,
    -                              boolean automaticTransition)
    + String sessionId, + boolean automaticTransitionToNextPlayback)
    Description copied from interface: PlaybackSessionManager.Listener
    Called when a session is permanently finished.
    @@ -526,8 +526,8 @@

    onSessionFinished

    onSessionFinished in interface PlaybackSessionManager.Listener
    Parameters:
    eventTime - The AnalyticsListener.EventTime at which the session finished.
    -
    session - The identifier of the finished session.
    -
    automaticTransition - Whether the session finished because of an automatic +
    sessionId - The identifier of the finished session.
    +
    automaticTransitionToNextPlayback - Whether the session finished because of an automatic transition to the next playback item.
  • @@ -539,8 +539,8 @@

    onSessionFinished

  • onPositionDiscontinuity

    public void onPositionDiscontinuity​(AnalyticsListener.EventTime eventTime,
    -                                    Player.PositionInfo oldPositionInfo,
    -                                    Player.PositionInfo newPositionInfo,
    +                                    Player.PositionInfo oldPosition,
    +                                    Player.PositionInfo newPosition,
                                         @DiscontinuityReason
                                         int reason)
    Description copied from interface: AnalyticsListener
    @@ -550,8 +550,8 @@

    onPositionDiscontinuity

    onPositionDiscontinuity in interface AnalyticsListener
    Parameters:
    eventTime - The event time.
    -
    oldPositionInfo - The position before the discontinuity.
    -
    newPositionInfo - The position after the discontinuity.
    +
    oldPosition - The position before the discontinuity.
    +
    newPosition - The position after the discontinuity.
    reason - The reason for the position discontinuity.
  • @@ -596,7 +596,7 @@

    onLoadError

    This method being called does not indicate that playback has failed, or that it will fail. The player may be able to recover from the error. Hence applications should not implement this method to display a user visible error or initiate an application level retry. - Player.Listener.onPlayerError(com.google.android.exoplayer2.ExoPlaybackException) is the appropriate place to implement such behavior. This + Player.Listener.onPlayerError(com.google.android.exoplayer2.PlaybackException) is the appropriate place to implement such behavior. This method is called to provide the application with an opportunity to log the error if it wishes to do so.

    @@ -625,7 +625,7 @@

    onDrmSessionManagerError

    This method being called does not indicate that playback has failed, or that it will fail. The player may be able to recover from the error. Hence applications should not implement this method to display a user visible error or initiate an application level retry. - Player.Listener.onPlayerError(com.google.android.exoplayer2.ExoPlaybackException) is the appropriate place to implement such behavior. This + Player.Listener.onPlayerError(com.google.android.exoplayer2.PlaybackException) is the appropriate place to implement such behavior. This method is called to provide the application with an opportunity to log the error if it wishes to do so.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/audio/Ac3Util.html b/docs/doc/reference/com/google/android/exoplayer2/audio/Ac3Util.html index 59f23c34a5b..02a56bf85cb 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/audio/Ac3Util.html +++ b/docs/doc/reference/com/google/android/exoplayer2/audio/Ac3Util.html @@ -187,9 +187,9 @@

    Field Summary

    - + @@ -328,20 +328,20 @@

    Methods inherited from class java.lang. +
    • -

      E_AC_3_CODEC_STRING

      -
      public static final String E_AC_3_CODEC_STRING
      -
      A non-standard codec string for E-AC-3. Use of this constant allows for disambiguation between - regular AC-3 ("ec-3") and E-AC-3 ("ec+3") streams from the codec string alone. The standard is - to use "ec-3" for both, as per the MP4RA registered codec - types.
      +

      E_AC3_JOC_CODEC_STRING

      +
      public static final String E_AC3_JOC_CODEC_STRING
      +
      A non-standard codec string for E-AC3-JOC. Use of this constant allows for disambiguation + between regular E-AC3 ("ec-3") and E-AC3-JOC ("ec+3") streams from the codec string alone. The + standard is to use "ec-3" for both, as per the MP4RA + registered codec types.
      See Also:
      -
      Constant Field Values
      +
      Constant Field Values
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/audio/AudioCapabilitiesReceiver.html b/docs/doc/reference/com/google/android/exoplayer2/audio/AudioCapabilitiesReceiver.html index cfc52d28dc5..9e706414487 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/audio/AudioCapabilitiesReceiver.html +++ b/docs/doc/reference/com/google/android/exoplayer2/audio/AudioCapabilitiesReceiver.html @@ -273,8 +273,7 @@

    Method Detail

    register

    public AudioCapabilities register()
    Registers the receiver, meaning it will notify the listener when audio capability changes - occur. The current audio capabilities will be returned. It is important to call - unregister() when the receiver is no longer required.
    + occur. The current audio capabilities will be returned. It is important to call unregister() when the receiver is no longer required.
    Returns:
    The current audio capabilities for the device.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/audio/AudioProcessor.html b/docs/doc/reference/com/google/android/exoplayer2/audio/AudioProcessor.html index 68cdfdb6f10..eecefafcb39 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/audio/AudioProcessor.html +++ b/docs/doc/reference/com/google/android/exoplayer2/audio/AudioProcessor.html @@ -253,7 +253,7 @@

    Method Summary

    - + @@ -344,7 +344,7 @@

    isActive

    • queueInput

      -
      void queueInput​(ByteBuffer buffer)
      +
      void queueInput​(ByteBuffer inputBuffer)
      Queues audio data between the position and limit of the input buffer for processing. buffer must be a direct byte buffer with native byte order. Its contents are treated as read-only. Its position will be advanced by the number of bytes consumed (which may be zero). @@ -352,7 +352,7 @@

      queueInput

      previous buffer returned by getOutput().
      Parameters:
      -
      buffer - The input buffer to process.
      +
      inputBuffer - The input buffer to process.
    @@ -363,11 +363,10 @@

    queueInput

  • queueEndOfStream

    void queueEndOfStream()
    -
    Queues an end of stream signal. After this method has been called, - queueInput(ByteBuffer) may not be called until after the next call to - flush(). Calling getOutput() will return any remaining output data. Multiple - calls may be required to read all of the remaining output data. isEnded() will return - true once all remaining output data has been read.
    +
    Queues an end of stream signal. After this method has been called, queueInput(ByteBuffer) may not be called until after the next call to flush(). + Calling getOutput() will return any remaining output data. Multiple calls may be + required to read all of the remaining output data. isEnded() will return true + once all remaining output data has been read.
  • diff --git a/docs/doc/reference/com/google/android/exoplayer2/audio/AudioRendererEventListener.html b/docs/doc/reference/com/google/android/exoplayer2/audio/AudioRendererEventListener.html index 8b7454693ef..ac7f66f0c93 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/audio/AudioRendererEventListener.html +++ b/docs/doc/reference/com/google/android/exoplayer2/audio/AudioRendererEventListener.html @@ -430,7 +430,7 @@

    onAudioCodecError

    This method being called does not indicate that playback has failed, or that it will fail. The player may be able to recover from the error. Hence applications should not implement this method to display a user visible error or initiate an application level retry. - Player.Listener.onPlayerError(com.google.android.exoplayer2.ExoPlaybackException) is the appropriate place to implement such behavior. This + Player.Listener.onPlayerError(com.google.android.exoplayer2.PlaybackException) is the appropriate place to implement such behavior. This method is called to provide the application with an opportunity to log the error if it wishes to do so.

    @@ -454,7 +454,7 @@

    onAudioSinkError

    This method being called does not indicate that playback has failed, or that it will fail. The player may be able to recover from the error. Hence applications should not implement this method to display a user visible error or initiate an application level retry. - Player.Listener.onPlayerError(com.google.android.exoplayer2.ExoPlaybackException) is the appropriate place to implement such behavior. This + Player.Listener.onPlayerError(com.google.android.exoplayer2.PlaybackException) is the appropriate place to implement such behavior. This method is called to provide the application with an opportunity to log the error if it wishes to do so.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/audio/AudioSink.Listener.html b/docs/doc/reference/com/google/android/exoplayer2/audio/AudioSink.Listener.html index a48843218bc..fcd9bbc4132 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/audio/AudioSink.Listener.html +++ b/docs/doc/reference/com/google/android/exoplayer2/audio/AudioSink.Listener.html @@ -320,11 +320,11 @@

    onAudioSinkError

    The player may be able to recover from the error (for example by recreating the AudioTrack, possibly with different settings) and continue. Hence applications should not implement this method to display a user visible error or initiate an application level retry - (Player.Listener.onPlayerError(com.google.android.exoplayer2.ExoPlaybackException) is the appropriate place to implement such behavior). + (Player.Listener.onPlayerError(com.google.android.exoplayer2.PlaybackException) is the appropriate place to implement such behavior). This method is called to provide the application with an opportunity to log the error if it wishes to do so. -

    Fatal errors that cannot be recovered will be reported wrapped in a ExoPlaybackException by Player.Listener.onPlayerError(ExoPlaybackException). +

    Fatal errors that cannot be recovered will be reported wrapped in a ExoPlaybackException by Player.Listener.onPlayerError(PlaybackException).

    Parameters:
    audioSinkError - The error that occurred. Typically an AudioSink.InitializationException, diff --git a/docs/doc/reference/com/google/android/exoplayer2/audio/AudioSink.WriteException.html b/docs/doc/reference/com/google/android/exoplayer2/audio/AudioSink.WriteException.html index b31f611ddd7..75df441db56 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/audio/AudioSink.WriteException.html +++ b/docs/doc/reference/com/google/android/exoplayer2/audio/AudioSink.WriteException.html @@ -263,8 +263,7 @@

    Field Detail

    errorCode

    public final int errorCode
    The error value returned from the sink implementation. If the sink writes to a platform - AudioTrack, this will be the error value returned from - AudioTrack.write(byte[], int, int) or AudioTrack.write(ByteBuffer, int, int). + AudioTrack, this will be the error value returned from AudioTrack.write(byte[], int, int) or AudioTrack.write(ByteBuffer, int, int). Otherwise, the meaning of the error code depends on the sink implementation.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/audio/AudioSink.html b/docs/doc/reference/com/google/android/exoplayer2/audio/AudioSink.html index dc2f7c59f1d..049db6402da 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/audio/AudioSink.html +++ b/docs/doc/reference/com/google/android/exoplayer2/audio/AudioSink.html @@ -770,8 +770,8 @@

    setAudioAttributes

    void setAudioAttributes​(AudioAttributes audioAttributes)
    Sets attributes for audio playback. If the attributes have changed and if the sink is not configured for use with tunneling, then it is reset and the audio session id is cleared. -

    - If the sink is configured for use with tunneling then the audio attributes are ignored. The + +

    If the sink is configured for use with tunneling then the audio attributes are ignored. The sink is not reset and the audio session id is not cleared. The passed attributes will be used if the sink is later re-configured into non-tunneled mode.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/audio/BaseAudioProcessor.html b/docs/doc/reference/com/google/android/exoplayer2/audio/BaseAudioProcessor.html index faeb9f0f4a9..75c47e1b313 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/audio/BaseAudioProcessor.html +++ b/docs/doc/reference/com/google/android/exoplayer2/audio/BaseAudioProcessor.html @@ -465,11 +465,10 @@

    isActive

    queueEndOfStream

    public final void queueEndOfStream()
    Description copied from interface: AudioProcessor
    -
    Queues an end of stream signal. After this method has been called, - AudioProcessor.queueInput(ByteBuffer) may not be called until after the next call to - AudioProcessor.flush(). Calling AudioProcessor.getOutput() will return any remaining output data. Multiple - calls may be required to read all of the remaining output data. AudioProcessor.isEnded() will return - true once all remaining output data has been read.
    +
    Queues an end of stream signal. After this method has been called, AudioProcessor.queueInput(ByteBuffer) may not be called until after the next call to AudioProcessor.flush(). + Calling AudioProcessor.getOutput() will return any remaining output data. Multiple calls may be + required to read all of the remaining output data. AudioProcessor.isEnded() will return true + once all remaining output data has been read.
    Specified by:
    queueEndOfStream in interface AudioProcessor
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/audio/DecoderAudioRenderer.html b/docs/doc/reference/com/google/android/exoplayer2/audio/DecoderAudioRenderer.html index ec558706778..88fb36940ca 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/audio/DecoderAudioRenderer.html +++ b/docs/doc/reference/com/google/android/exoplayer2/audio/DecoderAudioRenderer.html @@ -446,7 +446,7 @@

    Method Summary

    Methods inherited from class com.google.android.exoplayer2.BaseRenderer

    -createRendererException, createRendererException, disable, enable, getCapabilities, getConfiguration, getFormatHolder, getIndex, getLastResetPositionUs, getReadingPositionUs, getState, getStream, getStreamFormats, getTrackType, hasReadStreamToEnd, isCurrentStreamFinal, isSourceReady, maybeThrowStreamError, onReset, onStreamChanged, readSource, replaceStream, reset, resetPosition, setCurrentStreamFinal, setIndex, skipSource, start, stop, supportsMixedMimeTypeAdaptation +createRendererException, createRendererException, disable, enable, getCapabilities, getConfiguration, getFormatHolder, getIndex, getLastResetPositionUs, getReadingPositionUs, getState, getStream, getStreamFormats, getTrackType, hasReadStreamToEnd, isCurrentStreamFinal, isSourceReady, maybeThrowStreamError, onReset, onStreamChanged, readSource, replaceStream, reset, resetPosition, setCurrentStreamFinal, setIndex, skipSource, start, stop, supportsMixedMimeTypeAdaptation
    • @@ -815,16 +815,15 @@

      isReady

      public boolean isReady()
      Whether the renderer is able to immediately render media from the current position. -

      - If the renderer is in the Renderer.STATE_STARTED state then returning true indicates that the - renderer has everything that it needs to continue playback. Returning false indicates that + +

      If the renderer is in the Renderer.STATE_STARTED state then returning true indicates that + the renderer has everything that it needs to continue playback. Returning false indicates that the player should pause until the renderer is ready. -

      - If the renderer is in the Renderer.STATE_ENABLED state then returning true indicates that the - renderer is ready for playback to be started. Returning false indicates that it is not. -

      - This method may be called when the renderer is in the following states: - Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

      + +

      If the renderer is in the Renderer.STATE_ENABLED state then returning true indicates that + the renderer is ready for playback to be started. Returning false indicates that it is not. + +

      This method may be called when the renderer is in the following states: Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

      Specified by:
      isReady in interface Renderer
      @@ -943,8 +942,8 @@

      onStarted

      protected void onStarted()
      Description copied from class: BaseRenderer
      Called when the renderer is started. -

      - The default implementation is a no-op.

      + +

      The default implementation is a no-op.

      Overrides:
      onStarted in class BaseRenderer
      @@ -977,8 +976,8 @@

      onDisabled

      protected void onDisabled()
      Description copied from class: BaseRenderer
      Called when the renderer is disabled. -

      - The default implementation is a no-op.

      + +

      The default implementation is a no-op.

      Overrides:
      onDisabled in class BaseRenderer
      diff --git a/docs/doc/reference/com/google/android/exoplayer2/audio/DefaultAudioSink.html b/docs/doc/reference/com/google/android/exoplayer2/audio/DefaultAudioSink.html index 438f495204c..536ea3dffe1 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/audio/DefaultAudioSink.html +++ b/docs/doc/reference/com/google/android/exoplayer2/audio/DefaultAudioSink.html @@ -270,13 +270,20 @@

      Field Summary

    + + + + + - + - +
    All Methods Instance Methods Concrete Methods All Methods Instance Methods Concrete Methods Deprecated Methods 
    Modifier and Type Method
    voidonAvailableCommandsChanged​(Player.Commands availableCommands) +
    Called when the value returned from Player.isCommandAvailable(int) changes for at least one + Player.Command.
    +
    void onBandwidthSample​(int elapsedMs, - long bytes, - long bitrate)
    Called periodically to indicate that bytes have been transferred or the estimated bitrate has changed.
    void onDownstreamFormatChanged​(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId, @@ -357,7 +365,7 @@

    Method Summary

    Called when a downstream format change occurs (i.e.
    void onDrmKeysLoaded​(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId)
    void onDrmKeysRemoved​(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId)
    void onDrmKeysRestored​(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId)
    void onDrmSessionAcquired​(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId, @@ -390,7 +398,7 @@

    Method Summary

    Called each time a drm session is acquired.
    void onDrmSessionManagerError​(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId, @@ -399,7 +407,7 @@

    Method Summary

    Called when a drm error occurs.
    void onDrmSessionReleased​(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId)
    void onDroppedFrames​(int count, long elapsedMs)
    void onIsLoadingChanged​(boolean isLoading)
    Called when the player starts or stops loading the source.
    void onIsPlayingChanged​(boolean isPlaying)
    Called when the value of Player.isPlaying() changes.
    void onLoadCanceled​(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId, @@ -439,7 +447,7 @@

    Method Summary

    Called when a load is canceled.
    void onLoadCompleted​(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId, @@ -449,7 +457,7 @@

    Method Summary

    Called when a load ends.
    void onLoadError​(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId, @@ -461,7 +469,7 @@

    Method Summary

    Called when a load error occurs.
    void onLoadStarted​(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId, @@ -471,7 +479,14 @@

    Method Summary

    Called when a load begins.
    voidonMaxSeekToPreviousPositionChanged​(int maxSeekToPreviousPositionMs) +
    Called when the value of Player.getMaxSeekToPreviousPosition() changes.
    +
    void onMediaItemTransition​(MediaItem mediaItem, int reason)
    void onMediaMetadataChanged​(MediaMetadata mediaMetadata)
    Called when the combined MediaMetadata changes.
    void onMetadata​(Metadata metadata)
    Called when there is metadata associated with current playback time.
    void onPlaybackParametersChanged​(PlaybackParameters playbackParameters)
    Called when the current playback parameters change.
    voidonPlaybackStateChanged​(int state)onPlaybackStateChanged​(int playbackState)
    Called when the value returned from Player.getPlaybackState() changes.
    void onPlaybackSuppressionReasonChanged​(int playbackSuppressionReason)
    Called when the value returned from Player.getPlaybackSuppressionReason() changes.
    voidonPlayerError​(ExoPlaybackException error)onPlayerError​(PlaybackException error)
    Called when an error occurs.
    void onPlayerStateChanged​(boolean playWhenReady, int playbackState)  
    voidonPlaylistMetadataChanged​(MediaMetadata playlistMetadata) +
    Called when the playlist MediaMetadata changes.
    +
    void onPlayWhenReadyChanged​(boolean playWhenReady, int reason)
    void onPositionDiscontinuity​(Player.PositionInfo oldPosition, Player.PositionInfo newPosition, @@ -545,7 +567,7 @@

    Method Summary

    Called when a position discontinuity occurs.
    void onRenderedFirstFrame​(Object output, long renderTimeMs)
    void onRepeatModeChanged​(int repeatMode)
    Called when the value of Player.getRepeatMode() changes.
    voidonSeekBackIncrementChanged​(long seekBackIncrementMs) +
    Called when the value of Player.getSeekBackIncrement() changes.
    +
    voidonSeekForwardIncrementChanged​(long seekForwardIncrementMs) +
    Called when the value of Player.getSeekForwardIncrement() changes.
    +
    void onSeekProcessed()  
    void onShuffleModeEnabledChanged​(boolean shuffleModeEnabled)
    Called when the value of Player.getShuffleModeEnabled() changes.
    void onSkipSilenceEnabledChanged​(boolean skipSilenceEnabled)
    Called when skipping silences is enabled or disabled in the audio stream.
    void onStaticMetadataChanged​(List<Metadata> metadataList) -
    Called when the static metadata changes.
    +
    Deprecated.
    void onSurfaceSizeChanged​(int width, int height)
    void onTimelineChanged​(Timeline timeline, int reason)
    void onTracksChanged​(TrackGroupArray trackGroups, TrackSelectionArray trackSelections)
    void onUpstreamDiscarded​(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId, @@ -622,14 +658,14 @@

    Method Summary

    re-buffered in a different format.
    void onVideoCodecError​(Exception videoCodecError)
    Called when a video decoder encounters an error.
    void onVideoDecoderInitialized​(String decoderName, long initializedTimestampMs, @@ -638,28 +674,28 @@

    Method Summary

    Called when a decoder is created.
    void onVideoDecoderReleased​(String decoderName)
    Called when a decoder is released.
    void onVideoDisabled​(DecoderCounters counters)
    Called when the renderer is disabled.
    void onVideoEnabled​(DecoderCounters counters)
    Called when the renderer is enabled.
    void onVideoFrameProcessingOffset​(long totalProcessingOffsetUs, int frameCount)
    void onVideoInputFormatChanged​(Format format, DecoderReuseEvaluation decoderReuseEvaluation)
    void onVideoSizeChanged​(VideoSize videoSize)
    Called each time there's a change in the size of the video being rendered.
    void onVolumeChanged​(float volume)
    Called when the volume changes.
    void release()
    Releases the collector.
    void removeListener​(AnalyticsListener listener)
    Removes a previously added analytics event listener.
    protected void sendEvent​(AnalyticsListener.EventTime eventTime, int eventFlag, @@ -712,7 +748,7 @@

    Method Summary

    Sends an event to registered listeners.
    void setPlayer​(Player player, Looper looper)
    void updateMediaPeriodQueueInfo​(List<MediaSource.MediaPeriodId> queue, MediaSource.MediaPeriodId readingPeriod) Description
    Events​(ExoFlags flags, +Events​(FlagSet flags, SparseArray<AnalyticsListener.EventTime> eventTimes)
    Creates an instance.
    @@ -239,18 +239,18 @@

    Methods inherited from class java.lang. +
    • Events

      -
      public Events​(ExoFlags flags,
      +
      public Events​(FlagSet flags,
                     SparseArray<AnalyticsListener.EventTime> eventTimes)
      Creates an instance.
      Parameters:
      -
      flags - The ExoFlags containing the AnalyticsListener.EventFlags in the set.
      +
      flags - The FlagSet containing the AnalyticsListener.EventFlags in the set.
      eventTimes - A map from AnalyticsListener.EventFlags to AnalyticsListener.EventTime. Must at least contain all the events recorded in flags. Events that are not recorded in flags are ignored.
      diff --git a/docs/doc/reference/com/google/android/exoplayer2/analytics/AnalyticsListener.html b/docs/doc/reference/com/google/android/exoplayer2/analytics/AnalyticsListener.html index e65257378b5..fd1cff47c81 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/analytics/AnalyticsListener.html +++ b/docs/doc/reference/com/google/android/exoplayer2/analytics/AnalyticsListener.html @@ -25,7 +25,7 @@ catch(err) { } //--> -var data = {"i0":18,"i1":18,"i2":50,"i3":18,"i4":18,"i5":18,"i6":18,"i7":50,"i8":18,"i9":18,"i10":18,"i11":18,"i12":18,"i13":18,"i14":50,"i15":50,"i16":50,"i17":50,"i18":18,"i19":18,"i20":18,"i21":18,"i22":50,"i23":18,"i24":18,"i25":18,"i26":18,"i27":18,"i28":18,"i29":18,"i30":18,"i31":18,"i32":18,"i33":50,"i34":18,"i35":18,"i36":18,"i37":18,"i38":18,"i39":18,"i40":18,"i41":18,"i42":18,"i43":50,"i44":18,"i45":50,"i46":18,"i47":18,"i48":18,"i49":50,"i50":50,"i51":18,"i52":18,"i53":18,"i54":18,"i55":18,"i56":18,"i57":18,"i58":18,"i59":50,"i60":18,"i61":18,"i62":18,"i63":18,"i64":18,"i65":50,"i66":18,"i67":50,"i68":18,"i69":18}; +var data = {"i0":18,"i1":18,"i2":50,"i3":18,"i4":18,"i5":18,"i6":18,"i7":50,"i8":18,"i9":18,"i10":18,"i11":18,"i12":18,"i13":18,"i14":18,"i15":50,"i16":50,"i17":50,"i18":50,"i19":18,"i20":18,"i21":18,"i22":18,"i23":50,"i24":18,"i25":18,"i26":18,"i27":18,"i28":18,"i29":18,"i30":18,"i31":18,"i32":18,"i33":18,"i34":50,"i35":18,"i36":18,"i37":18,"i38":18,"i39":18,"i40":18,"i41":18,"i42":18,"i43":18,"i44":18,"i45":50,"i46":18,"i47":18,"i48":50,"i49":18,"i50":18,"i51":18,"i52":18,"i53":18,"i54":50,"i55":50,"i56":18,"i57":18,"i58":50,"i59":18,"i60":18,"i61":18,"i62":18,"i63":18,"i64":50,"i65":18,"i66":18,"i67":18,"i68":18,"i69":18,"i70":50,"i71":18,"i72":50,"i73":18,"i74":18}; var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],16:["t5","Default Methods"],32:["t6","Deprecated Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -273,109 +273,123 @@

      Field Summary

    static intEVENT_AVAILABLE_COMMANDS_CHANGED + +
    static int EVENT_BANDWIDTH_ESTIMATE
    The bandwidth estimate has been updated.
    static int EVENT_DOWNSTREAM_FORMAT_CHANGED
    The downstream format sent to renderers changed.
    static int EVENT_DRM_KEYS_LOADED
    DRM keys were loaded.
    static int EVENT_DRM_KEYS_REMOVED
    DRM keys were removed.
    static int EVENT_DRM_KEYS_RESTORED
    DRM keys were restored.
    static int EVENT_DRM_SESSION_ACQUIRED
    A DRM session has been acquired.
    static int EVENT_DRM_SESSION_MANAGER_ERROR
    A non-fatal DRM session manager error occurred.
    static int EVENT_DRM_SESSION_RELEASED
    A DRM session has been released.
    static int EVENT_DROPPED_VIDEO_FRAMES
    Video frames have been dropped.
    static int EVENT_IS_LOADING_CHANGED
    Player.isLoading() ()} changed.
    static int EVENT_IS_PLAYING_CHANGED
    static int EVENT_LOAD_CANCELED
    A source canceled loading data.
    static int EVENT_LOAD_COMPLETED
    A source started completed loading data.
    static int EVENT_LOAD_ERROR
    A source had a non-fatal error loading data.
    static int EVENT_LOAD_STARTED
    A source started loading data.
    static intEVENT_MAX_SEEK_TO_PREVIOUS_POSITION_CHANGED + +
    static int EVENT_MEDIA_ITEM_TRANSITION
    static intEVENT_PLAYLIST_METADATA_CHANGED + +
    static int EVENT_POSITION_DISCONTINUITY
    A position discontinuity occurred.
    static int EVENT_RENDERED_FIRST_FRAME @@ -454,119 +475,135 @@

    Field Summary

    since the stream changed.
    static int EVENT_REPEAT_MODE_CHANGED
    static intEVENT_SEEK_BACK_INCREMENT_CHANGED + +
    static intEVENT_SEEK_FORWARD_INCREMENT_CHANGED + +
    static int EVENT_SHUFFLE_MODE_ENABLED_CHANGED
    static int EVENT_SKIP_SILENCE_ENABLED_CHANGED
    Skipping silences was enabled or disabled in the audio stream.
    static int EVENT_STATIC_METADATA_CHANGED - +
    static int EVENT_SURFACE_SIZE_CHANGED
    The surface size changed.
    static int EVENT_TIMELINE_CHANGED
    static int EVENT_TRACKS_CHANGED
    static int EVENT_UPSTREAM_DISCARDED
    Data was removed from the end of the media buffer.
    static int EVENT_VIDEO_CODEC_ERROR
    The video codec encountered an error.
    static int EVENT_VIDEO_DECODER_INITIALIZED
    A video renderer created a decoder.
    static int EVENT_VIDEO_DECODER_RELEASED
    A video renderer released a decoder.
    static int EVENT_VIDEO_DISABLED
    A video renderer was disabled.
    static int EVENT_VIDEO_ENABLED
    A video renderer was enabled.
    static int EVENT_VIDEO_FRAME_PROCESSING_OFFSET
    Video frame processing offset data has been reported.
    static int EVENT_VIDEO_INPUT_FORMAT_CHANGED
    The format consumed by a video renderer changed.
    static int EVENT_VIDEO_SIZE_CHANGED
    The video size changed.
    static int EVENT_VOLUME_CHANGED @@ -639,7 +676,7 @@

    Method Summary

    default void onAudioDisabled​(AnalyticsListener.EventTime eventTime, - DecoderCounters counters)
    Called when an audio renderer is disabled.
    default void onAudioEnabled​(AnalyticsListener.EventTime eventTime, - DecoderCounters counters)
    Called when an audio renderer is enabled.
    default voidonAvailableCommandsChanged​(AnalyticsListener.EventTime eventTime, + Player.Commands availableCommands) +
    Called when the player's available commands changed.
    +
    default void onBandwidthEstimate​(AnalyticsListener.EventTime eventTime, int totalLoadTimeMs, long totalBytesLoaded, @@ -716,7 +761,7 @@

    Method Summary

    Called when the bandwidth estimate for the current data source has been updated.
    default void onDecoderDisabled​(AnalyticsListener.EventTime eventTime, int trackType, @@ -727,7 +772,7 @@

    Method Summary

    default void onDecoderEnabled​(AnalyticsListener.EventTime eventTime, int trackType, @@ -738,7 +783,7 @@

    Method Summary

    default void onDecoderInitialized​(AnalyticsListener.EventTime eventTime, int trackType, @@ -751,7 +796,7 @@

    Method Summary

    default void onDecoderInputFormatChanged​(AnalyticsListener.EventTime eventTime, int trackType, @@ -763,7 +808,7 @@

    Method Summary

    default void onDownstreamFormatChanged​(AnalyticsListener.EventTime eventTime, MediaLoadData mediaLoadData)
    default void onDrmKeysLoaded​(AnalyticsListener.EventTime eventTime)
    Called each time drm keys are loaded.
    default void onDrmKeysRemoved​(AnalyticsListener.EventTime eventTime)
    Called each time offline drm keys are removed.
    default void onDrmKeysRestored​(AnalyticsListener.EventTime eventTime)
    Called each time offline drm keys are restored.
    default void onDrmSessionAcquired​(AnalyticsListener.EventTime eventTime) @@ -801,7 +846,7 @@

    Method Summary

    default void onDrmSessionAcquired​(AnalyticsListener.EventTime eventTime, int state)
    default void onDrmSessionManagerError​(AnalyticsListener.EventTime eventTime, Exception error)
    default void onDrmSessionReleased​(AnalyticsListener.EventTime eventTime)
    Called each time a drm session is released.
    default void onDroppedVideoFrames​(AnalyticsListener.EventTime eventTime, int droppedFrames, @@ -833,7 +878,7 @@

    Method Summary

    Called after video frames have been dropped.
    default void onEvents​(Player player, AnalyticsListener.Events events)
    default void onIsLoadingChanged​(AnalyticsListener.EventTime eventTime, boolean isLoading)
    default void onIsPlayingChanged​(AnalyticsListener.EventTime eventTime, boolean isPlaying)
    default void onLoadCanceled​(AnalyticsListener.EventTime eventTime, LoadEventInfo loadEventInfo, @@ -866,7 +911,7 @@

    Method Summary

    Called when a media source canceled loading data.
    default void onLoadCompleted​(AnalyticsListener.EventTime eventTime, LoadEventInfo loadEventInfo, @@ -875,7 +920,7 @@

    Method Summary

    Called when a media source completed loading data.
    default void onLoadError​(AnalyticsListener.EventTime eventTime, LoadEventInfo loadEventInfo, @@ -886,7 +931,7 @@

    Method Summary

    Called when a media source loading error occurred.
    default void onLoadingChanged​(AnalyticsListener.EventTime eventTime, boolean isLoading)
    default void onLoadStarted​(AnalyticsListener.EventTime eventTime, LoadEventInfo loadEventInfo, @@ -905,7 +950,16 @@

    Method Summary

    Called when a media source started loading data.
    default voidonMaxSeekToPreviousPositionChanged​(AnalyticsListener.EventTime eventTime, + int maxSeekToPreviousPositionMs) +
    Called when the maximum position for which Player.seekToPrevious() seeks to the + previous window changes.
    +
    default void onMediaItemTransition​(AnalyticsListener.EventTime eventTime, MediaItem mediaItem, @@ -914,7 +968,7 @@

    Method Summary

    Called when playback transitions to a different media item.
    default void onMediaMetadataChanged​(AnalyticsListener.EventTime eventTime, MediaMetadata mediaMetadata)
    default void onMetadata​(AnalyticsListener.EventTime eventTime, Metadata metadata)
    default void onPlaybackParametersChanged​(AnalyticsListener.EventTime eventTime, PlaybackParameters playbackParameters)
    default void onPlaybackStateChanged​(AnalyticsListener.EventTime eventTime, int state)
    default void onPlaybackSuppressionReasonChanged​(AnalyticsListener.EventTime eventTime, int playbackSuppressionReason)
    default voidonPlayerError​(AnalyticsListener.EventTime eventTime, - ExoPlaybackException error)onPlayerError​(AnalyticsListener.EventTime eventTime, + PlaybackException error)
    Called when a fatal player error occurred.
    default void onPlayerReleased​(AnalyticsListener.EventTime eventTime)
    Called when the Player is released.
    default void onPlayerStateChanged​(AnalyticsListener.EventTime eventTime, boolean playWhenReady, @@ -980,7 +1034,15 @@

    Method Summary

    default voidonPlaylistMetadataChanged​(AnalyticsListener.EventTime eventTime, + MediaMetadata playlistMetadata) +
    Called when the playlist MediaMetadata changes.
    +
    default void onPlayWhenReadyChanged​(AnalyticsListener.EventTime eventTime, boolean playWhenReady, @@ -989,7 +1051,7 @@

    Method Summary

    Called when the value changed that indicates whether playback will proceed when ready.
    default void onPositionDiscontinuity​(AnalyticsListener.EventTime eventTime, int reason)
    default void onPositionDiscontinuity​(AnalyticsListener.EventTime eventTime, Player.PositionInfo oldPosition, @@ -1010,7 +1072,7 @@

    Method Summary

    Called when a position discontinuity occurred.
    default void onRenderedFirstFrame​(AnalyticsListener.EventTime eventTime, Object output, @@ -1020,7 +1082,7 @@

    Method Summary

    renderer was reset, or since the stream being rendered was changed.
    default void onRepeatModeChanged​(AnalyticsListener.EventTime eventTime, int repeatMode)
    default voidonSeekBackIncrementChanged​(AnalyticsListener.EventTime eventTime, + long seekBackIncrementMs) +
    Called when the seek back increment changed.
    +
    default voidonSeekForwardIncrementChanged​(AnalyticsListener.EventTime eventTime, + long seekForwardIncrementMs) +
    Called when the seek forward increment changed.
    +
    default void onSeekProcessed​(AnalyticsListener.EventTime eventTime) @@ -1037,7 +1115,7 @@

    Method Summary

    default void onSeekStarted​(AnalyticsListener.EventTime eventTime) @@ -1047,7 +1125,7 @@

    Method Summary

    default void onShuffleModeChanged​(AnalyticsListener.EventTime eventTime, boolean shuffleModeEnabled)
    default void onSkipSilenceEnabledChanged​(AnalyticsListener.EventTime eventTime, boolean skipSilenceEnabled)
    default void onStaticMetadataChanged​(AnalyticsListener.EventTime eventTime, List<Metadata> metadataList) -
    Called when the static metadata changes.
    +
    Deprecated. +
    Use Player.getMediaMetadata() and onMediaMetadataChanged(EventTime, + MediaMetadata) for access to structured metadata, or access the raw static metadata + directly from the track selections' formats.
    +
    default void onSurfaceSizeChanged​(AnalyticsListener.EventTime eventTime, int width, @@ -1080,7 +1162,7 @@

    Method Summary

    Called when the output surface size changed.
    default void onTimelineChanged​(AnalyticsListener.EventTime eventTime, int reason)
    default void onTracksChanged​(AnalyticsListener.EventTime eventTime, TrackGroupArray trackGroups, @@ -1097,7 +1179,7 @@

    Method Summary

    Called when the available or selected tracks for the renderers changed.
    default void onUpstreamDiscarded​(AnalyticsListener.EventTime eventTime, MediaLoadData mediaLoadData)
    default void onVideoCodecError​(AnalyticsListener.EventTime eventTime, Exception videoCodecError)
    default void onVideoDecoderInitialized​(AnalyticsListener.EventTime eventTime, String decoderName, @@ -1125,7 +1207,7 @@

    Method Summary

    default void onVideoDecoderInitialized​(AnalyticsListener.EventTime eventTime, String decoderName, @@ -1135,7 +1217,7 @@

    Method Summary

    Called when a video renderer creates a decoder.
    default void onVideoDecoderReleased​(AnalyticsListener.EventTime eventTime, String decoderName)
    default void onVideoDisabled​(AnalyticsListener.EventTime eventTime, - DecoderCounters counters)
    Called when a video renderer is disabled.
    default void onVideoEnabled​(AnalyticsListener.EventTime eventTime, - DecoderCounters counters)
    Called when a video renderer is enabled.
    default void onVideoFrameProcessingOffset​(AnalyticsListener.EventTime eventTime, long totalProcessingOffsetUs, @@ -1169,7 +1251,7 @@

    Method Summary

    renderer.
    default void onVideoInputFormatChanged​(AnalyticsListener.EventTime eventTime, Format format)
    default void onVideoInputFormatChanged​(AnalyticsListener.EventTime eventTime, Format format, @@ -1188,7 +1270,7 @@

    Method Summary

    Called when the format of the media being consumed by a video renderer changes.
    default void onVideoSizeChanged​(AnalyticsListener.EventTime eventTime, int width, @@ -1201,7 +1283,7 @@

    Method Summary

    default void onVideoSizeChanged​(AnalyticsListener.EventTime eventTime, VideoSize videoSize)
    default void onVolumeChanged​(AnalyticsListener.EventTime eventTime, float volume)
    void onAdPlaybackStarted​(AnalyticsListener.EventTime eventTime, - String contentSession, - String adSession)
    Called when a session is interrupted by ad playback.
    void onPositionDiscontinuity​(AnalyticsListener.EventTime eventTime, - Player.PositionInfo oldPositionInfo, - Player.PositionInfo newPositionInfo, + Player.PositionInfo oldPosition, + Player.PositionInfo newPosition, int reason)
    Called when a position discontinuity occurred.
    @@ -328,7 +328,7 @@

    Method Summary

    void onSessionActive​(AnalyticsListener.EventTime eventTime, - String session)
    Called when a session becomes active, i.e.
    void onSessionCreated​(AnalyticsListener.EventTime eventTime, - String session)
    Called when a new session is created as a result of PlaybackSessionManager.updateSessions(EventTime).
    void onSessionFinished​(AnalyticsListener.EventTime eventTime, - String session, - boolean automaticTransition)
    Called when a session is permanently finished.
    static StringE_AC_3_CODEC_STRINGE_AC3_JOC_CODEC_STRING -
    A non-standard codec string for E-AC-3.
    +
    A non-standard codec string for E-AC3-JOC.
    voidqueueInput​(ByteBuffer buffer)queueInput​(ByteBuffer inputBuffer)
    Queues audio data between the position and limit of the input buffer for processing.
    static intOFFLOAD_MODE_ENABLED_GAPLESS_DISABLED +
    The audio sink will prefer offload playback, disabling gapless offload support.
    +
    static int OFFLOAD_MODE_ENABLED_GAPLESS_NOT_REQUIRED
    The audio sink will prefer offload playback even if this might result in silence gaps between tracks.
    static int OFFLOAD_MODE_ENABLED_GAPLESS_REQUIRED @@ -676,6 +683,23 @@

    OFFLOAD_MODE_ENABLED_GAPLESS_NOT_REQUIRED

    + + + +
      +
    • +

      OFFLOAD_MODE_ENABLED_GAPLESS_DISABLED

      +
      public static final int OFFLOAD_MODE_ENABLED_GAPLESS_DISABLED
      +
      The audio sink will prefer offload playback, disabling gapless offload support. + +

      Use this option if gapless has undesirable side effects. For example if it introduces + hardware issues.

      +
      +
      See Also:
      +
      Constant Field Values
      +
      +
    • +
    @@ -685,8 +709,8 @@

    failOnSpuriousAudioTimestamp

    public static boolean failOnSpuriousAudioTimestamp
    Whether to throw an DefaultAudioSink.InvalidAudioTrackTimestampException when a spurious timestamp is reported from AudioTrack.getTimestamp(android.media.AudioTimestamp). -

    - The flag must be set before creating a player. Should be set to true for testing and + +

    The flag must be set before creating a player. Should be set to true for testing and debugging purposes only.

    @@ -1082,8 +1106,8 @@

    setAudioAttributes

    Description copied from interface: AudioSink
    Sets attributes for audio playback. If the attributes have changed and if the sink is not configured for use with tunneling, then it is reset and the audio session id is cleared. -

    - If the sink is configured for use with tunneling then the audio attributes are ignored. The + +

    If the sink is configured for use with tunneling then the audio attributes are ignored. The sink is not reset and the audio session id is not cleared. The passed attributes will be used if the sink is later re-configured into non-tunneled mode.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/audio/ForwardingAudioSink.html b/docs/doc/reference/com/google/android/exoplayer2/audio/ForwardingAudioSink.html index ad81dc23be3..b4e9d3044af 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/audio/ForwardingAudioSink.html +++ b/docs/doc/reference/com/google/android/exoplayer2/audio/ForwardingAudioSink.html @@ -733,8 +733,8 @@

    setAudioAttributes

    Description copied from interface: AudioSink
    Sets attributes for audio playback. If the attributes have changed and if the sink is not configured for use with tunneling, then it is reset and the audio session id is cleared. -

    - If the sink is configured for use with tunneling then the audio attributes are ignored. The + +

    If the sink is configured for use with tunneling then the audio attributes are ignored. The sink is not reset and the audio session id is not cleared. The passed attributes will be used if the sink is later re-configured into non-tunneled mode.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.html b/docs/doc/reference/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.html index 487dba630d3..e05758282cf 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.html +++ b/docs/doc/reference/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.html @@ -589,14 +589,14 @@

    Method Summary

    Methods inherited from class com.google.android.exoplayer2.mediacodec.MediaCodecRenderer

    -createDecoderException, experimentalSetAsynchronousBufferQueueingEnabled, experimentalSetForceAsyncQueueingSynchronizationWorkaround, experimentalSetSkipAndContinueIfSampleTooLarge, experimentalSetSynchronizeCodecInteractionsWithQueueingEnabled, flushOrReinitializeCodec, flushOrReleaseCodec, getCodec, getCodecInfo, getCodecNeedsEosPropagation, getCodecOperatingRate, getCodecOutputMediaFormat, getOutputStreamOffsetUs, getPlaybackSpeed, handleInputBufferSupplementalData, legacyKeepAvailableCodecInfosWithoutCodec, maybeInitCodecOrBypass, onProcessedOutputBuffer, onStreamChanged, releaseCodec, render, resetCodecStateForFlush, resetCodecStateForRelease, setPendingOutputEndOfStream, setPendingPlaybackException, setPlaybackSpeed, setRenderTimeLimitMs, shouldInitCodec, supportsFormat, supportsFormatDrm, supportsMixedMimeTypeAdaptation, updateCodecOperatingRate, updateOutputFormatForTime +createDecoderException, experimentalSetAsynchronousBufferQueueingEnabled, experimentalSetForceAsyncQueueingSynchronizationWorkaround, experimentalSetSynchronizeCodecInteractionsWithQueueingEnabled, flushOrReinitializeCodec, flushOrReleaseCodec, getCodec, getCodecInfo, getCodecNeedsEosPropagation, getCodecOperatingRate, getCodecOutputMediaFormat, getOutputStreamOffsetUs, getPlaybackSpeed, handleInputBufferSupplementalData, maybeInitCodecOrBypass, onProcessedOutputBuffer, onStreamChanged, releaseCodec, render, resetCodecStateForFlush, resetCodecStateForRelease, setPendingOutputEndOfStream, setPendingPlaybackException, setPlaybackSpeed, setRenderTimeLimitMs, shouldInitCodec, supportsFormat, supportsFormatDrm, supportsMixedMimeTypeAdaptation, updateCodecOperatingRate, updateOutputFormatForTime
    • @@ -1006,8 +1006,8 @@

      onCodecInitialized

      long initializationDurationMs)
      Called when a MediaCodec has been created and configured. -

      - The default implementation is a no-op.

      + +

      The default implementation is a no-op.

      Overrides:
      onCodecInitialized in class MediaCodecRenderer
      @@ -1181,8 +1181,8 @@

      onStarted

      protected void onStarted()
      Description copied from class: BaseRenderer
      Called when the renderer is started. -

      - The default implementation is a no-op.

      + +

      The default implementation is a no-op.

      Overrides:
      onStarted in class MediaCodecRenderer
      @@ -1215,8 +1215,8 @@

      onDisabled

      protected void onDisabled()
      Description copied from class: BaseRenderer
      Called when the renderer is disabled. -

      - The default implementation is a no-op.

      + +

      The default implementation is a no-op.

      Overrides:
      onDisabled in class MediaCodecRenderer
      @@ -1271,16 +1271,15 @@

      isReady

      public boolean isReady()
      Description copied from interface: Renderer
      Whether the renderer is able to immediately render media from the current position. -

      - If the renderer is in the Renderer.STATE_STARTED state then returning true indicates that the - renderer has everything that it needs to continue playback. Returning false indicates that + +

      If the renderer is in the Renderer.STATE_STARTED state then returning true indicates that + the renderer has everything that it needs to continue playback. Returning false indicates that the player should pause until the renderer is ready. -

      - If the renderer is in the Renderer.STATE_ENABLED state then returning true indicates that the - renderer is ready for playback to be started. Returning false indicates that it is not. -

      - This method may be called when the renderer is in the following states: - Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

      + +

      If the renderer is in the Renderer.STATE_ENABLED state then returning true indicates that + the renderer is ready for playback to be started. Returning false indicates that it is not. + +

      This method may be called when the renderer is in the following states: Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

      Specified by:
      isReady in interface Renderer
      @@ -1446,8 +1445,8 @@

      renderToEndOfStream

      throws ExoPlaybackException
      Description copied from class: MediaCodecRenderer
      Incrementally renders any remaining output. -

      - The default implementation is a no-op.

      + +

      The default implementation is a no-op.

      Overrides:
      renderToEndOfStream in class MediaCodecRenderer
      diff --git a/docs/doc/reference/com/google/android/exoplayer2/audio/SonicAudioProcessor.html b/docs/doc/reference/com/google/android/exoplayer2/audio/SonicAudioProcessor.html index 37b7e02f22c..7e20e13ce77 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/audio/SonicAudioProcessor.html +++ b/docs/doc/reference/com/google/android/exoplayer2/audio/SonicAudioProcessor.html @@ -526,11 +526,10 @@

      queueInput

      queueEndOfStream

      public void queueEndOfStream()
      Description copied from interface: AudioProcessor
      -
      Queues an end of stream signal. After this method has been called, - AudioProcessor.queueInput(ByteBuffer) may not be called until after the next call to - AudioProcessor.flush(). Calling AudioProcessor.getOutput() will return any remaining output data. Multiple - calls may be required to read all of the remaining output data. AudioProcessor.isEnded() will return - true once all remaining output data has been read.
      +
      Queues an end of stream signal. After this method has been called, AudioProcessor.queueInput(ByteBuffer) may not be called until after the next call to AudioProcessor.flush(). + Calling AudioProcessor.getOutput() will return any remaining output data. Multiple calls may be + required to read all of the remaining output data. AudioProcessor.isEnded() will return true + once all remaining output data has been read.
      Specified by:
      queueEndOfStream in interface AudioProcessor
      diff --git a/docs/doc/reference/com/google/android/exoplayer2/decoder/Buffer.html b/docs/doc/reference/com/google/android/exoplayer2/decoder/Buffer.html index 224d35cc9b3..0c467e7bf2e 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/decoder/Buffer.html +++ b/docs/doc/reference/com/google/android/exoplayer2/decoder/Buffer.html @@ -360,8 +360,8 @@

      addFlag

      Adds the flag to this buffer's flags.
      Parameters:
      -
      flag - The flag to add to this buffer's flags, which should be one of the - C.BUFFER_FLAG_* constants.
      +
      flag - The flag to add to this buffer's flags, which should be one of the + C.BUFFER_FLAG_* constants.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/decoder/DecoderCounters.html b/docs/doc/reference/com/google/android/exoplayer2/decoder/DecoderCounters.html index f5f09e949be..5141097f137 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/decoder/DecoderCounters.html +++ b/docs/doc/reference/com/google/android/exoplayer2/decoder/DecoderCounters.html @@ -356,8 +356,8 @@

    inputBufferCount

    skippedInputBufferCount

    public int skippedInputBufferCount
    The number of skipped input buffers. -

    - A skipped input buffer is an input buffer that was deliberately not sent to the decoder.

    + +

    A skipped input buffer is an input buffer that was deliberately not sent to the decoder. @@ -378,8 +378,8 @@

    renderedOutputBufferCount

    skippedOutputBufferCount

    public int skippedOutputBufferCount
    The number of skipped output buffers. -

    - A skipped output buffer is an output buffer that was deliberately not rendered.

    + +

    A skipped output buffer is an output buffer that was deliberately not rendered. @@ -390,8 +390,8 @@

    skippedOutputBufferCount

    droppedBufferCount

    public int droppedBufferCount
    The number of dropped buffers. -

    - A dropped buffer is an buffer that was supposed to be decoded/rendered, but was instead + +

    A dropped buffer is an buffer that was supposed to be decoded/rendered, but was instead dropped because it could not be rendered in time.

    @@ -403,8 +403,8 @@

    droppedBufferCount

    maxConsecutiveDroppedBufferCount

    public int maxConsecutiveDroppedBufferCount
    The maximum number of dropped buffers without an interleaving rendered output buffer. -

    - Skipped output buffers are ignored for the purposes of calculating this value.

    + +

    Skipped output buffers are ignored for the purposes of calculating this value. @@ -415,10 +415,10 @@

    maxConsecutiveDroppedBufferCount

    droppedToKeyframeCount

    public int droppedToKeyframeCount
    The number of times all buffers to a keyframe were dropped. -

    - Each time buffers to a keyframe are dropped, this counter is increased by one, and the dropped - buffer counters are increased by one (for the current output buffer) plus the number of buffers - dropped from the source to advance to the keyframe.

    + +

    Each time buffers to a keyframe are dropped, this counter is increased by one, and the + dropped buffer counters are increased by one (for the current output buffer) plus the number of + buffers dropped from the source to advance to the keyframe. diff --git a/docs/doc/reference/com/google/android/exoplayer2/decoder/SimpleDecoder.html b/docs/doc/reference/com/google/android/exoplayer2/decoder/SimpleDecoder.html index 007f2922a04..24264174223 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/decoder/SimpleDecoder.html +++ b/docs/doc/reference/com/google/android/exoplayer2/decoder/SimpleDecoder.html @@ -331,8 +331,8 @@

    Method Detail

    setInitialInputBufferSize

    protected final void setInitialInputBufferSize​(int size)
    Parameters:
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/drm/DrmSession.DrmSessionException.html b/docs/doc/reference/com/google/android/exoplayer2/drm/DrmSession.DrmSessionException.html index b096b30cd14..5378524f584 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/drm/DrmSession.DrmSessionException.html +++ b/docs/doc/reference/com/google/android/exoplayer2/drm/DrmSession.DrmSessionException.html @@ -81,13 +81,13 @@ @@ -159,6 +159,31 @@

    Class DrmSession.
    • + +
      + +
        @@ -173,7 +198,8 @@

        Constructor Summary

    Description
    DrmSessionException​(Throwable cause)DrmSessionException​(Throwable cause, + int errorCode)  
    @@ -210,6 +236,27 @@

    Methods inherited from class java.lang. @@ -193,7 +193,7 @@

    Fields inherited from class com.google.android.exoplayer2.Player

    -COMMAND_ADJUST_DEVICE_VOLUME, COMMAND_CHANGE_MEDIA_ITEMS, COMMAND_GET_AUDIO_ATTRIBUTES, COMMAND_GET_CURRENT_MEDIA_ITEM, COMMAND_GET_DEVICE_VOLUME, COMMAND_GET_MEDIA_ITEMS, COMMAND_GET_MEDIA_ITEMS_METADATA, COMMAND_GET_TEXT, COMMAND_GET_VOLUME, COMMAND_PLAY_PAUSE, COMMAND_PREPARE_STOP, COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, COMMAND_SEEK_TO_DEFAULT_POSITION, COMMAND_SEEK_TO_MEDIA_ITEM, COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM, COMMAND_SET_DEVICE_VOLUME, COMMAND_SET_REPEAT_MODE, COMMAND_SET_SHUFFLE_MODE, COMMAND_SET_SPEED_AND_PITCH, COMMAND_SET_VIDEO_SURFACE, COMMAND_SET_VOLUME, DISCONTINUITY_REASON_AUTO_TRANSITION, DISCONTINUITY_REASON_INTERNAL, DISCONTINUITY_REASON_REMOVE, DISCONTINUITY_REASON_SEEK, DISCONTINUITY_REASON_SEEK_ADJUSTMENT, DISCONTINUITY_REASON_SKIP, EVENT_AVAILABLE_COMMANDS_CHANGED, EVENT_IS_LOADING_CHANGED, EVENT_IS_PLAYING_CHANGED, EVENT_MEDIA_ITEM_TRANSITION, EVENT_MEDIA_METADATA_CHANGED, EVENT_PLAY_WHEN_READY_CHANGED, EVENT_PLAYBACK_PARAMETERS_CHANGED, EVENT_PLAYBACK_STATE_CHANGED, EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED, EVENT_PLAYER_ERROR, EVENT_POSITION_DISCONTINUITY, EVENT_REPEAT_MODE_CHANGED, EVENT_SHUFFLE_MODE_ENABLED_CHANGED, EVENT_STATIC_METADATA_CHANGED, EVENT_TIMELINE_CHANGED, EVENT_TRACKS_CHANGED, MEDIA_ITEM_TRANSITION_REASON_AUTO, MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED, MEDIA_ITEM_TRANSITION_REASON_REPEAT, MEDIA_ITEM_TRANSITION_REASON_SEEK, PLAY_WHEN_READY_CHANGE_REASON_AUDIO_BECOMING_NOISY, PLAY_WHEN_READY_CHANGE_REASON_AUDIO_FOCUS_LOSS, PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM, PLAY_WHEN_READY_CHANGE_REASON_REMOTE, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST, PLAYBACK_SUPPRESSION_REASON_NONE, PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS, REPEAT_MODE_ALL, REPEAT_MODE_OFF, REPEAT_MODE_ONE, STATE_BUFFERING, STATE_ENDED, STATE_IDLE, STATE_READY, TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED, TIMELINE_CHANGE_REASON_SOURCE_UPDATE +COMMAND_ADJUST_DEVICE_VOLUME, COMMAND_CHANGE_MEDIA_ITEMS, COMMAND_GET_AUDIO_ATTRIBUTES, COMMAND_GET_CURRENT_MEDIA_ITEM, COMMAND_GET_DEVICE_VOLUME, COMMAND_GET_MEDIA_ITEMS_METADATA, COMMAND_GET_TEXT, COMMAND_GET_TIMELINE, COMMAND_GET_VOLUME, COMMAND_INVALID, COMMAND_PLAY_PAUSE, COMMAND_PREPARE_STOP, COMMAND_SEEK_BACK, COMMAND_SEEK_FORWARD, COMMAND_SEEK_IN_CURRENT_WINDOW, COMMAND_SEEK_TO_DEFAULT_POSITION, COMMAND_SEEK_TO_NEXT, COMMAND_SEEK_TO_NEXT_WINDOW, COMMAND_SEEK_TO_PREVIOUS, COMMAND_SEEK_TO_PREVIOUS_WINDOW, COMMAND_SEEK_TO_WINDOW, COMMAND_SET_DEVICE_VOLUME, COMMAND_SET_MEDIA_ITEMS_METADATA, COMMAND_SET_REPEAT_MODE, COMMAND_SET_SHUFFLE_MODE, COMMAND_SET_SPEED_AND_PITCH, COMMAND_SET_VIDEO_SURFACE, COMMAND_SET_VOLUME, DISCONTINUITY_REASON_AUTO_TRANSITION, DISCONTINUITY_REASON_INTERNAL, DISCONTINUITY_REASON_REMOVE, DISCONTINUITY_REASON_SEEK, DISCONTINUITY_REASON_SEEK_ADJUSTMENT, DISCONTINUITY_REASON_SKIP, EVENT_AVAILABLE_COMMANDS_CHANGED, EVENT_IS_LOADING_CHANGED, EVENT_IS_PLAYING_CHANGED, EVENT_MAX_SEEK_TO_PREVIOUS_POSITION_CHANGED, EVENT_MEDIA_ITEM_TRANSITION, EVENT_MEDIA_METADATA_CHANGED, EVENT_PLAY_WHEN_READY_CHANGED, EVENT_PLAYBACK_PARAMETERS_CHANGED, EVENT_PLAYBACK_STATE_CHANGED, EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED, EVENT_PLAYER_ERROR, EVENT_PLAYLIST_METADATA_CHANGED, EVENT_POSITION_DISCONTINUITY, EVENT_REPEAT_MODE_CHANGED, EVENT_SEEK_BACK_INCREMENT_CHANGED, EVENT_SEEK_FORWARD_INCREMENT_CHANGED, EVENT_SHUFFLE_MODE_ENABLED_CHANGED, EVENT_STATIC_METADATA_CHANGED, EVENT_TIMELINE_CHANGED, EVENT_TRACKS_CHANGED, MEDIA_ITEM_TRANSITION_REASON_AUTO, MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED, MEDIA_ITEM_TRANSITION_REASON_REPEAT, MEDIA_ITEM_TRANSITION_REASON_SEEK, PLAY_WHEN_READY_CHANGE_REASON_AUDIO_BECOMING_NOISY, PLAY_WHEN_READY_CHANGE_REASON_AUDIO_FOCUS_LOSS, PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM, PLAY_WHEN_READY_CHANGE_REASON_REMOTE, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST, PLAYBACK_SUPPRESSION_REASON_NONE, PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS, REPEAT_MODE_ALL, REPEAT_MODE_OFF, REPEAT_MODE_ONE, STATE_BUFFERING, STATE_ENDED, STATE_IDLE, STATE_READY, TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED, TIMELINE_CHANGE_REASON_SOURCE_UPDATE @@ -214,7 +214,7 @@

    Constructor Summary

    CastPlayer​(com.google.android.gms.cast.framework.CastContext castContext) -
    Creates a new cast player that uses a DefaultMediaItemConverter.
    +
    Creates a new cast player.
    @@ -224,6 +224,15 @@

    Constructor Summary

    Creates a new cast player.
    + +CastPlayer​(com.google.android.gms.cast.framework.CastContext castContext, + MediaItemConverter mediaItemConverter, + long seekBackIncrementMs, + long seekForwardIncrementMs) + +
    Creates a new cast player.
    + + @@ -243,39 +252,20 @@

    Method Summary

    Description -com.google.android.gms.common.api.PendingResult<com.google.android.gms.cast.framework.media.RemoteMediaClient.MediaChannelResult> -addItems​(int periodId, - com.google.android.gms.cast.MediaQueueItem... items) - -
    Deprecated. - -
    - - - -com.google.android.gms.common.api.PendingResult<com.google.android.gms.cast.framework.media.RemoteMediaClient.MediaChannelResult> -addItems​(com.google.android.gms.cast.MediaQueueItem... items) - -
    Deprecated. - -
    - - - void addListener​(Player.EventListener listener)
    Registers a listener to receive events from the player.
    - + void addListener​(Player.Listener listener)
    Registers a listener to receive all events from the player.
    - + void addMediaItems​(int index, List<MediaItem> mediaItems) @@ -283,49 +273,49 @@

    Method Summary

    Adds a list of media items at the given index of the playlist.
    - + void clearVideoSurface()
    This method is not supported and does nothing.
    - + void clearVideoSurface​(Surface surface)
    This method is not supported and does nothing.
    - + void clearVideoSurfaceHolder​(SurfaceHolder surfaceHolder)
    This method is not supported and does nothing.
    - + void clearVideoSurfaceView​(SurfaceView surfaceView)
    This method is not supported and does nothing.
    - + void clearVideoTextureView​(TextureView textureView)
    This method is not supported and does nothing.
    - + void decreaseDeviceVolume()
    This method is not supported and does nothing.
    - + Looper getApplicationLooper() @@ -333,21 +323,21 @@

    Method Summary

    player and on which player events are received. - + AudioAttributes getAudioAttributes()
    This method is not supported and returns AudioAttributes.DEFAULT.
    - + Player.Commands getAvailableCommands()
    Returns the player's currently available Player.Commands.
    - + long getBufferedPosition() @@ -355,7 +345,7 @@

    Method Summary

    buffered, in milliseconds. - + long getContentBufferedPosition() @@ -363,7 +353,7 @@

    Method Summary

    the current content window up to which data is buffered, in milliseconds. - + long getContentPosition() @@ -371,7 +361,7 @@

    Method Summary

    played once all ads in the ad group have finished playing, in milliseconds. - + int getCurrentAdGroupIndex() @@ -379,28 +369,28 @@

    Method Summary

    currently being played. - + int getCurrentAdIndexInAdGroup()
    If Player.isPlayingAd() returns true, returns the index of the ad in its ad group.
    - + ImmutableList<Cue> getCurrentCues()
    This method is not supported and returns an empty list.
    - + int getCurrentPeriodIndex()
    Returns the index of the period currently being played.
    - + long getCurrentPosition() @@ -409,63 +399,63 @@

    Method Summary

    empty. - + ImmutableList<Metadata> getCurrentStaticMetadata() -
    Returns the current static metadata for the track selections.
    +
    Deprecated.
    - + Timeline getCurrentTimeline()
    Returns the current Timeline.
    - + TrackGroupArray getCurrentTrackGroups()
    Returns the available track groups.
    - + TrackSelectionArray getCurrentTrackSelections()
    Returns the current track selections.
    - + int getCurrentWindowIndex()
    Returns the index of the current window in the timeline, or the prospective window index if the current timeline is empty.
    - + DeviceInfo getDeviceInfo()
    This method is not supported and always returns DeviceInfo.UNKNOWN.
    - + int getDeviceVolume()
    This method is not supported and always returns 0.
    - + long getDuration()
    Returns the duration of the current content window or ad in milliseconds, or C.TIME_UNSET if the duration is not known.
    - + com.google.android.gms.cast.MediaQueueItem getItem​(int periodId) @@ -473,7 +463,15 @@

    Method Summary

    period with id periodId exist. - + +int +getMaxSeekToPreviousPosition() + +
    Returns the maximum position for which Player.seekToPrevious() seeks to the previous window, + in milliseconds.
    + + + MediaMetadata getMediaMetadata() @@ -481,21 +479,21 @@

    Method Summary

    supported. - + PlaybackParameters getPlaybackParameters()
    Returns the currently active playback parameters.
    - + int getPlaybackState()
    Returns the current playback state of the player.
    - + int getPlaybackSuppressionReason() @@ -503,13 +501,20 @@

    Method Summary

    true
    , or Player.PLAYBACK_SUPPRESSION_REASON_NONE if playback is not suppressed. - -ExoPlaybackException + +PlaybackException getPlayerError()
    Returns the error that caused playback to fail.
    + +MediaMetadata +getPlaylistMetadata() + +
    Returns the playlist MediaMetadata, as set by Player.setPlaylistMetadata(MediaMetadata), or MediaMetadata.EMPTY if not supported.
    + + boolean getPlayWhenReady() @@ -525,102 +530,83 @@

    Method Summary

    +long +getSeekBackIncrement() + +
    Returns the Player.seekBack() increment.
    + + + +long +getSeekForwardIncrement() + +
    Returns the Player.seekForward() increment.
    + + + boolean getShuffleModeEnabled()
    Returns whether shuffling of windows is enabled.
    - + long getTotalBufferedDuration()
    Returns an estimate of the total buffered duration from the current position, in milliseconds.
    - + VideoSize getVideoSize()
    This method is not supported and returns VideoSize.UNKNOWN.
    - + float getVolume()
    This method is not supported and returns 1.
    - + void increaseDeviceVolume()
    This method is not supported and does nothing.
    - + boolean isCastSessionAvailable()
    Returns whether a cast session is available.
    - + boolean isDeviceMuted()
    This method is not supported and always returns false.
    - + boolean isLoading()
    Whether the player is currently loading the source.
    - + boolean isPlayingAd()
    Returns whether the player is currently playing an ad.
    - -com.google.android.gms.common.api.PendingResult<com.google.android.gms.cast.framework.media.RemoteMediaClient.MediaChannelResult> -loadItem​(com.google.android.gms.cast.MediaQueueItem item, - long positionMs) - -
    Deprecated. - -
    - - - -com.google.android.gms.common.api.PendingResult<com.google.android.gms.cast.framework.media.RemoteMediaClient.MediaChannelResult> -loadItems​(com.google.android.gms.cast.MediaQueueItem[] items, - int startIndex, - long positionMs, - int repeatMode) - -
    Deprecated. - -
    - - -com.google.android.gms.common.api.PendingResult<com.google.android.gms.cast.framework.media.RemoteMediaClient.MediaChannelResult> -moveItem​(int periodId, - int newIndex) - -
    Deprecated. - -
    - - - void moveMediaItems​(int fromIndex, int toIndex, @@ -629,44 +615,35 @@

    Method Summary

    Moves the media item range to the new index.
    - + void prepare()
    Prepares the player.
    - + void release()
    Releases the player.
    - -com.google.android.gms.common.api.PendingResult<com.google.android.gms.cast.framework.media.RemoteMediaClient.MediaChannelResult> -removeItem​(int periodId) - -
    Deprecated. - -
    - - - + void removeListener​(Player.EventListener listener)
    Unregister a listener registered through Player.addListener(EventListener).
    - + void removeListener​(Player.Listener listener)
    Unregister a listener registered through Player.addListener(Listener).
    - + void removeMediaItems​(int fromIndex, int toIndex) @@ -674,7 +651,7 @@

    Method Summary

    Removes a range of media items from the playlist.
    - + void seekTo​(int windowIndex, long positionMs) @@ -682,21 +659,21 @@

    Method Summary

    Seeks to a position specified in milliseconds in the specified window.
    - + void setDeviceMuted​(boolean muted)
    This method is not supported and does nothing.
    - + void setDeviceVolume​(int volume)
    This method is not supported and does nothing.
    - + void setMediaItems​(List<MediaItem> mediaItems, boolean resetPosition) @@ -704,7 +681,7 @@

    Method Summary

    Clears the playlist and adds the specified MediaItems.
    - + void setMediaItems​(List<MediaItem> mediaItems, int startWindowIndex, @@ -713,77 +690,84 @@

    Method Summary

    Clears the playlist and adds the specified MediaItems.
    - + void setPlaybackParameters​(PlaybackParameters playbackParameters)
    Attempts to set the playback parameters.
    - + +void +setPlaylistMetadata​(MediaMetadata mediaMetadata) + +
    This method is not supported and does nothing.
    + + + void setPlayWhenReady​(boolean playWhenReady)
    Sets whether playback should proceed when Player.getPlaybackState() == Player.STATE_READY.
    - + void setRepeatMode​(int repeatMode)
    Sets the Player.RepeatMode to be used for playback.
    - + void setSessionAvailabilityListener​(SessionAvailabilityListener listener)
    Sets a listener for updates on the cast session availability.
    - + void setShuffleModeEnabled​(boolean shuffleModeEnabled)
    Sets whether shuffling of windows is enabled.
    - + void setVideoSurface​(Surface surface)
    This method is not supported and does nothing.
    - + void setVideoSurfaceHolder​(SurfaceHolder surfaceHolder)
    This method is not supported and does nothing.
    - + void setVideoSurfaceView​(SurfaceView surfaceView)
    This method is not supported and does nothing.
    - + void setVideoTextureView​(TextureView textureView)
    This method is not supported and does nothing.
    - + void setVolume​(float audioVolume)
    This method is not supported and does nothing.
    - + void stop​(boolean reset)   @@ -794,7 +778,7 @@

    Method Summary

    Methods inherited from class com.google.android.exoplayer2.BasePlayer

    -addMediaItem, addMediaItem, addMediaItems, clearMediaItems, getAvailableCommands, getBufferedPercentage, getContentDuration, getCurrentLiveOffset, getCurrentManifest, getCurrentMediaItem, getCurrentTag, getMediaItemAt, getMediaItemCount, getNextWindowIndex, getPlaybackError, getPreviousWindowIndex, hasNext, hasPrevious, isCommandAvailable, isCurrentWindowDynamic, isCurrentWindowLive, isCurrentWindowSeekable, isPlaying, moveMediaItem, next, pause, play, previous, removeMediaItem, seekTo, seekToDefaultPosition, seekToDefaultPosition, setMediaItem, setMediaItem, setMediaItem, setMediaItems, setPlaybackSpeed, stop +addMediaItem, addMediaItem, addMediaItems, clearMediaItems, getAvailableCommands, getBufferedPercentage, getContentDuration, getCurrentLiveOffset, getCurrentManifest, getCurrentMediaItem, getMediaItemAt, getMediaItemCount, getNextWindowIndex, getPreviousWindowIndex, hasNext, hasNextWindow, hasPrevious, hasPreviousWindow, isCommandAvailable, isCurrentWindowDynamic, isCurrentWindowLive, isCurrentWindowSeekable, isPlaying, moveMediaItem, next, pause, play, previous, removeMediaItem, seekBack, seekForward, seekTo, seekToDefaultPosition, seekToDefaultPosition, seekToNext, seekToNextWindow, seekToPrevious, seekToPreviousWindow, setMediaItem, setMediaItem, setMediaItem, setMediaItems, setPlaybackSpeed, stop + + + + + + + + + + + + @@ -1478,21 +1461,9 @@

    getCurrentTrackGroups

    • getCurrentStaticMetadata

      -
      public ImmutableList<Metadata> getCurrentStaticMetadata()
      -
      Description copied from interface: Player
      -
      Returns the current static metadata for the track selections. - -

      The returned metadataList is an immutable list of Metadata instances, where - the elements correspond to the current track selections, - or an empty list if there are no track selections or the selected tracks contain no static - metadata. - -

      This metadata is considered static in that it comes from the tracks' declared Formats, - rather than being timed (or dynamic) metadata, which is represented within a metadata track.

      -
      -
      See Also:
      -
      Player.Listener.onStaticMetadataChanged(List)
      -
      +
      @Deprecated
      +public ImmutableList<Metadata> getCurrentStaticMetadata()
      +
      Deprecated.
    @@ -1507,8 +1478,29 @@

    getMediaMetadata

    supported.

    This MediaMetadata is a combination of the MediaItem.mediaMetadata and the - static and dynamic metadata sourced from Player.Listener.onStaticMetadataChanged(List) and - MetadataOutput.onMetadata(Metadata). + static and dynamic metadata from the track selections' + formats and MetadataOutput.onMetadata(Metadata). + + + + + +

    + + + +
      +
    • +

      setPlaylistMetadata

      +
      public void setPlaylistMetadata​(MediaMetadata mediaMetadata)
      +
      This method is not supported and does nothing.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/ext/cast/DefaultMediaItemConverter.html b/docs/doc/reference/com/google/android/exoplayer2/ext/cast/DefaultMediaItemConverter.html index 3cc3860c387..ed353aae8c5 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ext/cast/DefaultMediaItemConverter.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ext/cast/DefaultMediaItemConverter.html @@ -180,14 +180,14 @@

    Method Summary

    MediaItem -toMediaItem​(com.google.android.gms.cast.MediaQueueItem item) +toMediaItem​(com.google.android.gms.cast.MediaQueueItem mediaQueueItem)
    Converts a MediaQueueItem to a MediaItem.
    com.google.android.gms.cast.MediaQueueItem -toMediaQueueItem​(MediaItem item) +toMediaQueueItem​(MediaItem mediaItem)
    Converts a MediaItem to a MediaQueueItem.
    @@ -241,14 +241,14 @@

    Method Detail

    • toMediaItem

      -
      public MediaItem toMediaItem​(com.google.android.gms.cast.MediaQueueItem item)
      +
      public MediaItem toMediaItem​(com.google.android.gms.cast.MediaQueueItem mediaQueueItem)
      Description copied from interface: MediaItemConverter
      Converts a MediaQueueItem to a MediaItem.
      Specified by:
      toMediaItem in interface MediaItemConverter
      Parameters:
      -
      item - The MediaQueueItem.
      +
      mediaQueueItem - The MediaQueueItem.
      Returns:
      The equivalent MediaItem.
      @@ -260,14 +260,14 @@

      toMediaItem

      • toMediaQueueItem

        -
        public com.google.android.gms.cast.MediaQueueItem toMediaQueueItem​(MediaItem item)
        +
        public com.google.android.gms.cast.MediaQueueItem toMediaQueueItem​(MediaItem mediaItem)
        Description copied from interface: MediaItemConverter
        Converts a MediaItem to a MediaQueueItem.
        Specified by:
        toMediaQueueItem in interface MediaItemConverter
        Parameters:
        -
        item - The MediaItem.
        +
        mediaItem - The MediaItem.
        Returns:
        An equivalent MediaQueueItem.
        diff --git a/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/CronetDataSource.Factory.html b/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/CronetDataSource.Factory.html index 84924d24b06..cd11401f070 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/CronetDataSource.Factory.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/CronetDataSource.Factory.html @@ -25,7 +25,7 @@ catch(err) { } //--> -var data = {"i0":10,"i1":42,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10}; +var data = {"i0":10,"i1":42,"i2":10,"i3":10,"i4":10,"i5":42,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10}; var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"],32:["t6","Deprecated Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -164,6 +164,15 @@

        Constructor Summary

        Factory​(CronetEngineWrapper cronetEngineWrapper, Executor executor) +
        Deprecated. +
        Use Factory(CronetEngine, Executor) with an instantiated CronetEngine, or DefaultHttpDataSource for cases where CronetEngineWrapper.getCronetEngine() would have returned null.
        +
        + + + +Factory​(org.chromium.net.CronetEngine cronetEngine, + Executor executor) +
        Creates an instance.
        @@ -226,7 +235,10 @@

        Method Summary

        CronetDataSource.Factory setFallbackFactory​(HttpDataSource.Factory fallbackFactory) -
        Sets the fallback HttpDataSource.Factory that is used as a fallback if the CronetEngineWrapper fails to provide a CronetEngine.
        +
        Deprecated. +
        Do not use CronetDataSource or its factory in cases where a suitable + CronetEngine is not available.
        +
        @@ -239,26 +251,42 @@

        Method Summary

        CronetDataSource.Factory +setKeepPostFor302Redirects​(boolean keepPostFor302Redirects) + +
        Sets whether we should keep the POST method and body when we have HTTP 302 redirects for a + POST request.
        + + + +CronetDataSource.Factory setReadTimeoutMs​(int readTimeoutMs)
        Sets the read timeout, in milliseconds.
        - + +CronetDataSource.Factory +setRequestPriority​(int requestPriority) + +
        Sets the priority of requests made by CronetDataSource instances created by this + factory.
        + + + CronetDataSource.Factory setResetTimeoutOnRedirects​(boolean resetTimeoutOnRedirects)
        Sets whether the connect timeout is reset when a redirect occurs.
        - + CronetDataSource.Factory setTransferListener​(TransferListener transferListener)
        Sets the TransferListener that will be used.
        - + CronetDataSource.Factory setUserAgent​(String userAgent) @@ -289,14 +317,40 @@

        Methods inherited from class java.lang. + + +
          +
        • +

          Factory

          +
          public Factory​(org.chromium.net.CronetEngine cronetEngine,
          +               Executor executor)
          +
          Creates an instance.
          +
          +
          Parameters:
          +
          cronetEngine - A CronetEngine to make the requests. This should not be + a fallback instance obtained from JavaCronetProvider. It's more efficient to use + DefaultHttpDataSource instead in this case.
          +
          executor - The Executor that will handle responses. This + may be a direct executor (i.e. executes tasks on the calling thread) in order to avoid a + thread hop from Cronet's internal network thread to the response handling thread. + However, to avoid slowing down overall network performance, care must be taken to make + sure response handling is a fast operation when using a direct executor.
          +
          +
        • +
        + + + +
          +
        • +

          setRequestPriority

          +
          public CronetDataSource.Factory setRequestPriority​(int requestPriority)
          +
          Sets the priority of requests made by CronetDataSource instances created by this + factory. + +

          The default is UrlRequest.Builder.REQUEST_PRIORITY_MEDIUM.

          +
          +
          Parameters:
          +
          requestPriority - The request priority, which should be one of Cronet's + UrlRequest.Builder#REQUEST_PRIORITY_* constants.
          +
          Returns:
          +
          This factory.
          +
          +
        • +
        @@ -475,6 +549,17 @@

        setContentTypePredicate

    + + + +
      +
    • +

      setKeepPostFor302Redirects

      +
      public CronetDataSource.Factory setKeepPostFor302Redirects​(boolean keepPostFor302Redirects)
      +
      Sets whether we should keep the POST method and body when we have HTTP 302 redirects for a + POST request.
      +
    • +
    @@ -502,8 +587,13 @@

    setTransferListener

    @@ -228,15 +240,43 @@

    Constructor Summary

    Description +OpenException​(DataSpec dataSpec, + int errorCode, + int cronetConnectionStatus) +  + + OpenException​(IOException cause, DataSpec dataSpec, int cronetConnectionStatus) + + + + + +OpenException​(IOException cause, + DataSpec dataSpec, + int errorCode, + int cronetConnectionStatus)   OpenException​(String errorMessage, DataSpec dataSpec, int cronetConnectionStatus) + + + + + +OpenException​(String errorMessage, + DataSpec dataSpec, + int errorCode, + int cronetConnectionStatus)   @@ -251,6 +291,20 @@

    Constructor Summary

    Method Summary

    + +
    • @@ -307,19 +361,65 @@

      Constructor Detail

      + + + + -
        + + + + +
        • OpenException

          public OpenException​(String errorMessage,
                                DataSpec dataSpec,
          +                     @ErrorCode
          +                     int errorCode,
          +                     int cronetConnectionStatus)
          +
        • +
        + + + +
          +
        • +

          OpenException

          +
          public OpenException​(DataSpec dataSpec,
          +                     @ErrorCode
          +                     int errorCode,
                                int cronetConnectionStatus)
        diff --git a/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/CronetDataSource.html b/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/CronetDataSource.html index 68f2eff96cd..2f063babf72 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/CronetDataSource.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/CronetDataSource.html @@ -240,10 +240,12 @@

        Constructor Summary

        - + + + + + + + + + + + @@ -289,7 +309,8 @@

        Constructor Summary

        - + + - + + + int length) @@ -606,7 +628,7 @@

        CronetDataSource

        -
          +
          • CronetDataSource

            @Deprecated
            @@ -625,6 +647,28 @@ 

            CronetDataSource

          + + + +
            +
          • +

            CronetDataSource

            +
            protected CronetDataSource​(org.chromium.net.CronetEngine cronetEngine,
            +                           Executor executor,
            +                           int requestPriority,
            +                           int connectTimeoutMs,
            +                           int readTimeoutMs,
            +                           boolean resetTimeoutOnRedirects,
            +                           boolean handleSetCookieRequests,
            +                           @Nullable
            +                           String userAgent,
            +                           @Nullable
            +                           HttpDataSource.RequestProperties defaultRequestProperties,
            +                           @Nullable
            +                           Predicate<String> contentTypePredicate,
            +                           boolean keepPostFor302Redirects)
            +
          • +
        @@ -807,7 +851,7 @@

        open

        read

        public int read​(byte[] buffer,
                         int offset,
        -                int readLength)
        +                int length)
                  throws HttpDataSource.HttpDataSourceException
        Description copied from interface: DataReader
        Reads up to length bytes of data from the input. @@ -824,7 +868,7 @@

        read

        Parameters:
        buffer - A target array into which data should be written.
        offset - The offset into the target array at which to write.
        -
        readLength - The maximum number of bytes to read from the input.
        +
        length - The maximum number of bytes to read from the input.
        Returns:
        The number of bytes read, or C.RESULT_END_OF_INPUT if the input has ended. This may be less than length because the end of the input (or available data) was diff --git a/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/CronetEngineWrapper.html b/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/CronetEngineWrapper.html index 7f6c49cb205..b7187d77b81 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/CronetEngineWrapper.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/CronetEngineWrapper.html @@ -25,12 +25,6 @@ catch(err) { } //--> -var data = {"i0":10}; -var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]}; -var altColor = "altColor"; -var rowColor = "rowColor"; -var tableTab = "tableTab"; -var activeTableTab = "activeTableTab"; var pathtoroot = "../../../../../../"; var useModuleDirectories = false; loadScripts(document, 'script'); @@ -86,16 +80,16 @@
        @@ -129,8 +123,15 @@

        Class CronetEngineWrapper

      • -
        public final class CronetEngineWrapper
        +
        @Deprecated
        +public final class CronetEngineWrapper
         extends Object
        +
        Deprecated. +
        Use CronetEngine directly. See the Android developer + guide to learn how to instantiate a CronetEngine for use by your application. You + can also use CronetUtil.buildCronetEngine(android.content.Context, java.lang.String, boolean) to build a CronetEngine suitable + for use by ExoPlayer.
        +
        A wrapper class for a CronetEngine.
      • @@ -138,84 +139,6 @@

        Class CronetEngineWrapper
        • - -
          -
            -
          • - - -

            Nested Class Summary

            -

        Constructors 
        ConstructorModifierConstructor Description
          CronetDataSource​(org.chromium.net.CronetEngine cronetEngine, Executor executor) @@ -253,6 +255,7 @@

        Constructor Summary

          CronetDataSource​(org.chromium.net.CronetEngine cronetEngine, Executor executor, int connectTimeoutMs, @@ -266,6 +269,7 @@

        Constructor Summary

          CronetDataSource​(org.chromium.net.CronetEngine cronetEngine, Executor executor, int connectTimeoutMs, @@ -280,6 +284,22 @@

        Constructor Summary

        protected CronetDataSource​(org.chromium.net.CronetEngine cronetEngine, + Executor executor, + int requestPriority, + int connectTimeoutMs, + int readTimeoutMs, + boolean resetTimeoutOnRedirects, + boolean handleSetCookieRequests, + String userAgent, + HttpDataSource.RequestProperties defaultRequestProperties, + Predicate<String> contentTypePredicate, + boolean keepPostFor302Redirects) 
          CronetDataSource​(org.chromium.net.CronetEngine cronetEngine, Executor executor, Predicate<String> contentTypePredicate)
          CronetDataSource​(org.chromium.net.CronetEngine cronetEngine, Executor executor, Predicate<String> contentTypePredicate, @@ -303,7 +324,8 @@

        Constructor Summary

          CronetDataSource​(org.chromium.net.CronetEngine cronetEngine, Executor executor, Predicate<String> contentTypePredicate, @@ -409,7 +431,7 @@

        Method Summary

        int read​(byte[] buffer, int offset, - int readLength)
        Reads up to length bytes of data from the input.
        - - - - - - - - - - - -
        Nested Classes 
        Modifier and TypeClassDescription
        static interface CronetEngineWrapper.CronetEngineSource -
        Source of CronetEngine.
        -
        - -
      - - -
      -
        -
      • - - -

        Field Summary

        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        Fields 
        Modifier and TypeFieldDescription
        static intSOURCE_GMS -
        Cronet implementation from GMSCore.
        -
        static intSOURCE_NATIVE -
        Natively bundled Cronet implementation.
        -
        static intSOURCE_UNAVAILABLE -
        No Cronet implementation available.
        -
        static intSOURCE_UNKNOWN -
        Other (unknown) Cronet implementation.
        -
        static intSOURCE_USER_PROVIDED -
        User-provided Cronet engine.
        -
        -
      • -
      -
        @@ -232,20 +155,23 @@

        Constructor Summary

        CronetEngineWrapper​(Context context) +
        Deprecated.
        Creates a wrapper for a CronetEngine built using the most suitable CronetProvider.
        CronetEngineWrapper​(Context context, String userAgent, - boolean preferGMSCoreCronet) + boolean preferGooglePlayServices)
        +
        Deprecated.
        Creates a wrapper for a CronetEngine built using the most suitable CronetProvider.
        CronetEngineWrapper​(org.chromium.net.CronetEngine cronetEngine) +
        Deprecated.
        Creates a wrapper for an existing CronetEngine.
        @@ -260,21 +186,6 @@

        Constructor Summary

        Method Summary

        - - - - - - - - - - - - -
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethodDescription
        intgetCronetEngineSource() -
        Returns the source of the wrapped CronetEngine.
        -
        • @@ -291,86 +202,6 @@

          Methods inherited from class java.lang.
          • - -
            -
              -
            • - - -

              Field Detail

              - - - -
                -
              • -

                SOURCE_NATIVE

                -
                public static final int SOURCE_NATIVE
                -
                Natively bundled Cronet implementation.
                -
                -
                See Also:
                -
                Constant Field Values
                -
                -
              • -
              - - - -
                -
              • -

                SOURCE_GMS

                -
                public static final int SOURCE_GMS
                -
                Cronet implementation from GMSCore.
                -
                -
                See Also:
                -
                Constant Field Values
                -
                -
              • -
              - - - -
                -
              • -

                SOURCE_UNKNOWN

                -
                public static final int SOURCE_UNKNOWN
                -
                Other (unknown) Cronet implementation.
                -
                -
                See Also:
                -
                Constant Field Values
                -
                -
              • -
              - - - -
                -
              • -

                SOURCE_USER_PROVIDED

                -
                public static final int SOURCE_USER_PROVIDED
                -
                User-provided Cronet engine.
                -
                -
                See Also:
                -
                Constant Field Values
                -
                -
              • -
              - - - -
                -
              • -

                SOURCE_UNAVAILABLE

                -
                public static final int SOURCE_UNAVAILABLE
                -
                No Cronet implementation available. Fallback Http provider is used if possible.
                -
                -
                See Also:
                -
                Constant Field Values
                -
                -
              • -
              -
            • -
            -
              @@ -385,6 +216,7 @@

              Constructor Detail

            • CronetEngineWrapper

              public CronetEngineWrapper​(Context context)
              +
              Deprecated.
              Creates a wrapper for a CronetEngine built using the most suitable CronetProvider. When natively bundled Cronet and GMSCore Cronet are both available, the natively bundled provider is preferred.
              @@ -402,7 +234,8 @@

              CronetEngineWrapper

              public CronetEngineWrapper​(Context context,
                                          @Nullable
                                          String userAgent,
              -                           boolean preferGMSCoreCronet)
              + boolean preferGooglePlayServices) +
              Deprecated.
              Creates a wrapper for a CronetEngine built using the most suitable CronetProvider. When natively bundled Cronet and GMSCore Cronet are both available, preferGMSCoreCronet determines which is preferred.
              @@ -410,8 +243,8 @@

              CronetEngineWrapper

              context - A context.
              userAgent - A default user agent, or null to use a default user agent of the CronetEngine.
              -
              preferGMSCoreCronet - Whether Cronet from GMSCore should be preferred over natively - bundled Cronet if both are available.
              +
              preferGooglePlayServices - Whether Cronet from Google Play Services should be preferred + over Cronet Embedded, if both are available.
            @@ -422,6 +255,7 @@

            CronetEngineWrapper

          • CronetEngineWrapper

            public CronetEngineWrapper​(org.chromium.net.CronetEngine cronetEngine)
            +
            Deprecated.
            Creates a wrapper for an existing CronetEngine.
            Parameters:
            @@ -432,31 +266,6 @@

            CronetEngineWrapper

      - -
      - -
    @@ -505,16 +314,16 @@

    getCronetEngineSource

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/CronetUtil.html b/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/CronetUtil.html new file mode 100644 index 00000000000..ae3a8ee830d --- /dev/null +++ b/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/CronetUtil.html @@ -0,0 +1,287 @@ + + + + +CronetUtil (ExoPlayer library) + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class CronetUtil

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.google.android.exoplayer2.ext.cronet.CronetUtil
      • +
      +
    • +
    +
    +
      +
    • +
      +
      public final class CronetUtil
      +extends Object
      +
      Cronet utility methods.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          buildCronetEngine

          +
          @Nullable
          +public static org.chromium.net.CronetEngine buildCronetEngine​(Context context,
          +                                                              @Nullable
          +                                                              String userAgent,
          +                                                              boolean preferGooglePlayServices)
          +
          Builds a CronetEngine suitable for use with ExoPlayer. When choosing a Cronet provider to build the CronetEngine, disabled providers are not + considered. Neither are fallback providers, since it's more efficient to use DefaultHttpDataSource than it is to use CronetDataSource with a fallback CronetEngine. + +

          Note that it's recommended for applications to create only one instance of CronetEngine, so if your application already has an instance for performing other networking, + then that instance should be used and calling this method is unnecessary. See the Android developer + guide to learn more about using Cronet for network operations.

          +
          +
          Parameters:
          +
          context - A context.
          +
          userAgent - A default user agent, or null to use a default user agent of the + CronetEngine.
          +
          preferGooglePlayServices - Whether Cronet from Google Play Services should be preferred + over Cronet Embedded, if both are available.
          +
          Returns:
          +
          The CronetEngine, or null if no suitable engine could be built.
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +
    + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/package-summary.html b/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/package-summary.html index cf9f6dd9566..dd92b5129f1 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/package-summary.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/package-summary.html @@ -123,8 +123,14 @@

    Package com.google.android.exoplayer2.ext CronetEngineWrapper +Deprecated. +
    Use CronetEngine directly.
    + + + +CronetUtil -
    A wrapper class for a CronetEngine.
    +
    Cronet utility methods.
    @@ -147,23 +153,6 @@

    Package com.google.android.exoplayer2.ext -
  • - - - - - - - - - - - - -
    Annotation Types Summary 
    Annotation TypeDescription
    CronetEngineWrapper.CronetEngineSource -
    Source of CronetEngine.
    -
    -
  • diff --git a/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/package-tree.html b/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/package-tree.html index 73483b20ca2..d038641cdbc 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/package-tree.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/package-tree.html @@ -110,6 +110,7 @@

    Class Hierarchy

  • com.google.android.exoplayer2.ext.cronet.CronetDataSource.Factory (implements com.google.android.exoplayer2.upstream.HttpDataSource.Factory)
  • com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper
  • +
  • com.google.android.exoplayer2.ext.cronet.CronetUtil
  • com.google.android.exoplayer2.upstream.HttpDataSource.BaseFactory (implements com.google.android.exoplayer2.upstream.HttpDataSource.Factory) @@ -369,14 +372,17 @@

    onSkipToPrevious

  • onSkipToQueueItem

    void onSkipToQueueItem​(Player player,
    +                       @Deprecated
                            ControlDispatcher controlDispatcher,
                            long id)
    See MediaSessionCompat.Callback.onSkipToQueueItem(long).
    Parameters:
    player - The player connected to the media session.
    -
    controlDispatcher - A ControlDispatcher that should be used for dispatching - changes to the player.
    +
    controlDispatcher - This parameter is deprecated. Use player instead. Operations + can be customized by passing a ForwardingPlayer to MediaSessionConnector.setPlayer(Player), or + when configuring the player (for example by using + SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)).
  • @@ -387,13 +393,16 @@

    onSkipToQueueItem

  • onSkipToNext

    void onSkipToNext​(Player player,
    +                  @Deprecated
                       ControlDispatcher controlDispatcher)
    See MediaSessionCompat.Callback.onSkipToNext().
    Parameters:
    player - The player connected to the media session.
    -
    controlDispatcher - A ControlDispatcher that should be used for dispatching - changes to the player.
    +
    controlDispatcher - This parameter is deprecated. Use player instead. Operations + can be customized by passing a ForwardingPlayer to MediaSessionConnector.setPlayer(Player), or + when configuring the player (for example by using + SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)).
  • diff --git a/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.html b/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.html index 240ff9e1567..2fbe4eb63f7 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.html @@ -25,7 +25,7 @@ catch(err) { } //--> -var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":42,"i13":10,"i14":10,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":42,"i21":10}; +var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":42,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10,"i21":10}; var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"],32:["t6","Deprecated Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -278,24 +278,17 @@

    Field Summary

    static long -ACTION_SET_PLAYBACK_SPEED - -
    Indicates this session supports the set playback speed command.
    - - - -static long ALL_PLAYBACK_ACTIONS   - + static long DEFAULT_PLAYBACK_ACTIONS
    The default playback actions.
    - + static String EXTRAS_SPEED @@ -303,7 +296,7 @@

    Field Summary

    Player.getPlaybackParameters().speed. - + android.support.v4.media.session.MediaSessionCompat mediaSession @@ -390,7 +383,9 @@

    Method Summary

    void setControlDispatcher​(ControlDispatcher controlDispatcher) - +
    Deprecated. +
    Use a ForwardingPlayer and pass it to setPlayer(Player) instead.
    +
    @@ -426,25 +421,24 @@

    Method Summary

    void -setEnabledPlaybackActions​(long enabledPlaybackActions) +setDispatchUnsupportedActionsEnabled​(boolean dispatchUnsupportedActionsEnabled) -
    Sets the enabled playback actions.
    +
    Sets whether actions that are not advertised to the MediaSessionCompat will be + dispatched either way.
    void -setErrorMessageProvider​(ErrorMessageProvider<? super ExoPlaybackException> errorMessageProvider) +setEnabledPlaybackActions​(long enabledPlaybackActions) -
    Sets the optional ErrorMessageProvider.
    +
    Sets the enabled playback actions.
    void -setFastForwardIncrementMs​(int fastForwardMs) +setErrorMessageProvider​(ErrorMessageProvider<? super PlaybackException> errorMessageProvider) - +
    Sets the optional ErrorMessageProvider.
    @@ -463,26 +457,34 @@

    Method Summary

    void +setMetadataDeduplicationEnabled​(boolean metadataDeduplicationEnabled) + +
    Sets whether MediaSessionConnector.MediaMetadataProvider.sameAs(MediaMetadataCompat, MediaMetadataCompat) + should be consulted before calling MediaSessionCompat.setMetadata(MediaMetadataCompat).
    + + + +void setPlaybackPreparer​(MediaSessionConnector.PlaybackPreparer playbackPreparer) - + void setPlayer​(Player player)
    Sets the player to be connected to the media session.
    - + void setQueueEditor​(MediaSessionConnector.QueueEditor queueEditor)
    Sets the MediaSessionConnector.QueueEditor to handle queue edits sent by the media controller.
    - + void setQueueNavigator​(MediaSessionConnector.QueueNavigator queueNavigator) @@ -490,22 +492,13 @@

    Method Summary

    ACTION_SKIP_TO_PREVIOUS and ACTION_SKIP_TO_QUEUE_ITEM. - + void setRatingCallback​(MediaSessionConnector.RatingCallback ratingCallback)
    Sets the MediaSessionConnector.RatingCallback to handle user ratings.
    - -void -setRewindIncrementMs​(int rewindMs) - - - - void unregisterCustomCommandReceiver​(MediaSessionConnector.CommandReceiver commandReceiver) @@ -537,20 +530,6 @@

    Methods inherited from class java.lang. - - -
      -
    • -

      ACTION_SET_PLAYBACK_SPEED

      -
      public static final long ACTION_SET_PLAYBACK_SPEED
      -
      Indicates this session supports the set playback speed command.
      -
      -
      See Also:
      -
      Constant Field Values
      -
      -
    • -
    @@ -675,12 +654,13 @@

    setPlaybackPreparer

    @@ -722,32 +702,6 @@

    setEnabledPlaybackActions

    -
    - - - - - - - @@ -755,7 +709,7 @@

    setFastForwardIncrementMs

  • setErrorMessageProvider

    public void setErrorMessageProvider​(@Nullable
    -                                    ErrorMessageProvider<? super ExoPlaybackException> errorMessageProvider)
    + ErrorMessageProvider<? super PlaybackException> errorMessageProvider)
    Sets the optional ErrorMessageProvider.
    Parameters:
    @@ -913,6 +867,35 @@

    setMediaMetadataProvider

  • + + + +
      +
    • +

      setDispatchUnsupportedActionsEnabled

      +
      public void setDispatchUnsupportedActionsEnabled​(boolean dispatchUnsupportedActionsEnabled)
      +
      Sets whether actions that are not advertised to the MediaSessionCompat will be + dispatched either way. Default value is false.
      +
    • +
    + + + +
      +
    • +

      setMetadataDeduplicationEnabled

      +
      public void setMetadataDeduplicationEnabled​(boolean metadataDeduplicationEnabled)
      +
      Sets whether MediaSessionConnector.MediaMetadataProvider.sameAs(MediaMetadataCompat, MediaMetadataCompat) + should be consulted before calling MediaSessionCompat.setMetadata(MediaMetadataCompat). + +

      Note that this comparison is normally only required when you are using media sources that + may introduce duplicate updates of the metadata for the same media item (e.g. live streams).

      +
      +
      Parameters:
      +
      metadataDeduplicationEnabled - Whether to deduplicate metadata objects on invalidation.
      +
      +
    • +
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/RepeatModeActionProvider.html b/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/RepeatModeActionProvider.html index 3f4cd71c3a6..32ee3067482 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/RepeatModeActionProvider.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/RepeatModeActionProvider.html @@ -330,6 +330,7 @@

    Method Detail

  • onCustomAction

    public void onCustomAction​(Player player,
    +                           @Deprecated
                                ControlDispatcher controlDispatcher,
                                String action,
                                @Nullable
    @@ -341,8 +342,10 @@ 

    onCustomAction

    onCustomAction in interface MediaSessionConnector.CustomActionProvider
    Parameters:
    player - The player connected to the media session.
    -
    controlDispatcher - A ControlDispatcher that should be used for dispatching - changes to the player.
    +
    controlDispatcher - This parameter is deprecated. Use player instead. Operations + can be customized by passing a ForwardingPlayer to MediaSessionConnector.setPlayer(Player), or + when configuring the player (for example by using + SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)).
    action - The name of the action which was sent by a media controller.
    extras - Optional extras sent by a media controller, may be null.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/TimelineQueueEditor.QueueDataAdapter.html b/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/TimelineQueueEditor.QueueDataAdapter.html index b77a67cacbe..8eeecc7ba51 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/TimelineQueueEditor.QueueDataAdapter.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/TimelineQueueEditor.QueueDataAdapter.html @@ -127,8 +127,7 @@

    Interfa
    public static interface TimelineQueueEditor.QueueDataAdapter
    Adapter to get MediaDescriptionCompat of items in the queue and to notify the - application about changes in the queue to sync the data structure backing the - MediaSessionConnector.
    + application about changes in the queue to sync the data structure backing the MediaSessionConnector.

  • diff --git a/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/TimelineQueueEditor.html b/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/TimelineQueueEditor.html index e7e899f10da..d7e91f838eb 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/TimelineQueueEditor.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/TimelineQueueEditor.html @@ -180,8 +180,7 @@

    Nested Class Summary

    TimelineQueueEditor.QueueDataAdapter
    Adapter to get MediaDescriptionCompat of items in the queue and to notify the - application about changes in the queue to sync the data structure backing the - MediaSessionConnector.
    + application about changes in the queue to sync the data structure backing the MediaSessionConnector. @@ -488,6 +487,7 @@

    onRemoveQueueItem

  • onCommand

    public boolean onCommand​(Player player,
    +                         @Deprecated
                              ControlDispatcher controlDispatcher,
                              String command,
                              @Nullable
    @@ -496,15 +496,16 @@ 

    onCommand

    ResultReceiver cb)
    Description copied from interface: MediaSessionConnector.CommandReceiver
    See MediaSessionCompat.Callback.onCommand(String, Bundle, ResultReceiver). The - receiver may handle the command, but is not required to do so. Changes to the player should - be made via the ControlDispatcher.
    + receiver may handle the command, but is not required to do so.
    Specified by:
    onCommand in interface MediaSessionConnector.CommandReceiver
    Parameters:
    player - The player connected to the media session.
    -
    controlDispatcher - A ControlDispatcher that should be used for dispatching - changes to the player.
    +
    controlDispatcher - This parameter is deprecated. Use player instead. Operations + can be customized by passing a ForwardingPlayer to MediaSessionConnector.setPlayer(Player), or + when configuring the player (for example by using + SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)).
    command - The command name.
    extras - Optional parameters for the command, may be null.
    cb - A result receiver to which a result may be sent by the command, may be null.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/TimelineQueueNavigator.html b/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/TimelineQueueNavigator.html index 930f99d0233..35b60298804 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/TimelineQueueNavigator.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/TimelineQueueNavigator.html @@ -345,8 +345,8 @@

    Constructor Detail

    TimelineQueueNavigator

    public TimelineQueueNavigator​(android.support.v4.media.session.MediaSessionCompat mediaSession)
    Creates an instance for a given MediaSessionCompat. -

    - Equivalent to TimelineQueueNavigator(mediaSession, DEFAULT_MAX_QUEUE_SIZE).

    + +

    Equivalent to TimelineQueueNavigator(mediaSession, DEFAULT_MAX_QUEUE_SIZE).

    Parameters:
    mediaSession - The MediaSessionCompat.
    @@ -362,10 +362,10 @@

    TimelineQueueNavigator

    public TimelineQueueNavigator​(android.support.v4.media.session.MediaSessionCompat mediaSession,
                                   int maxQueueSize)
    Creates an instance for a given MediaSessionCompat and maximum queue size. -

    - If the number of windows in the Player's Timeline exceeds maxQueueSize, - the media session queue will correspond to maxQueueSize windows centered on the one - currently being played.

    + +

    If the number of windows in the Player's Timeline exceeds + maxQueueSize, the media session queue will correspond to maxQueueSize windows centered + on the one currently being played.

    Parameters:
    mediaSession - The MediaSessionCompat.
    @@ -489,6 +489,7 @@

    getActiveQueueItemId

  • onSkipToPrevious

    public void onSkipToPrevious​(Player player,
    +                             @Deprecated
                                  ControlDispatcher controlDispatcher)
    Description copied from interface: MediaSessionConnector.QueueNavigator
    See MediaSessionCompat.Callback.onSkipToPrevious().
    @@ -497,8 +498,10 @@

    onSkipToPrevious

    onSkipToPrevious in interface MediaSessionConnector.QueueNavigator
    Parameters:
    player - The player connected to the media session.
    -
    controlDispatcher - A ControlDispatcher that should be used for dispatching - changes to the player.
    +
    controlDispatcher - This parameter is deprecated. Use player instead. Operations + can be customized by passing a ForwardingPlayer to MediaSessionConnector.setPlayer(Player), or + when configuring the player (for example by using + SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)).
  • @@ -509,6 +512,7 @@

    onSkipToPrevious

  • onSkipToQueueItem

    public void onSkipToQueueItem​(Player player,
    +                              @Deprecated
                                   ControlDispatcher controlDispatcher,
                                   long id)
    Description copied from interface: MediaSessionConnector.QueueNavigator
    @@ -518,8 +522,10 @@

    onSkipToQueueItem

    onSkipToQueueItem in interface MediaSessionConnector.QueueNavigator
    Parameters:
    player - The player connected to the media session.
    -
    controlDispatcher - A ControlDispatcher that should be used for dispatching - changes to the player.
    +
    controlDispatcher - This parameter is deprecated. Use player instead. Operations + can be customized by passing a ForwardingPlayer to MediaSessionConnector.setPlayer(Player), or + when configuring the player (for example by using + SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)).
  • @@ -530,6 +536,7 @@

    onSkipToQueueItem

  • onSkipToNext

    public void onSkipToNext​(Player player,
    +                         @Deprecated
                              ControlDispatcher controlDispatcher)
    Description copied from interface: MediaSessionConnector.QueueNavigator
    See MediaSessionCompat.Callback.onSkipToNext().
    @@ -538,8 +545,10 @@

    onSkipToNext

    onSkipToNext in interface MediaSessionConnector.QueueNavigator
    Parameters:
    player - The player connected to the media session.
    -
    controlDispatcher - A ControlDispatcher that should be used for dispatching - changes to the player.
    +
    controlDispatcher - This parameter is deprecated. Use player instead. Operations + can be customized by passing a ForwardingPlayer to MediaSessionConnector.setPlayer(Player), or + when configuring the player (for example by using + SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)).
  • @@ -550,6 +559,7 @@

    onSkipToNext

  • onCommand

    public boolean onCommand​(Player player,
    +                         @Deprecated
                              ControlDispatcher controlDispatcher,
                              String command,
                              @Nullable
    @@ -558,15 +568,16 @@ 

    onCommand

    ResultReceiver cb)
    Description copied from interface: MediaSessionConnector.CommandReceiver
    See MediaSessionCompat.Callback.onCommand(String, Bundle, ResultReceiver). The - receiver may handle the command, but is not required to do so. Changes to the player should - be made via the ControlDispatcher.
    + receiver may handle the command, but is not required to do so.
    Specified by:
    onCommand in interface MediaSessionConnector.CommandReceiver
    Parameters:
    player - The player connected to the media session.
    -
    controlDispatcher - A ControlDispatcher that should be used for dispatching - changes to the player.
    +
    controlDispatcher - This parameter is deprecated. Use player instead. Operations + can be customized by passing a ForwardingPlayer to MediaSessionConnector.setPlayer(Player), or + when configuring the player (for example by using + SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)).
    command - The command name.
    extras - Optional parameters for the command, may be null.
    cb - A result receiver to which a result may be sent by the command, may be null.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/package-summary.html b/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/package-summary.html index bb92c438df4..2b43dd966cb 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/package-summary.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/package-summary.html @@ -169,8 +169,7 @@

    Package com.google.android.exoplayer2.ext TimelineQueueEditor.QueueDataAdapter
    Adapter to get MediaDescriptionCompat of items in the queue and to notify the - application about changes in the queue to sync the data structure backing the - MediaSessionConnector.
    + application about changes in the queue to sync the data structure backing the MediaSessionConnector. diff --git a/docs/doc/reference/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.html b/docs/doc/reference/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.html index 5537fcc7909..68fd3ed58c7 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.html @@ -314,7 +314,7 @@

    Method Summary

    int read​(byte[] buffer, int offset, - int readLength) + int length)
    Reads up to length bytes of data from the input.
    @@ -598,7 +598,7 @@

    open

    read

    public int read​(byte[] buffer,
                     int offset,
    -                int readLength)
    +                int length)
              throws HttpDataSource.HttpDataSourceException
    Description copied from interface: DataReader
    Reads up to length bytes of data from the input. @@ -615,7 +615,7 @@

    read

    Parameters:
    buffer - A target array into which data should be written.
    offset - The offset into the target array at which to write.
    -
    readLength - The maximum number of bytes to read from the input.
    +
    length - The maximum number of bytes to read from the input.
    Returns:
    The number of bytes read, or C.RESULT_END_OF_INPUT if the input has ended. This may be less than length because the end of the input (or available data) was @@ -631,8 +631,7 @@

    read

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/ext/opus/LibopusAudioRenderer.html b/docs/doc/reference/com/google/android/exoplayer2/ext/opus/LibopusAudioRenderer.html index becbb9c861b..3f3066eeab8 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ext/opus/LibopusAudioRenderer.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ext/opus/LibopusAudioRenderer.html @@ -293,7 +293,7 @@

    Methods inherited from class com.google.android.exoplayer2.audio.

    Methods inherited from class com.google.android.exoplayer2.BaseRenderer

    -createRendererException, createRendererException, disable, enable, getCapabilities, getConfiguration, getFormatHolder, getIndex, getLastResetPositionUs, getReadingPositionUs, getState, getStream, getStreamFormats, getTrackType, hasReadStreamToEnd, isCurrentStreamFinal, isSourceReady, maybeThrowStreamError, onReset, onStreamChanged, readSource, replaceStream, reset, resetPosition, setCurrentStreamFinal, setIndex, skipSource, start, stop, supportsMixedMimeTypeAdaptation
  • +createRendererException, createRendererException, disable, enable, getCapabilities, getConfiguration, getFormatHolder, getIndex, getLastResetPositionUs, getReadingPositionUs, getState, getStream, getStreamFormats, getTrackType, hasReadStreamToEnd, isCurrentStreamFinal, isSourceReady, maybeThrowStreamError, onReset, onStreamChanged, readSource, replaceStream, reset, resetPosition, setCurrentStreamFinal, setIndex, skipSource, start, stop, supportsMixedMimeTypeAdaptation @@ -107,91 +113,40 @@
    - -

    Class VpxOutputBuffer

    + +

    Class RtmpDataSource.Factory

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/ext/rtmp/RtmpDataSource.html b/docs/doc/reference/com/google/android/exoplayer2/ext/rtmp/RtmpDataSource.html index 57fe4bf2856..86edd522989 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ext/rtmp/RtmpDataSource.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ext/rtmp/RtmpDataSource.html @@ -154,13 +154,21 @@

    Class RtmpDataSource

    Nested Class Summary

    - + + + + + + + + + + + + +
    Nested Classes 
    Modifier and TypeClassDescription
    static class RtmpDataSource.Factory + +
    @@ -224,7 +232,7 @@

    Method Summary

    int read​(byte[] buffer, int offset, - int readLength) + int length)
    Reads up to length bytes of data from the input.
    @@ -334,7 +342,7 @@

    open

    read

    public int read​(byte[] buffer,
                     int offset,
    -                int readLength)
    +                int length)
              throws IOException
    Description copied from interface: DataReader
    Reads up to length bytes of data from the input. @@ -347,7 +355,7 @@

    read

    Parameters:
    buffer - A target array into which data should be written.
    offset - The offset into the target array at which to write.
    -
    readLength - The maximum number of bytes to read from the input.
    +
    length - The maximum number of bytes to read from the input.
    Returns:
    The number of bytes read, or C.RESULT_END_OF_INPUT if the input has ended. This may be less than length because the end of the input (or available data) was diff --git a/docs/doc/reference/com/google/android/exoplayer2/ext/rtmp/RtmpDataSourceFactory.html b/docs/doc/reference/com/google/android/exoplayer2/ext/rtmp/RtmpDataSourceFactory.html index 5b12c976a63..1372689cfd3 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ext/rtmp/RtmpDataSourceFactory.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ext/rtmp/RtmpDataSourceFactory.html @@ -25,8 +25,8 @@ catch(err) { } //--> -var data = {"i0":10}; -var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]}; +var data = {"i0":42}; +var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"],32:["t6","Deprecated Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; var tableTab = "tableTab"; @@ -133,10 +133,13 @@

    Class RtmpDataSourceFactor
    DataSource.Factory

    -
    public final class RtmpDataSourceFactory
    +
    @Deprecated
    +public final class RtmpDataSourceFactory
     extends Object
     implements DataSource.Factory
    - +
    Deprecated. + +

    @@ -158,11 +161,15 @@

    Constructor Summary

    RtmpDataSourceFactory() -  + +
    Deprecated.
    RtmpDataSourceFactory​(TransferListener listener) -  + +
    Deprecated.
    +  @@ -176,7 +183,7 @@

    Constructor Summary

    Method Summary

    - + @@ -186,6 +193,7 @@

    Method Summary

    @@ -220,6 +228,7 @@

    Constructor Detail

  • RtmpDataSourceFactory

    public RtmpDataSourceFactory()
    +
    Deprecated.
  • @@ -230,6 +239,7 @@

    RtmpDataSourceFactory

    RtmpDataSourceFactory

    public RtmpDataSourceFactory​(@Nullable
                                  TransferListener listener)
    +
    Deprecated.
    Parameters:
    listener - An optional listener.
    @@ -253,6 +263,7 @@

    Method Detail

  • createDataSource

    public RtmpDataSource createDataSource()
    +
    Deprecated.
    Description copied from interface: DataSource.Factory
    Creates a DataSource instance.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/ext/rtmp/package-summary.html b/docs/doc/reference/com/google/android/exoplayer2/ext/rtmp/package-summary.html index 0df22e84d50..5fbf1b1b813 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ext/rtmp/package-summary.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ext/rtmp/package-summary.html @@ -110,9 +110,15 @@

    Package com.google.android.exoplayer2.ext

  • - + + + + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/ext/rtmp/package-tree.html b/docs/doc/reference/com/google/android/exoplayer2/ext/rtmp/package-tree.html index 033c1f9dd19..32f83f6dc03 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ext/rtmp/package-tree.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ext/rtmp/package-tree.html @@ -108,6 +108,7 @@

    Class Hierarchy

  • com.google.android.exoplayer2.ext.rtmp.RtmpDataSource
  • +
  • com.google.android.exoplayer2.ext.rtmp.RtmpDataSource.Factory (implements com.google.android.exoplayer2.upstream.DataSource.Factory)
  • com.google.android.exoplayer2.ext.rtmp.RtmpDataSourceFactory (implements com.google.android.exoplayer2.upstream.DataSource.Factory)
  • diff --git a/docs/doc/reference/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.html b/docs/doc/reference/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.html index dc5b6d5552d..0ed5d790101 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.html @@ -324,7 +324,7 @@

    Methods inherited from class com.google.android.exoplayer2.video.

    Methods inherited from class com.google.android.exoplayer2.BaseRenderer

    -createRendererException, createRendererException, disable, enable, getCapabilities, getConfiguration, getFormatHolder, getIndex, getLastResetPositionUs, getMediaClock, getReadingPositionUs, getState, getStream, getStreamFormats, getTrackType, hasReadStreamToEnd, isCurrentStreamFinal, isSourceReady, maybeThrowStreamError, onReset, readSource, replaceStream, reset, resetPosition, setCurrentStreamFinal, setIndex, skipSource, start, stop, supportsMixedMimeTypeAdaptation +createRendererException, createRendererException, disable, enable, getCapabilities, getConfiguration, getFormatHolder, getIndex, getLastResetPositionUs, getMediaClock, getReadingPositionUs, getState, getStream, getStreamFormats, getTrackType, hasReadStreamToEnd, isCurrentStreamFinal, isSourceReady, maybeThrowStreamError, onReset, readSource, replaceStream, reset, resetPosition, setCurrentStreamFinal, setIndex, skipSource, start, stop, supportsMixedMimeTypeAdaptation - - -
    All Methods Instance Methods Concrete Methods All Methods Instance Methods Concrete Methods Deprecated Methods 
    Modifier and Type Method RtmpDataSource createDataSource() +
    Deprecated.
    Creates a DataSource instance.
    RtmpDataSourceFactoryRtmpDataSource.Factory - + +
    RtmpDataSourceFactoryDeprecated. +
    VpxOutputBufferDeprecated. - -
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/ext/vp9/package-tree.html b/docs/doc/reference/com/google/android/exoplayer2/ext/vp9/package-tree.html index 9a99bd35353..9aaf97e293c 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ext/vp9/package-tree.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ext/vp9/package-tree.html @@ -112,19 +112,6 @@

    Class Hierarchy

    -
  • com.google.android.exoplayer2.decoder.Buffer - -
  • com.google.android.exoplayer2.decoder.SimpleDecoder<I,​O,​E> (implements com.google.android.exoplayer2.decoder.Decoder<I,​O,​E>)
    • com.google.android.exoplayer2.ext.vp9.VpxDecoder
    • diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/DefaultExtractorInput.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/DefaultExtractorInput.html index 0619fb7c36c..bef6affacb2 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/DefaultExtractorInput.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/DefaultExtractorInput.html @@ -247,7 +247,7 @@

      Method Summary

      int -read​(byte[] target, +read​(byte[] buffer, int offset, int length) @@ -368,7 +368,7 @@

      Method Detail

      • read

        -
        public int read​(byte[] target,
        +
        public int read​(byte[] buffer,
                         int offset,
                         int length)
                  throws IOException
        @@ -383,7 +383,7 @@

        read

        Specified by:
        read in interface ExtractorInput
        Parameters:
        -
        target - A target array into which data should be written.
        +
        buffer - A target array into which data should be written.
        offset - The offset into the target array at which to write.
        length - The maximum number of bytes to read from the input.
        Returns:
        diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/Extractor.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/Extractor.html index 76f1d984e0f..ba7efc414ed 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/Extractor.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/Extractor.html @@ -185,8 +185,7 @@

        Field Summary

        static int RESULT_END_OF_INPUT -
        Returned by read(ExtractorInput, PositionHolder) if the end of the - ExtractorInput was reached.
        +
        Returned by read(ExtractorInput, PositionHolder) if the end of the ExtractorInput was reached.
        @@ -310,8 +309,7 @@

        RESULT_SEEK

      • RESULT_END_OF_INPUT

        static final int RESULT_END_OF_INPUT
        -
        Returned by read(ExtractorInput, PositionHolder) if the end of the - ExtractorInput was reached. Equal to C.RESULT_END_OF_INPUT.
        +
        Returned by read(ExtractorInput, PositionHolder) if the end of the ExtractorInput was reached. Equal to C.RESULT_END_OF_INPUT.
        See Also:
        Constant Field Values
        @@ -410,8 +408,8 @@

        seek

        void seek​(long position,
                   long timeUs)
        Notifies the extractor that a seek has occurred. -

        - Following a call to this method, the ExtractorInput passed to the next invocation of + +

        Following a call to this method, the ExtractorInput passed to the next invocation of read(ExtractorInput, PositionHolder) is required to provide data starting from position in the stream. Valid random access positions are the start of the stream and positions that can be obtained from any SeekMap passed to the ExtractorOutput.

        diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/ExtractorInput.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/ExtractorInput.html index 16f7c7a83a2..c391ed06b3c 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/ExtractorInput.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/ExtractorInput.html @@ -143,7 +143,7 @@

        Interface ExtractorInput

        wants to read an entire block/frame/header of known length.
      -

      InputStream-like methods

      +

      InputStream-like methods

      The read()/peek() and skip() methods provide InputStream-like byte-level access operations. The length parameter is a maximum, and each method returns @@ -151,7 +151,7 @@

      Block-based methods

      +

      Block-based methods

      The read/skip/peekFully() and advancePeekPosition() methods assume the user wants to read an entire block/frame/header of known length. @@ -259,7 +259,7 @@

      Method Summary

      int -
      read​(byte[] target, +read​(byte[] buffer, int offset, int length) @@ -346,7 +346,7 @@

      Method Detail

      • read

        -
        int read​(byte[] target,
        +
        int read​(byte[] buffer,
                  int offset,
                  int length)
           throws IOException
        @@ -358,7 +358,7 @@

        read

        Specified by:
        read in interface DataReader
        Parameters:
        -
        target - A target array into which data should be written.
        +
        buffer - A target array into which data should be written.
        offset - The offset into the target array at which to write.
        length - The maximum number of bytes to read from the input.
        Returns:
        diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/ExtractorUtil.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/ExtractorUtil.html index b8977b5a6f8..a1fe6a8ec45 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/ExtractorUtil.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/ExtractorUtil.html @@ -25,7 +25,7 @@ catch(err) { } //--> -var data = {"i0":9,"i1":9,"i2":9,"i3":9}; +var data = {"i0":9,"i1":9,"i2":9,"i3":9,"i4":9}; var tabs = {65535:["t0","All Methods"],1:["t1","Static Methods"],8:["t4","Concrete Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -153,6 +153,14 @@

        Method Summary

        Description +static void +checkContainerInput​(boolean expression, + String message) + +
        If expression is false, throws a container malformed ParserException with the given message.
        + + + static boolean peekFullyQuietly​(ExtractorInput input, byte[] output, @@ -163,7 +171,7 @@

        Method Summary

        Peeks data from input, respecting allowEndOfInput.
        - + static int peekToLength​(ExtractorInput input, byte[] target, @@ -174,7 +182,7 @@

        Method Summary

        input if there was less than length bytes left.
  • - + static boolean readFullyQuietly​(ExtractorInput input, byte[] output, @@ -186,7 +194,7 @@

    Method Summary

    having fully satisfied the read. - + static boolean skipFullyQuietly​(ExtractorInput input, int length) @@ -220,6 +228,24 @@

    Methods inherited from class java.lang. + + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/ForwardingExtractorInput.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/ForwardingExtractorInput.html index bf238225813..033e4a1b7f8 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/ForwardingExtractorInput.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/ForwardingExtractorInput.html @@ -245,7 +245,7 @@

    Method Summary

    int -read​(byte[] target, +read​(byte[] buffer, int offset, int length) @@ -358,7 +358,7 @@

    Method Detail

    • read

      -
      public int read​(byte[] target,
      +
      public int read​(byte[] buffer,
                       int offset,
                       int length)
                throws IOException
      @@ -373,7 +373,7 @@

      read

      Specified by:
      read in interface ExtractorInput
      Parameters:
      -
      target - A target array into which data should be written.
      +
      buffer - A target array into which data should be written.
      offset - The offset into the target array at which to write.
      length - The maximum number of bytes to read from the input.
      Returns:
      diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/GaplessInfoHolder.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/GaplessInfoHolder.html index ae68d031310..e34761a99a9 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/GaplessInfoHolder.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/GaplessInfoHolder.html @@ -156,16 +156,14 @@

      Field Summary

      int encoderDelay -
      The number of samples to trim from the start of the decoded audio stream, or - Format.NO_VALUE if not set.
      +
      The number of samples to trim from the start of the decoded audio stream, or Format.NO_VALUE if not set.
      int encoderPadding -
      The number of samples to trim from the end of the decoded audio stream, or - Format.NO_VALUE if not set.
      +
      The number of samples to trim from the end of the decoded audio stream, or Format.NO_VALUE if not set.
      @@ -261,8 +259,7 @@

      Field Detail

    • encoderDelay

      public int encoderDelay
      -
      The number of samples to trim from the start of the decoded audio stream, or - Format.NO_VALUE if not set.
      +
      The number of samples to trim from the start of the decoded audio stream, or Format.NO_VALUE if not set.
    @@ -272,8 +269,7 @@

    encoderDelay

  • encoderPadding

    public int encoderPadding
    -
    +
    The number of samples to trim from the end of the decoded audio stream, or Format.NO_VALUE if not set.
  • diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/TrackOutput.CryptoData.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/TrackOutput.CryptoData.html index 2da524d3932..b91d7d0a204 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/TrackOutput.CryptoData.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/TrackOutput.CryptoData.html @@ -160,8 +160,7 @@

    Field Summary

    int clearBlocks -
    The number of clear blocks in the encryption pattern, 0 if pattern encryption does not - apply.
    +
    The number of clear blocks in the encryption pattern, 0 if pattern encryption does not apply.
    @@ -301,8 +300,7 @@

    encryptedBlocks

  • clearBlocks

    public final int clearBlocks
    -
    The number of clear blocks in the encryption pattern, 0 if pattern encryption does not - apply.
    +
    The number of clear blocks in the encryption pattern, 0 if pattern encryption does not apply.
  • diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/TrackOutput.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/TrackOutput.html index 01e885ca99f..4d059a1a830 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/TrackOutput.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/TrackOutput.html @@ -269,7 +269,7 @@

    Method Summary

    int flags, int size, int offset, - TrackOutput.CryptoData encryptionData)
    + TrackOutput.CryptoData cryptoData)
    Called when metadata associated with a sample has been extracted from the stream.
    @@ -477,7 +477,7 @@

    sampleMetadata

    int size, int offset, @Nullable - TrackOutput.CryptoData encryptionData) + TrackOutput.CryptoData cryptoData)
    Called when metadata associated with a sample has been extracted from the stream.

    The corresponding sample data will have already been passed to the output via calls to @@ -490,7 +490,7 @@

    sampleMetadata

    offset - The number of bytes that have been passed to sampleData(DataReader, int, boolean) or sampleData(ParsableByteArray, int) since the last byte belonging to the sample whose metadata is being passed.
    -
    encryptionData - The encryption data required to decrypt the sample. May be null.
    +
    cryptoData - The encryption data required to decrypt the sample. May be null.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/VorbisUtil.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/VorbisUtil.html index 3156c09b105..3b577bb31a1 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/VorbisUtil.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/VorbisUtil.html @@ -277,8 +277,8 @@

    iLog

    Returns:
    ilog(x)
    See Also:
    -
    - Vorbis spec
    +
    Vorbis + spec
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/amr/AmrExtractor.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/amr/AmrExtractor.html index 5b494b4ec82..f288a7c4e8d 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/amr/AmrExtractor.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/amr/AmrExtractor.html @@ -259,7 +259,7 @@

    Method Summary

    void -init​(ExtractorOutput extractorOutput) +init​(ExtractorOutput output)
    Initializes the extractor with an ExtractorOutput.
    @@ -419,14 +419,14 @@

    sniff

    @@ -478,8 +478,8 @@

    seek

    long timeUs)
    Description copied from interface: Extractor
    Notifies the extractor that a seek has occurred. -

    - Following a call to this method, the ExtractorInput passed to the next invocation of + +

    Following a call to this method, the ExtractorInput passed to the next invocation of Extractor.read(ExtractorInput, PositionHolder) is required to provide data starting from position in the stream. Valid random access positions are the start of the stream and positions that can be obtained from any SeekMap passed to the ExtractorOutput.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/flac/FlacExtractor.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/flac/FlacExtractor.html index 916ac9db27a..f3affabfd94 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/flac/FlacExtractor.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/flac/FlacExtractor.html @@ -483,8 +483,8 @@

    seek

    long timeUs)
    Description copied from interface: Extractor
    Notifies the extractor that a seek has occurred. -

    - Following a call to this method, the ExtractorInput passed to the next invocation of + +

    Following a call to this method, the ExtractorInput passed to the next invocation of Extractor.read(ExtractorInput, PositionHolder) is required to provide data starting from position in the stream. Valid random access positions are the start of the stream and positions that can be obtained from any SeekMap passed to the ExtractorOutput.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/flv/FlvExtractor.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/flv/FlvExtractor.html index 37ed14e6dcf..45e72516a59 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/flv/FlvExtractor.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/flv/FlvExtractor.html @@ -381,8 +381,8 @@

    seek

    long timeUs)
    Description copied from interface: Extractor
    Notifies the extractor that a seek has occurred. -

    - Following a call to this method, the ExtractorInput passed to the next invocation of + +

    Following a call to this method, the ExtractorInput passed to the next invocation of Extractor.read(ExtractorInput, PositionHolder) is required to provide data starting from position in the stream. Valid random access positions are the start of the stream and positions that can be obtained from any SeekMap passed to the ExtractorOutput.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/jpeg/JpegExtractor.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/jpeg/JpegExtractor.html index 8dc5a790210..31bbfa20b46 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/jpeg/JpegExtractor.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/jpeg/JpegExtractor.html @@ -385,8 +385,8 @@

    seek

    long timeUs)
    Description copied from interface: Extractor
    Notifies the extractor that a seek has occurred. -

    - Following a call to this method, the ExtractorInput passed to the next invocation of + +

    Following a call to this method, the ExtractorInput passed to the next invocation of Extractor.read(ExtractorInput, PositionHolder) is required to provide data starting from position in the stream. Valid random access positions are the start of the stream and positions that can be obtained from any SeekMap passed to the ExtractorOutput.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/mkv/EbmlProcessor.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/mkv/EbmlProcessor.html index 3be56f7ce62..8ecb69e1e46 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/mkv/EbmlProcessor.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/mkv/EbmlProcessor.html @@ -450,12 +450,12 @@

    startMasterElement

    long contentSize) throws ParserException
    Called when the start of a master element is encountered. -

    - Following events should be considered as taking place within this element until a matching call - to endMasterElement(int) is made. -

    - Note that it is possible for another master element of the same element ID to be nested within - itself.

    + +

    Following events should be considered as taking place within this element until a matching + call to endMasterElement(int) is made. + +

    Note that it is possible for another master element of the same element ID to be nested + within itself.

    Parameters:
    id - The element ID.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.html index 1c696bef1be..c2710b8d648 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.html @@ -411,8 +411,8 @@

    FACTORY

    FLAG_DISABLE_SEEK_FOR_CUES

    public static final int FLAG_DISABLE_SEEK_FOR_CUES
    Flag to disable seeking for cues. -

    - Normally (i.e. when this flag is not set) the extractor will seek to the cues element if its + +

    Normally (i.e. when this flag is not set) the extractor will seek to the cues element if its position is specified in the seek head and if it's after the first cluster. Setting this flag disables seeking to the cues element. If the cues element is after the first cluster then the media is treated as being unseekable.

    @@ -515,8 +515,8 @@

    seek

    long timeUs)
    Description copied from interface: Extractor
    Notifies the extractor that a seek has occurred. -

    - Following a call to this method, the ExtractorInput passed to the next invocation of + +

    Following a call to this method, the ExtractorInput passed to the next invocation of Extractor.read(ExtractorInput, PositionHolder) is required to provide data starting from position in the stream. Valid random access positions are the start of the stream and positions that can be obtained from any SeekMap passed to the ExtractorOutput.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/mp3/Mp3Extractor.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/mp3/Mp3Extractor.html index c2f1f0f75d6..d666de88609 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/mp3/Mp3Extractor.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/mp3/Mp3Extractor.html @@ -452,8 +452,7 @@

    Mp3Extractor

    Parameters:
    flags - Flags that control the extractor's behavior.
    -
    forcedFirstSampleTimestampUs - A timestamp to force for the first sample, or - C.TIME_UNSET if forcing is not required.
    +
    forcedFirstSampleTimestampUs - A timestamp to force for the first sample, or C.TIME_UNSET if forcing is not required.
    @@ -520,8 +519,8 @@

    seek

    long timeUs)
    Description copied from interface: Extractor
    Notifies the extractor that a seek has occurred. -

    - Following a call to this method, the ExtractorInput passed to the next invocation of + +

    Following a call to this method, the ExtractorInput passed to the next invocation of Extractor.read(ExtractorInput, PositionHolder) is required to provide data starting from position in the stream. Valid random access positions are the start of the stream and positions that can be obtained from any SeekMap passed to the ExtractorOutput.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.html index f3656ae3427..82ecce52633 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.html @@ -387,8 +387,8 @@

    FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME

    Flag to work around an issue in some video streams where every frame is marked as a sync frame. The workaround overrides the sync frame flags in the stream, forcing them to false except for the first sample in each segment. -

    - This flag does nothing if the stream is not a video stream.

    + +

    This flag does nothing if the stream is not a video stream.

    See Also:
    Constant Field Values
    @@ -625,8 +625,8 @@

    seek

    long timeUs)
    Description copied from interface: Extractor
    Notifies the extractor that a seek has occurred. -

    - Following a call to this method, the ExtractorInput passed to the next invocation of + +

    Following a call to this method, the ExtractorInput passed to the next invocation of Extractor.read(ExtractorInput, PositionHolder) is required to provide data starting from position in the stream. Valid random access positions are the start of the stream and positions that can be obtained from any SeekMap passed to the ExtractorOutput.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.html index 02a15a9a2bf..1fcd5f502c6 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.html @@ -520,8 +520,8 @@

    seek

    long timeUs)
    Description copied from interface: Extractor
    Notifies the extractor that a seek has occurred. -

    - Following a call to this method, the ExtractorInput passed to the next invocation of + +

    Following a call to this method, the ExtractorInput passed to the next invocation of Extractor.read(ExtractorInput, PositionHolder) is required to provide data starting from position in the stream. Valid random access positions are the start of the stream and positions that can be obtained from any SeekMap passed to the ExtractorOutput.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/mp4/PsshAtomUtil.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/mp4/PsshAtomUtil.html index 404a363bcc0..cb056d2749c 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/mp4/PsshAtomUtil.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/mp4/PsshAtomUtil.html @@ -307,8 +307,8 @@

    parseUuid

    parseVersion

    public static int parseVersion​(byte[] atom)
    Parses the version from a PSSH atom. Version 0 and 1 PSSH atoms are supported. -

    - The version is only parsed if the data is a valid PSSH atom.

    + +

    The version is only parsed if the data is a valid PSSH atom.

    Parameters:
    atom - The atom to parse.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/ogg/OggExtractor.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/ogg/OggExtractor.html index 945dfd89081..7ce17f418bc 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/ogg/OggExtractor.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/ogg/OggExtractor.html @@ -381,8 +381,8 @@

    seek

    long timeUs)
    Description copied from interface: Extractor
    Notifies the extractor that a seek has occurred. -

    - Following a call to this method, the ExtractorInput passed to the next invocation of + +

    Following a call to this method, the ExtractorInput passed to the next invocation of Extractor.read(ExtractorInput, PositionHolder) is required to provide data starting from position in the stream. Valid random access positions are the start of the stream and positions that can be obtained from any SeekMap passed to the ExtractorOutput.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/rawcc/RawCcExtractor.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/rawcc/RawCcExtractor.html index 3d44f0b9146..5a902b3a462 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/rawcc/RawCcExtractor.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/rawcc/RawCcExtractor.html @@ -384,8 +384,8 @@

    seek

    long timeUs)
    Description copied from interface: Extractor
    Notifies the extractor that a seek has occurred. -

    - Following a call to this method, the ExtractorInput passed to the next invocation of + +

    Following a call to this method, the ExtractorInput passed to the next invocation of Extractor.read(ExtractorInput, PositionHolder) is required to provide data starting from position in the stream. Valid random access positions are the start of the stream and positions that can be obtained from any SeekMap passed to the ExtractorOutput.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/Ac3Extractor.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/Ac3Extractor.html index 0a171ac125e..97d0748fb59 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/Ac3Extractor.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/Ac3Extractor.html @@ -384,8 +384,8 @@

    seek

    long timeUs)
    Description copied from interface: Extractor
    Notifies the extractor that a seek has occurred. -

    - Following a call to this method, the ExtractorInput passed to the next invocation of + +

    Following a call to this method, the ExtractorInput passed to the next invocation of Extractor.read(ExtractorInput, PositionHolder) is required to provide data starting from position in the stream. Valid random access positions are the start of the stream and positions that can be obtained from any SeekMap passed to the ExtractorOutput.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/Ac3Reader.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/Ac3Reader.html index f144bdca371..c7ce01df5aa 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/Ac3Reader.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/Ac3Reader.html @@ -196,7 +196,7 @@

    Method Summary

    void createTracks​(ExtractorOutput extractorOutput, - TsPayloadReader.TrackIdGenerator generator) + TsPayloadReader.TrackIdGenerator idGenerator)
    Initializes the reader by providing outputs and ids for the tracks.
    @@ -304,7 +304,7 @@

    seek

  • createTracks

    public void createTracks​(ExtractorOutput extractorOutput,
    -                         TsPayloadReader.TrackIdGenerator generator)
    + TsPayloadReader.TrackIdGenerator idGenerator)
    Description copied from interface: ElementaryStreamReader
    Initializes the reader by providing outputs and ids for the tracks.
    @@ -312,7 +312,7 @@

    createTracks

    createTracks in interface ElementaryStreamReader
    Parameters:
    extractorOutput - The ExtractorOutput that receives the extracted data.
    -
    generator - A TsPayloadReader.TrackIdGenerator that generates unique track ids for the +
    idGenerator - A TsPayloadReader.TrackIdGenerator that generates unique track ids for the TrackOutputs.
  • diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/Ac4Extractor.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/Ac4Extractor.html index 4d7b50c62fc..1c131e1269d 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/Ac4Extractor.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/Ac4Extractor.html @@ -384,8 +384,8 @@

    seek

    long timeUs)
    Description copied from interface: Extractor
    Notifies the extractor that a seek has occurred. -

    - Following a call to this method, the ExtractorInput passed to the next invocation of + +

    Following a call to this method, the ExtractorInput passed to the next invocation of Extractor.read(ExtractorInput, PositionHolder) is required to provide data starting from position in the stream. Valid random access positions are the start of the stream and positions that can be obtained from any SeekMap passed to the ExtractorOutput.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/Ac4Reader.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/Ac4Reader.html index 78d1ff221a8..53bb6b67791 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/Ac4Reader.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/Ac4Reader.html @@ -196,7 +196,7 @@

    Method Summary

    void createTracks​(ExtractorOutput extractorOutput, - TsPayloadReader.TrackIdGenerator generator) + TsPayloadReader.TrackIdGenerator idGenerator)
    Initializes the reader by providing outputs and ids for the tracks.
    @@ -304,7 +304,7 @@

    seek

  • createTracks

    public void createTracks​(ExtractorOutput extractorOutput,
    -                         TsPayloadReader.TrackIdGenerator generator)
    + TsPayloadReader.TrackIdGenerator idGenerator)
    Description copied from interface: ElementaryStreamReader
    Initializes the reader by providing outputs and ids for the tracks.
    @@ -312,7 +312,7 @@

    createTracks

    createTracks in interface ElementaryStreamReader
    Parameters:
    extractorOutput - The ExtractorOutput that receives the extracted data.
    -
    generator - A TsPayloadReader.TrackIdGenerator that generates unique track ids for the +
    idGenerator - A TsPayloadReader.TrackIdGenerator that generates unique track ids for the TrackOutputs.
  • diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/AdtsExtractor.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/AdtsExtractor.html index 98bd365c205..2fe8201fd45 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/AdtsExtractor.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/AdtsExtractor.html @@ -446,8 +446,8 @@

    seek

    long timeUs)
    Description copied from interface: Extractor
    Notifies the extractor that a seek has occurred. -

    - Following a call to this method, the ExtractorInput passed to the next invocation of + +

    Following a call to this method, the ExtractorInput passed to the next invocation of Extractor.read(ExtractorInput, PositionHolder) is required to provide data starting from position in the stream. Valid random access positions are the start of the stream and positions that can be obtained from any SeekMap passed to the ExtractorOutput.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/DefaultTsPayloadReaderFactory.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/DefaultTsPayloadReaderFactory.html index 89aa3c3e941..16413430707 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/DefaultTsPayloadReaderFactory.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/DefaultTsPayloadReaderFactory.html @@ -479,11 +479,10 @@

    DefaultTsPayloadReaderFactory

    flags - A combination of FLAG_* values that control the behavior of the created readers.
    closedCaptionFormats - Formats to be exposed by payload readers for streams with - embedded closed captions when no caption service descriptors are provided. If - FLAG_OVERRIDE_CAPTION_DESCRIPTORS is set, closedCaptionFormats overrides - any descriptor information. If not set, and closedCaptionFormats is empty, a - closed caption track with Format.accessibilityChannel Format.NO_VALUE will - be exposed.
    + embedded closed captions when no caption service descriptors are provided. If FLAG_OVERRIDE_CAPTION_DESCRIPTORS is set, closedCaptionFormats overrides any + descriptor information. If not set, and closedCaptionFormats is empty, a closed + caption track with Format.accessibilityChannel Format.NO_VALUE will be + exposed.
    @@ -506,8 +505,8 @@

    createInitialPayloadReaders

    public SparseArray<TsPayloadReader> createInitialPayloadReaders()
    Description copied from interface: TsPayloadReader.Factory
    Returns the initial mapping from PIDs to payload readers. -

    - This method allows the injection of payload readers for reserved PIDs, excluding PID 0.

    + +

    This method allows the injection of payload readers for reserved PIDs, excluding PID 0.

    Specified by:
    createInitialPayloadReaders in interface TsPayloadReader.Factory
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/PsExtractor.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/PsExtractor.html index b34d6d87e54..f5d7d303040 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/PsExtractor.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/PsExtractor.html @@ -484,8 +484,8 @@

    seek

    long timeUs)
    Description copied from interface: Extractor
    Notifies the extractor that a seek has occurred. -

    - Following a call to this method, the ExtractorInput passed to the next invocation of + +

    Following a call to this method, the ExtractorInput passed to the next invocation of Extractor.read(ExtractorInput, PositionHolder) is required to provide data starting from position in the stream. Valid random access positions are the start of the stream and positions that can be obtained from any SeekMap passed to the ExtractorOutput.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/TsExtractor.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/TsExtractor.html index 2805e8dae1c..237a09b1e34 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/TsExtractor.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/TsExtractor.html @@ -934,8 +934,8 @@

    seek

    long timeUs)
    Description copied from interface: Extractor
    Notifies the extractor that a seek has occurred. -

    - Following a call to this method, the ExtractorInput passed to the next invocation of + +

    Following a call to this method, the ExtractorInput passed to the next invocation of Extractor.read(ExtractorInput, PositionHolder) is required to provide data starting from position in the stream. Valid random access positions are the start of the stream and positions that can be obtained from any SeekMap passed to the ExtractorOutput.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/TsPayloadReader.Factory.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/TsPayloadReader.Factory.html index 182366731ad..693710f1f6d 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/TsPayloadReader.Factory.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/TsPayloadReader.Factory.html @@ -191,8 +191,8 @@

    Method Detail

    createInitialPayloadReaders

    SparseArray<TsPayloadReader> createInitialPayloadReaders()
    Returns the initial mapping from PIDs to payload readers. -

    - This method allows the injection of payload readers for reserved PIDs, excluding PID 0.

    + +

    This method allows the injection of payload readers for reserved PIDs, excluding PID 0.

    Returns:
    A SparseArray that maps PIDs to payload readers.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/TsPayloadReader.TrackIdGenerator.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/TsPayloadReader.TrackIdGenerator.html index f61d0ad210c..9c18aeae45f 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/TsPayloadReader.TrackIdGenerator.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/ts/TsPayloadReader.TrackIdGenerator.html @@ -299,8 +299,7 @@

    getFormatId

    Returns:
    The last generated format id, with the format "programNumber/trackId". If no - programNumber was provided, the trackId alone is used as - format id.
    + programNumber was provided, the trackId alone is used as format id.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/extractor/wav/WavExtractor.html b/docs/doc/reference/com/google/android/exoplayer2/extractor/wav/WavExtractor.html index 9ada74d22cf..f20854b7881 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/extractor/wav/WavExtractor.html +++ b/docs/doc/reference/com/google/android/exoplayer2/extractor/wav/WavExtractor.html @@ -381,8 +381,8 @@

    seek

    long timeUs)
    Description copied from interface: Extractor
    Notifies the extractor that a seek has occurred. -

    - Following a call to this method, the ExtractorInput passed to the next invocation of + +

    Following a call to this method, the ExtractorInput passed to the next invocation of Extractor.read(ExtractorInput, PositionHolder) is required to provide data starting from position in the stream. Valid random access positions are the start of the stream and positions that can be obtained from any SeekMap passed to the ExtractorOutput.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/mediacodec/MediaCodecAdapter.html b/docs/doc/reference/com/google/android/exoplayer2/mediacodec/MediaCodecAdapter.html index bc9babb9053..0487ffd65e9 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/mediacodec/MediaCodecAdapter.html +++ b/docs/doc/reference/com/google/android/exoplayer2/mediacodec/MediaCodecAdapter.html @@ -25,7 +25,7 @@ catch(err) { } //--> -var data = {"i0":6,"i1":6,"i2":6,"i3":6,"i4":6,"i5":6,"i6":6,"i7":6,"i8":6,"i9":6,"i10":6,"i11":6,"i12":6,"i13":6,"i14":6}; +var data = {"i0":6,"i1":6,"i2":6,"i3":6,"i4":6,"i5":6,"i6":6,"i7":6,"i8":6,"i9":6,"i10":6,"i11":6,"i12":6,"i13":6,"i14":6,"i15":6}; var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],4:["t3","Abstract Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -232,6 +232,13 @@

    Method Summary

    +boolean +needsReconfiguration() + +
    Whether the adapter needs to be reconfigured before it is used.
    + + + void queueInputBuffer​(int index, int offset, @@ -242,7 +249,7 @@

    Method Summary

    Submit an input buffer for decoding.
    - + void queueSecureInputBuffer​(int index, int offset, @@ -253,14 +260,14 @@

    Method Summary

    Submit an input buffer that is potentially encrypted for decoding.
    - + void release()
    Releases the adapter and the underlying MediaCodec.
    - + void releaseOutputBuffer​(int index, boolean render) @@ -268,7 +275,7 @@

    Method Summary

    Returns the buffer to the MediaCodec.
    - + void releaseOutputBuffer​(int index, long renderTimeStampNs) @@ -277,7 +284,7 @@

    Method Summary

    it on the output surface. - + void setOnFrameRenderedListener​(MediaCodecAdapter.OnFrameRenderedListener listener, Handler handler) @@ -285,21 +292,21 @@

    Method Summary

    Registers a callback to be invoked when an output frame is rendered on the output surface.
    - + void setOutputSurface​(Surface surface)
    Dynamically sets the output surface of a MediaCodec.
    - + void setParameters​(Bundle params)
    Communicate additional parameter changes to the MediaCodec instance.
    - + void setVideoScalingMode​(int scalingMode) @@ -545,7 +552,7 @@

    setParameters

    -
      +
      • setVideoScalingMode

        void setVideoScalingMode​(@VideoScalingMode
        @@ -557,6 +564,16 @@ 

        setVideoScalingMode

    + + + +
      +
    • +

      needsReconfiguration

      +
      boolean needsReconfiguration()
      +
      Whether the adapter needs to be reconfigured before it is used.
      +
    • +
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.html b/docs/doc/reference/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.html index 5dddd729cca..5fc130e4f15 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.html +++ b/docs/doc/reference/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.html @@ -25,7 +25,7 @@ catch(err) { } //--> -var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":6,"i15":6,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10,"i21":10,"i22":10,"i23":10,"i24":10,"i25":10,"i26":10,"i27":10,"i28":10,"i29":10,"i30":10,"i31":10,"i32":10,"i33":10,"i34":10,"i35":10,"i36":10,"i37":10,"i38":6,"i39":10,"i40":10,"i41":10,"i42":10,"i43":10,"i44":10,"i45":10,"i46":10,"i47":10,"i48":10,"i49":10,"i50":10,"i51":6,"i52":9,"i53":10,"i54":10,"i55":10}; +var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":6,"i14":6,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10,"i21":10,"i22":10,"i23":10,"i24":10,"i25":10,"i26":10,"i27":10,"i28":10,"i29":10,"i30":10,"i31":10,"i32":10,"i33":10,"i34":10,"i35":10,"i36":6,"i37":10,"i38":10,"i39":10,"i40":10,"i41":10,"i42":10,"i43":10,"i44":10,"i45":10,"i46":10,"i47":10,"i48":10,"i49":6,"i50":9,"i51":10,"i52":10,"i53":10}; var tabs = {65535:["t0","All Methods"],1:["t1","Static Methods"],2:["t2","Instance Methods"],4:["t3","Abstract Methods"],8:["t4","Concrete Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -305,44 +305,36 @@

    Method Summary

    void -experimentalSetSkipAndContinueIfSampleTooLarge​(boolean enabled) - -
    Enables skipping and continuing playback from the next key frame if a sample is encountered - that's too large to fit into one of the decoder's input buffers.
    - - - -void experimentalSetSynchronizeCodecInteractionsWithQueueingEnabled​(boolean enabled)
    Enables synchronizing codec interactions with asynchronous buffer queueing.
    - + protected boolean flushOrReinitializeCodec()
    Flushes the codec.
    - + protected boolean flushOrReleaseCodec()
    Flushes the codec.
    - + protected MediaCodecAdapter getCodec()   - + protected MediaCodecInfo getCodecInfo()   - + protected boolean getCodecNeedsEosPropagation() @@ -350,14 +342,14 @@

    Method Summary

    rather than by using an end-of-stream buffer queued to the codec. - + protected float getCodecOperatingRate()
    Returns the operating rate used by the current codec
    - + protected float getCodecOperatingRateV23​(float targetPlaybackSpeed, Format format, @@ -367,12 +359,12 @@

    Method Summary

    Format and set of possible stream formats. - + protected MediaFormat getCodecOutputMediaFormat()   - + protected abstract List<MediaCodecInfo> getDecoderInfos​(MediaCodecSelector mediaCodecSelector, Format format, @@ -381,7 +373,7 @@

    Method Summary

    Returns a list of decoders that can decode media in the specified format, in priority order.
    - + protected abstract MediaCodecAdapter.Configuration getMediaCodecConfiguration​(MediaCodecInfo codecInfo, Format format, @@ -392,7 +384,7 @@

    Method Summary

    MediaCodec to decode the given Format for a playback. - + protected long getOutputStreamOffsetUs() @@ -400,55 +392,47 @@

    Method Summary

    boolean, Format)
    to get the playback position with respect to the media. - + protected float getPlaybackSpeed()
    Returns the current playback speed, as set by setPlaybackSpeed(float, float).
    - + protected void handleInputBufferSupplementalData​(DecoderInputBuffer buffer)
    Handles supplemental data associated with an input buffer.
    - + boolean isEnded()
    Whether the renderer is ready for the ExoPlayer instance to transition to Player.STATE_ENDED.
    - + boolean isReady()
    Whether the renderer is able to immediately render media from the current position.
    - -protected boolean -legacyKeepAvailableCodecInfosWithoutCodec() - -
    Returns whether to keep available codec infos when the codec hasn't been initialized, which is - the behavior before a bug fix.
    - - - + protected void maybeInitCodecOrBypass()   - + protected void onCodecError​(Exception codecError)
    Called when a codec error has occurred.
    - + protected void onCodecInitialized​(String name, long initializedTimestampMs, @@ -457,21 +441,21 @@

    Method Summary

    Called when a MediaCodec has been created and configured.
    - + protected void onCodecReleased​(String name)
    Called when a MediaCodec has been released.
    - + protected void onDisabled()
    Called when the renderer is disabled.
    - + protected void onEnabled​(boolean joining, boolean mayRenderStartOfStream) @@ -479,14 +463,14 @@

    Method Summary

    Called when the renderer is enabled.
    - + protected DecoderReuseEvaluation onInputFormatChanged​(FormatHolder formatHolder)
    Called when a new Format is read from the upstream MediaPeriod.
    - + protected void onOutputFormatChanged​(Format format, MediaFormat mediaFormat) @@ -494,7 +478,7 @@

    Method Summary

    Called when one of the output formats changes.
    - + protected void onPositionReset​(long positionUs, boolean joining) @@ -502,49 +486,49 @@

    Method Summary

    Called when the position is reset.
    - + protected void onProcessedOutputBuffer​(long presentationTimeUs)
    Called when an output buffer is successfully processed.
    - + protected void onProcessedStreamChange()
    Called after the last output buffer before a stream change has been processed.
    - + protected void onQueueInputBuffer​(DecoderInputBuffer buffer)
    Called immediately before an input buffer is queued into the codec.
    - + protected void onReset()
    Called when the renderer is reset.
    - + protected void onStarted()
    Called when the renderer is started.
    - + protected void onStopped()
    Called when the renderer is stopped.
    - + protected void onStreamChanged​(Format[] formats, long startPositionUs, @@ -553,7 +537,7 @@

    Method Summary

    Called when the renderer's stream has changed.
    - + protected abstract boolean processOutputBuffer​(long positionUs, long elapsedRealtimeUs, @@ -570,12 +554,12 @@

    Method Summary

    Processes an output media buffer.
    - + protected void releaseCodec()   - + void render​(long positionUs, long elapsedRealtimeUs) @@ -583,28 +567,28 @@

    Method Summary

    Incrementally renders the SampleStream.
    - + protected void renderToEndOfStream()
    Incrementally renders any remaining output.
    - + protected void resetCodecStateForFlush()
    Resets the renderer internal state after a codec flush.
    - + protected void resetCodecStateForRelease()
    Resets the renderer internal state after a codec release.
    - + protected void setPendingOutputEndOfStream() @@ -612,14 +596,14 @@

    Method Summary

    render. - + protected void setPendingPlaybackException​(ExoPlaybackException exception)
    Sets an exception to be re-thrown by render.
    - + void setPlaybackSpeed​(float currentPlaybackSpeed, float targetPlaybackSpeed) @@ -627,7 +611,7 @@

    Method Summary

    Indicates the playback speed to this renderer.
    - + void setRenderTimeLimitMs​(long renderTimeLimitMs) @@ -635,26 +619,26 @@

    Method Summary

    filling the decoder. - + protected boolean shouldInitCodec​(MediaCodecInfo codecInfo)   - + protected boolean shouldUseBypass​(Format format)
    Returns whether buffers in the input format can be processed without a codec.
    - + int supportsFormat​(Format format)
    Returns the extent to which the Renderer supports a given format.
    - + protected abstract int supportsFormat​(MediaCodecSelector mediaCodecSelector, Format format) @@ -662,14 +646,14 @@

    Method Summary

    Returns the RendererCapabilities.Capabilities for the given Format.
    - + protected static boolean supportsFormatDrm​(Format format)
    Returns whether this renderer supports the given Format's DRM scheme.
    - + int supportsMixedMimeTypeAdaptation() @@ -677,7 +661,7 @@

    Method Summary

    that have different MIME types. - + protected boolean updateCodecOperatingRate() @@ -685,7 +669,7 @@

    Method Summary

    previously set operating rate needs to be cleared. - + protected void updateOutputFormatForTime​(long presentationTimeUs) @@ -698,7 +682,7 @@

    Method Summary

    Methods inherited from class com.google.android.exoplayer2.BaseRenderer

    -createRendererException, createRendererException, disable, enable, getCapabilities, getConfiguration, getFormatHolder, getIndex, getLastResetPositionUs, getMediaClock, getReadingPositionUs, getState, getStream, getStreamFormats, getTrackType, handleMessage, hasReadStreamToEnd, isCurrentStreamFinal, isSourceReady, maybeThrowStreamError, readSource, replaceStream, reset, resetPosition, setCurrentStreamFinal, setIndex, skipSource, start, stop +createRendererException, createRendererException, disable, enable, getCapabilities, getConfiguration, getFormatHolder, getIndex, getLastResetPositionUs, getMediaClock, getReadingPositionUs, getState, getStream, getStreamFormats, getTrackType, handleMessage, hasReadStreamToEnd, isCurrentStreamFinal, isSourceReady, maybeThrowStreamError, readSource, replaceStream, reset, resetPosition, setCurrentStreamFinal, setIndex, skipSource, start, stop - - - -
      -
    • -

      experimentalSetSkipAndContinueIfSampleTooLarge

      -
      public void experimentalSetSkipAndContinueIfSampleTooLarge​(boolean enabled)
      -
      Enables skipping and continuing playback from the next key frame if a sample is encountered - that's too large to fit into one of the decoder's input buffers. When not enabled, playback - will fail in this case. - -

      This method is experimental, and will be renamed or removed in a future release. It should - only be called before the renderer is used.

      -
    • -
    @@ -1229,8 +1198,8 @@

    onDisabled

    protected void onDisabled()
    Description copied from class: BaseRenderer
    Called when the renderer is disabled. -

    - The default implementation is a no-op.

    + +

    The default implementation is a no-op.

    Overrides:
    onDisabled in class BaseRenderer
    @@ -1272,8 +1241,8 @@

    onStarted

    protected void onStarted()
    Description copied from class: BaseRenderer
    Called when the renderer is started. -

    - The default implementation is a no-op.

    + +

    The default implementation is a no-op.

    Overrides:
    onStarted in class BaseRenderer
    @@ -1416,8 +1385,8 @@

    onCodecInitialized

    long initializedTimestampMs, long initializationDurationMs)
    Called when a MediaCodec has been created and configured. -

    - The default implementation is a no-op.

    + +

    The default implementation is a no-op.

    Parameters:
    name - The name of the codec that was initialized.
    @@ -1481,17 +1450,6 @@

    onInputFormatChanged

    - - - -
      -
    • -

      legacyKeepAvailableCodecInfosWithoutCodec

      -
      protected boolean legacyKeepAvailableCodecInfosWithoutCodec()
      -
      Returns whether to keep available codec infos when the codec hasn't been initialized, which is - the behavior before a bug fix. See also [Internal: b/162837741].
      -
    • -
    @@ -1629,16 +1587,15 @@

    isReady

    public boolean isReady()
    Description copied from interface: Renderer
    Whether the renderer is able to immediately render media from the current position. -

    - If the renderer is in the Renderer.STATE_STARTED state then returning true indicates that the - renderer has everything that it needs to continue playback. Returning false indicates that + +

    If the renderer is in the Renderer.STATE_STARTED state then returning true indicates that + the renderer has everything that it needs to continue playback. Returning false indicates that the player should pause until the renderer is ready. -

    - If the renderer is in the Renderer.STATE_ENABLED state then returning true indicates that the - renderer is ready for playback to be started. Returning false indicates that it is not. -

    - This method may be called when the renderer is in the following states: - Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

    + +

    If the renderer is in the Renderer.STATE_ENABLED state then returning true indicates that + the renderer is ready for playback to be started. Returning false indicates that it is not. + +

    This method may be called when the renderer is in the following states: Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

    Returns:
    Whether the renderer is ready to render media.
    @@ -1778,8 +1735,8 @@

    renderToEndOfStream

    protected void renderToEndOfStream()
                                 throws ExoPlaybackException
    Incrementally renders any remaining output. -

    - The default implementation is a no-op.

    + +

    The default implementation is a no-op.

    Throws:
    ExoPlaybackException - Thrown if an error occurs rendering remaining output.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.DecoderQueryException.html b/docs/doc/reference/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.DecoderQueryException.html index 6093ba66525..964293772d5 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.DecoderQueryException.html +++ b/docs/doc/reference/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.DecoderQueryException.html @@ -144,8 +144,8 @@

    Class Media
    public static class MediaCodecUtil.DecoderQueryException
     extends Exception
    Thrown when an error occurs querying the device for its underlying media capabilities. -

    - Such failures are not expected in normal operation and are normally temporary (e.g. if the + +

    Such failures are not expected in normal operation and are normally temporary (e.g. if the mediaserver process has crashed and is yet to restart).

    See Also:
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/mediacodec/SynchronousMediaCodecAdapter.html b/docs/doc/reference/com/google/android/exoplayer2/mediacodec/SynchronousMediaCodecAdapter.html index fd33f3e7680..f967d4999e7 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/mediacodec/SynchronousMediaCodecAdapter.html +++ b/docs/doc/reference/com/google/android/exoplayer2/mediacodec/SynchronousMediaCodecAdapter.html @@ -25,7 +25,7 @@ catch(err) { } //--> -var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10}; +var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10}; var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -232,6 +232,13 @@

    Method Summary

    +boolean +needsReconfiguration() + +
    Whether the adapter needs to be reconfigured before it is used.
    + + + void queueInputBuffer​(int index, int offset, @@ -242,7 +249,7 @@

    Method Summary

    Submit an input buffer for decoding.
    - + void queueSecureInputBuffer​(int index, int offset, @@ -253,14 +260,14 @@

    Method Summary

    Submit an input buffer that is potentially encrypted for decoding.
    - + void release()
    Releases the adapter and the underlying MediaCodec.
    - + void releaseOutputBuffer​(int index, boolean render) @@ -268,7 +275,7 @@

    Method Summary

    Returns the buffer to the MediaCodec.
    - + void releaseOutputBuffer​(int index, long renderTimeStampNs) @@ -277,7 +284,7 @@

    Method Summary

    it on the output surface. - + void setOnFrameRenderedListener​(MediaCodecAdapter.OnFrameRenderedListener listener, Handler handler) @@ -285,21 +292,21 @@

    Method Summary

    Registers a callback to be invoked when an output frame is rendered on the output surface.
    - + void setOutputSurface​(Surface surface)
    Dynamically sets the output surface of a MediaCodec.
    - + void setParameters​(Bundle params)
    Communicate additional parameter changes to the MediaCodec instance.
    - + void setVideoScalingMode​(int scalingMode) @@ -330,6 +337,21 @@

    Methods inherited from class java.lang. + + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/metadata/MetadataInputBuffer.html b/docs/doc/reference/com/google/android/exoplayer2/metadata/MetadataInputBuffer.html index 65cc1d75bf1..af7bb84d43b 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/metadata/MetadataInputBuffer.html +++ b/docs/doc/reference/com/google/android/exoplayer2/metadata/MetadataInputBuffer.html @@ -177,8 +177,7 @@

    Field Summary

    long subsampleOffsetUs -
    An offset that must be added to the metadata's timestamps after it's been decoded, or - Format.OFFSET_SAMPLE_RELATIVE if DecoderInputBuffer.timeUs should be added.
    +
    An offset that must be added to the metadata's timestamps after it's been decoded, or Format.OFFSET_SAMPLE_RELATIVE if DecoderInputBuffer.timeUs should be added.
    @@ -264,8 +263,7 @@

    Field Detail

  • subsampleOffsetUs

    public long subsampleOffsetUs
    -
    An offset that must be added to the metadata's timestamps after it's been decoded, or - Format.OFFSET_SAMPLE_RELATIVE if DecoderInputBuffer.timeUs should be added.
    +
    An offset that must be added to the metadata's timestamps after it's been decoded, or Format.OFFSET_SAMPLE_RELATIVE if DecoderInputBuffer.timeUs should be added.
  • diff --git a/docs/doc/reference/com/google/android/exoplayer2/metadata/MetadataRenderer.html b/docs/doc/reference/com/google/android/exoplayer2/metadata/MetadataRenderer.html index 81a214399fc..35e653f10f6 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/metadata/MetadataRenderer.html +++ b/docs/doc/reference/com/google/android/exoplayer2/metadata/MetadataRenderer.html @@ -309,7 +309,7 @@

    Method Summary

    Methods inherited from class com.google.android.exoplayer2.BaseRenderer

    -createRendererException, createRendererException, disable, enable, getCapabilities, getConfiguration, getFormatHolder, getIndex, getLastResetPositionUs, getMediaClock, getReadingPositionUs, getState, getStream, getStreamFormats, getTrackType, handleMessage, hasReadStreamToEnd, isCurrentStreamFinal, isSourceReady, maybeThrowStreamError, onEnabled, onReset, onStarted, onStopped, readSource, replaceStream, reset, resetPosition, setCurrentStreamFinal, setIndex, skipSource, start, stop, supportsMixedMimeTypeAdaptation +createRendererException, createRendererException, disable, enable, getCapabilities, getConfiguration, getFormatHolder, getIndex, getLastResetPositionUs, getMediaClock, getReadingPositionUs, getState, getStream, getStreamFormats, getTrackType, handleMessage, hasReadStreamToEnd, isCurrentStreamFinal, isSourceReady, maybeThrowStreamError, onEnabled, onReset, onStarted, onStopped, readSource, replaceStream, reset, resetPosition, setCurrentStreamFinal, setIndex, skipSource, start, stop, supportsMixedMimeTypeAdaptation @@ -470,6 +477,26 @@

    PictureFrame

    Method Detail

    + + + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/metadata/flac/VorbisComment.html b/docs/doc/reference/com/google/android/exoplayer2/metadata/flac/VorbisComment.html index 21ae44893d1..86d3cb8d33b 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/metadata/flac/VorbisComment.html +++ b/docs/doc/reference/com/google/android/exoplayer2/metadata/flac/VorbisComment.html @@ -25,7 +25,7 @@ catch(err) { } //--> -var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10}; +var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10}; var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -256,11 +256,18 @@

    Method Summary

      +void +populateMediaMetadata​(MediaMetadata.Builder builder) + +
    Updates the MediaMetadata.Builder with the type specific values stored in this Entry.
    + + + String toString()   - + void writeToParcel​(Parcel dest, int flags) @@ -279,7 +286,7 @@

    Methods inherited from class java.lang.Metadata.Entry

    -getWrappedMetadataBytes, getWrappedMetadataFormat, populateMediaMetadata +getWrappedMetadataBytes, getWrappedMetadataFormat @@ -361,6 +368,26 @@

    VorbisComment

    Method Detail

    + + + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/metadata/scte35/SpliceInsertCommand.html b/docs/doc/reference/com/google/android/exoplayer2/metadata/scte35/SpliceInsertCommand.html index 0828707beee..85c42913011 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/metadata/scte35/SpliceInsertCommand.html +++ b/docs/doc/reference/com/google/android/exoplayer2/metadata/scte35/SpliceInsertCommand.html @@ -197,8 +197,7 @@

    Field Summary

    boolean autoReturn -
    If breakDurationUs is not C.TIME_UNSET, defines whether - breakDurationUs should be used to know when to return to the network feed.
    +
    If breakDurationUs is not C.TIME_UNSET, defines whether breakDurationUs should be used to know when to return to the network feed.
    @@ -226,8 +225,7 @@

    Field Summary

    List<SpliceInsertCommand.ComponentSplice> componentSpliceList -
    If programSpliceFlag is false, a non-empty list containing the - SpliceInsertCommand.ComponentSplices.
    +
    If programSpliceFlag is false, a non-empty list containing the SpliceInsertCommand.ComponentSplices.
    @@ -410,9 +408,7 @@

    programSpliceFlag

    spliceImmediateFlag

    public final boolean spliceImmediateFlag
    Whether splicing should be done at the nearest opportunity. If false, splicing should be done - at the moment indicated by programSplicePlaybackPositionUs or - SpliceInsertCommand.ComponentSplice.componentSplicePlaybackPositionUs, depending on - programSpliceFlag.
    + at the moment indicated by programSplicePlaybackPositionUs or SpliceInsertCommand.ComponentSplice.componentSplicePlaybackPositionUs, depending on programSpliceFlag. @@ -422,8 +418,7 @@

    spliceImmediateFlag

  • programSplicePts

    public final long programSplicePts
    -
    If programSpliceFlag is true, the PTS at which the program splice should occur. - C.TIME_UNSET otherwise.
    +
    If programSpliceFlag is true, the PTS at which the program splice should occur. C.TIME_UNSET otherwise.
  • @@ -443,8 +438,7 @@

    programSplicePlaybackPositionUs

  • componentSpliceList

    public final List<SpliceInsertCommand.ComponentSplice> componentSpliceList
    -
    If programSpliceFlag is false, a non-empty list containing the - SpliceInsertCommand.ComponentSplices. Otherwise, an empty list.
    +
    If programSpliceFlag is false, a non-empty list containing the SpliceInsertCommand.ComponentSplices. Otherwise, an empty list.
  • @@ -454,9 +448,7 @@

    componentSpliceList

  • autoReturn

    public final boolean autoReturn
    -
    If breakDurationUs is not C.TIME_UNSET, defines whether - breakDurationUs should be used to know when to return to the network feed. If - breakDurationUs is C.TIME_UNSET, the value is undefined.
    +
    If breakDurationUs is not C.TIME_UNSET, defines whether breakDurationUs should be used to know when to return to the network feed. If breakDurationUs is C.TIME_UNSET, the value is undefined.
  • diff --git a/docs/doc/reference/com/google/android/exoplayer2/metadata/scte35/SpliceScheduleCommand.Event.html b/docs/doc/reference/com/google/android/exoplayer2/metadata/scte35/SpliceScheduleCommand.Event.html index 2f55f5c58c1..d79e35774ed 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/metadata/scte35/SpliceScheduleCommand.Event.html +++ b/docs/doc/reference/com/google/android/exoplayer2/metadata/scte35/SpliceScheduleCommand.Event.html @@ -154,8 +154,7 @@

    Field Summary

    boolean
    autoReturn -
    If breakDurationUs is not C.TIME_UNSET, defines whether - breakDurationUs should be used to know when to return to the network feed.
    +
    If breakDurationUs is not C.TIME_UNSET, defines whether breakDurationUs should be used to know when to return to the network feed.
    @@ -184,8 +183,7 @@

    Field Summary

    List<SpliceScheduleCommand.ComponentSplice> componentSpliceList -
    If programSpliceFlag is false, a non-empty list containing the - SpliceScheduleCommand.ComponentSplices.
    +
    If programSpliceFlag is false, a non-empty list containing the SpliceScheduleCommand.ComponentSplices.
    @@ -326,8 +324,7 @@

    utcSpliceTime

  • componentSpliceList

    public final List<SpliceScheduleCommand.ComponentSplice> componentSpliceList
    -
    If programSpliceFlag is false, a non-empty list containing the - SpliceScheduleCommand.ComponentSplices. Otherwise, an empty list.
    +
    If programSpliceFlag is false, a non-empty list containing the SpliceScheduleCommand.ComponentSplices. Otherwise, an empty list.
  • @@ -337,9 +334,7 @@

    componentSpliceList

  • autoReturn

    public final boolean autoReturn
    -
    If breakDurationUs is not C.TIME_UNSET, defines whether - breakDurationUs should be used to know when to return to the network feed. If - breakDurationUs is C.TIME_UNSET, the value is undefined.
    +
    If breakDurationUs is not C.TIME_UNSET, defines whether breakDurationUs should be used to know when to return to the network feed. If breakDurationUs is C.TIME_UNSET, the value is undefined.
  • diff --git a/docs/doc/reference/com/google/android/exoplayer2/offline/DefaultDownloaderFactory.html b/docs/doc/reference/com/google/android/exoplayer2/offline/DefaultDownloaderFactory.html index fc91999988d..c03a3ae2529 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/offline/DefaultDownloaderFactory.html +++ b/docs/doc/reference/com/google/android/exoplayer2/offline/DefaultDownloaderFactory.html @@ -284,7 +284,7 @@

    createDownloader

    Specified by:
    createDownloader in interface DownloaderFactory
    Parameters:
    -
    request - The action.
    +
    request - The download request.
    Returns:
    The downloader.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/offline/DownloaderFactory.html b/docs/doc/reference/com/google/android/exoplayer2/offline/DownloaderFactory.html index 8b6b187b218..ac86bc015f2 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/offline/DownloaderFactory.html +++ b/docs/doc/reference/com/google/android/exoplayer2/offline/DownloaderFactory.html @@ -149,7 +149,7 @@

    Method Summary

    Downloader -createDownloader​(DownloadRequest action) +createDownloader​(DownloadRequest request)
    Creates a Downloader to perform the given DownloadRequest.
    @@ -177,11 +177,11 @@

    Method Detail

    - - - - diff --git a/docs/doc/reference/com/google/android/exoplayer2/package-summary.html b/docs/doc/reference/com/google/android/exoplayer2/package-summary.html index 390855e98b6..dd129d99fca 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/package-summary.html +++ b/docs/doc/reference/com/google/android/exoplayer2/package-summary.html @@ -119,8 +119,8 @@

    Package com.google.android.exoplayer2

    ControlDispatcher - -
    Dispatches operations to the Player.
    +Deprecated. +
    Use a ForwardingPlayer or configure the player to customize operations.
    @@ -179,61 +179,55 @@

    Package com.google.android.exoplayer2

    -PlaybackPreparer -Deprecated. -
    Use ControlDispatcher instead.
    - - - Player
    A media player interface defining traditional high-level functionality, such as the ability to play, pause, seek and query properties of the currently playing media.
    - + Player.EventListener Deprecated. - + Player.Listener
    Listener of all changes in the Player.
    - + PlayerMessage.Sender
    A sender for messages.
    - + PlayerMessage.Target
    A target for messages.
    - + Renderer
    Renders media read from a SampleStream.
    - + Renderer.WakeupListener
    Some renderers can signal when Renderer.render(long, long) should be called.
    - + RendererCapabilities
    Defines the capabilities of a Renderer.
    - + RenderersFactory
    Builds Renderer instances for use by a SimpleExoPlayer.
    @@ -283,8 +277,8 @@

    Package com.google.android.exoplayer2

    DefaultControlDispatcher - - +Deprecated. +
    Use a ForwardingPlayer or configure the player to customize operations.
    @@ -349,180 +343,192 @@

    Package com.google.android.exoplayer2

    +ForwardingPlayer + +
    A Player that forwards operations to another Player.
    + + + HeartRating
    A rating expressed as "heart" or "no heart".
    - + MediaItem
    Representation of a media item.
    - + MediaItem.AdsConfiguration
    Configuration for playing back linear ads with a media item.
    - + MediaItem.Builder
    A builder for MediaItem instances.
    - + MediaItem.ClippingProperties
    Optionally clips the media item to a custom start and end position.
    - + MediaItem.DrmConfiguration
    DRM configuration for a media item.
    - + MediaItem.LiveConfiguration
    Live playback configuration.
    - + MediaItem.PlaybackProperties
    Properties for local playback.
    - + MediaItem.Subtitle
    Properties for a text track.
    - + MediaMetadata
    Metadata of a MediaItem, playlist, or a combination of multiple sources of Metadata.
    - + MediaMetadata.Builder
    A builder for MediaMetadata instances.
    - + MetadataRetriever
    Retrieves the static metadata of MediaItems.
    - + NoSampleRenderer
    A Renderer implementation whose track type is C.TRACK_TYPE_NONE and does not consume data from its SampleStream.
    - + PercentageRating
    A rating expressed as a percentage.
    - + PlaybackParameters
    Parameters that apply to playback, including speed setting.
    - + Player.Commands
    A set of commands.
    - + Player.Commands.Builder
    A builder for Player.Commands instances.
    - + Player.Events - +
    A set of events.
    - + Player.PositionInfo
    Position info describing a playback position involved in a discontinuity.
    - + PlayerMessage
    Defines a player message which can be sent with a PlayerMessage.Sender and received by a PlayerMessage.Target.
    - + Rating
    A rating for media content.
    - + RendererConfiguration
    The configuration of a Renderer.
    - + SeekParameters
    Parameters that apply to seeking.
    - + SimpleExoPlayer
    An ExoPlayer implementation that uses default Renderer components.
    - + SimpleExoPlayer.Builder
    A builder for SimpleExoPlayer instances.
    - + StarRating
    A rating expressed as a fractional number of stars.
    - + ThumbRating
    A rating expressed as "thumbs up" or "thumbs down".
    - + Timeline
    A flexible representation of the structure of media.
    - + Timeline.Period
    Holds information about a period in a Timeline.
    + +Timeline.RemotableTimeline + +
    A concrete class of Timeline to restore a Timeline instance from a Bundle sent by another process via IBinder.
    + + Timeline.Window @@ -564,6 +570,12 @@

    Package com.google.android.exoplayer2

    Thrown when an error occurs parsing media data and metadata. + +PlaybackException + +
    Thrown when a non locally recoverable playback failure occurs.
    + + @@ -642,101 +654,125 @@

    Package com.google.android.exoplayer2

    +C.DataType + +
    Represents a type of data.
    + + + C.Encoding
    Represents an audio encoding, or an invalid or unset value.
    - + C.FormatSupport
    Level of renderer support for a format.
    - + C.NetworkType
    Network connection type.
    - + C.PcmEncoding
    Represents a PCM audio encoding, or an invalid or unset value.
    - + C.Projection
    Video projection types.
    - + C.RoleFlags
    Track role flags.
    - + C.SelectionFlags
    Track selection flags.
    - + C.StereoMode
    The stereo mode for 360/3D/VR videos.
    - + C.StreamType
    Stream types for an AudioTrack.
    - + C.VideoOutputMode
    Video decoder output modes.
    - + C.VideoScalingMode
    Video scaling modes for MediaCodec-based renderers.
    - + C.WakeMode
    Mode specifying whether the player should hold a WakeLock and a WifiLock.
    - + DefaultRenderersFactory.ExtensionRendererMode
    Modes for using extension renderers.
    - + ExoPlaybackException.Type
    The type of source that produced the error.
    - + ExoTimeoutException.TimeoutOperation
    The operation which produced the timeout error.
    - + MediaMetadata.FolderType
    The folder type of the media item.
    + +MediaMetadata.PictureType + +
    The picture type of the artwork.
    + + + +PlaybackException.ErrorCode + +
    Codes that identify causes of player errors.
    + + + +PlaybackException.FieldNumber + +
    Identifiers for fields in a Bundle which represents a playback exception.
    + + Player.Command @@ -750,7 +786,7 @@

    Package com.google.android.exoplayer2

    -Player.EventFlags +Player.Event
    Events that can be reported via Player.Listener.onEvents(Player, Events).
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/package-tree.html b/docs/doc/reference/com/google/android/exoplayer2/package-tree.html index 9b686b811d9..2b76260ff83 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/package-tree.html +++ b/docs/doc/reference/com/google/android/exoplayer2/package-tree.html @@ -126,6 +126,7 @@

    Class Hierarchy

  • com.google.android.exoplayer2.Format (implements android.os.Parcelable)
  • com.google.android.exoplayer2.Format.Builder
  • com.google.android.exoplayer2.FormatHolder
  • +
  • com.google.android.exoplayer2.ForwardingPlayer (implements com.google.android.exoplayer2.Player)
  • com.google.android.exoplayer2.MediaItem (implements com.google.android.exoplayer2.Bundleable)
  • com.google.android.exoplayer2.MediaItem.AdsConfiguration
  • com.google.android.exoplayer2.MediaItem.Builder
  • @@ -139,7 +140,7 @@

    Class Hierarchy

  • com.google.android.exoplayer2.MetadataRetriever
  • com.google.android.exoplayer2.NoSampleRenderer (implements com.google.android.exoplayer2.Renderer, com.google.android.exoplayer2.RendererCapabilities)
  • com.google.android.exoplayer2.PlaybackParameters (implements com.google.android.exoplayer2.Bundleable)
  • -
  • com.google.android.exoplayer2.Player.Commands
  • +
  • com.google.android.exoplayer2.Player.Commands (implements com.google.android.exoplayer2.Bundleable)
  • com.google.android.exoplayer2.Player.Commands.Builder
  • com.google.android.exoplayer2.Player.Events
  • com.google.android.exoplayer2.Player.PositionInfo (implements com.google.android.exoplayer2.Bundleable)
  • @@ -159,15 +160,19 @@

    Class Hierarchy

    + + + +
      +
    • +

      selectedBaseUrl

      +
      public final BaseUrl selectedBaseUrl
      +
    • +
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.html b/docs/doc/reference/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.html index d06c6cca448..f9f6b1e2bbd 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.html @@ -217,9 +217,10 @@

    Constructor Summary

    Description -DefaultDashChunkSource​(ChunkExtractor.Factory chunkExtractorFactory, +DefaultDashChunkSource​(ChunkExtractor.Factory chunkExtractorFactory, LoaderErrorThrower manifestLoaderErrorThrower, DashManifest manifest, + BaseUrlExclusionList baseUrlExclusionList, int periodIndex, int[] adaptationSetIndices, ExoTrackSelection trackSelection, @@ -319,10 +320,10 @@

    Method Summary

    boolean -onChunkLoadError​(Chunk chunk, +onChunkLoadError​(Chunk chunk, boolean cancelable, - Exception e, - long exclusionDurationMs) + LoadErrorHandlingPolicy.LoadErrorInfo loadErrorInfo, + LoadErrorHandlingPolicy loadErrorHandlingPolicy)
    Called when the ChunkSampleStream encounters an error loading a chunk obtained from this source.
    @@ -402,7 +403,7 @@

    representationHolders

    Constructor Detail

    - +
      @@ -411,6 +412,7 @@

      DefaultDashChunkSource

      public DefaultDashChunkSource​(ChunkExtractor.Factory chunkExtractorFactory,
                                     LoaderErrorThrower manifestLoaderErrorThrower,
                                     DashManifest manifest,
      +                              BaseUrlExclusionList baseUrlExclusionList,
                                     int periodIndex,
                                     int[] adaptationSetIndices,
                                     ExoTrackSelection trackSelection,
      @@ -428,6 +430,7 @@ 

      DefaultDashChunkSource

      chunks.
      manifestLoaderErrorThrower - Throws errors affecting loading of manifests.
      manifest - The initial manifest.
      +
      baseUrlExclusionList - The base URL exclusion list.
      periodIndex - The index of the period in the manifest.
      adaptationSetIndices - The indices of the adaptation sets in the period.
      trackSelection - The track selection.
      @@ -632,7 +635,7 @@

      onChunkLoadCompleted

    - +
      @@ -640,20 +643,20 @@

      onChunkLoadCompleted

      onChunkLoadError

      public boolean onChunkLoadError​(Chunk chunk,
                                       boolean cancelable,
      -                                Exception e,
      -                                long exclusionDurationMs)
      -
      Description copied from interface: ChunkSource
      + LoadErrorHandlingPolicy.LoadErrorInfo loadErrorInfo, + LoadErrorHandlingPolicy loadErrorHandlingPolicy) +
      Description copied from interface: ChunkSource
      Called when the ChunkSampleStream encounters an error loading a chunk obtained from this source.
      Specified by:
      -
      onChunkLoadError in interface ChunkSource
      +
      onChunkLoadError in interface ChunkSource
      Parameters:
      chunk - The chunk whose load encountered the error.
      cancelable - Whether the load can be canceled.
      -
      e - The error.
      -
      exclusionDurationMs - The duration for which the associated track may be excluded, or - C.TIME_UNSET if the track may not be excluded.
      +
      loadErrorInfo - The load error info.
      +
      loadErrorHandlingPolicy - The load error handling policy to customize the behaviour of + handling the load error.
      Returns:
      Whether the load should be canceled so that a replacement chunk can be loaded instead. Must be false if cancelable is false. If true, ChunkSource.getNextChunk(long, long, List, ChunkHolder) will be called to obtain the replacement @@ -687,6 +690,7 @@

      newInitializationChunk

      Format trackFormat, int trackSelectionReason, Object trackSelectionData, + @Nullable RangedUri initializationUri, RangedUri indexUri) diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/dash/PlayerEmsgHandler.PlayerTrackEmsgHandler.html b/docs/doc/reference/com/google/android/exoplayer2/source/dash/PlayerEmsgHandler.PlayerTrackEmsgHandler.html index f8ba12a0bb9..c7ebfc03cf1 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/dash/PlayerEmsgHandler.PlayerTrackEmsgHandler.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/dash/PlayerEmsgHandler.PlayerTrackEmsgHandler.html @@ -255,7 +255,7 @@

      Method Summary

      int flags, int size, int offset, - TrackOutput.CryptoData encryptionData)
      + TrackOutput.CryptoData cryptoData)
      Called when metadata associated with a sample has been extracted from the stream.
      @@ -372,7 +372,7 @@

      sampleMetadata

      int size, int offset, @Nullable - TrackOutput.CryptoData encryptionData) + TrackOutput.CryptoData cryptoData)
      Description copied from interface: TrackOutput
      Called when metadata associated with a sample has been extracted from the stream. @@ -388,7 +388,7 @@

      sampleMetadata

      offset - The number of bytes that have been passed to TrackOutput.sampleData(DataReader, int, boolean) or TrackOutput.sampleData(ParsableByteArray, int) since the last byte belonging to the sample whose metadata is being passed.
      -
      encryptionData - The encryption data required to decrypt the sample. May be null.
      +
      cryptoData - The encryption data required to decrypt the sample. May be null.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/dash/manifest/AdaptationSet.html b/docs/doc/reference/com/google/android/exoplayer2/source/dash/manifest/AdaptationSet.html index c7fe078e01a..45d6f90fde1 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/dash/manifest/AdaptationSet.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/dash/manifest/AdaptationSet.html @@ -288,8 +288,8 @@

    id

  • type

    public final int type
    -
    The type of the adaptation set. One of the C - TRACK_TYPE_* constants.
    +
    The type of the adaptation set. One of the C + TRACK_TYPE_* constants.
  • diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/dash/manifest/BaseUrl.html b/docs/doc/reference/com/google/android/exoplayer2/source/dash/manifest/BaseUrl.html new file mode 100644 index 00000000000..4845528f958 --- /dev/null +++ b/docs/doc/reference/com/google/android/exoplayer2/source/dash/manifest/BaseUrl.html @@ -0,0 +1,489 @@ + + + + +BaseUrl (ExoPlayer library) + + + + + + + + + + + + + +
    + +
    + +
    + +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.google.android.exoplayer2.source.dash.manifest.BaseUrl
      • +
      +
    • +
    +
    +
      +
    • +
      +
      public final class BaseUrl
      +extends Object
      +
      A base URL, as defined by ISO 23009-1, 2nd edition, 5.6. and ETSI TS 103 285 V1.2.1, 10.8.2.1
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Field Detail

        + + + +
          +
        • +

          DEFAULT_PRIORITY

          +
          public static final int DEFAULT_PRIORITY
          +
          The default priority.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          DEFAULT_WEIGHT

          +
          public static final int DEFAULT_WEIGHT
          +
          The default weight.
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          url

          +
          public final String url
          +
          The URL.
          +
        • +
        + + + +
          +
        • +

          serviceLocation

          +
          public final String serviceLocation
          +
          The service location.
          +
        • +
        + + + +
          +
        • +

          priority

          +
          public final int priority
          +
          The priority.
          +
        • +
        + + + +
          +
        • +

          weight

          +
          public final int weight
          +
          The weight.
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Constructor Detail

        + + + + + + + +
          +
        • +

          BaseUrl

          +
          public BaseUrl​(String url,
          +               String serviceLocation,
          +               int priority,
          +               int weight)
          +
          Creates an instance.
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          equals

          +
          public boolean equals​(@Nullable
          +                      Object o)
          +
          +
          Overrides:
          +
          equals in class Object
          +
          +
        • +
        + + + +
          +
        • +

          hashCode

          +
          public int hashCode()
          +
          +
          Overrides:
          +
          hashCode in class Object
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + + + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/dash/manifest/DashManifest.html b/docs/doc/reference/com/google/android/exoplayer2/source/dash/manifest/DashManifest.html index 03b57388fe5..cca2123239a 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/dash/manifest/DashManifest.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/dash/manifest/DashManifest.html @@ -213,8 +213,8 @@

    Field Summary

    long publishTimeMs -
    The publishTime value in milliseconds since epoch, or C.TIME_UNSET if - not present.
    +
    The publishTime value in milliseconds since epoch, or C.TIME_UNSET if not + present.
    @@ -236,8 +236,7 @@

    Field Summary

    long timeShiftBufferDepthMs -
    The timeShiftBufferDepth value in milliseconds, or C.TIME_UNSET if not - present.
    +
    The timeShiftBufferDepth value in milliseconds, or C.TIME_UNSET if not present.
    @@ -408,8 +407,7 @@

    minUpdatePeriodMs

  • timeShiftBufferDepthMs

    public final long timeShiftBufferDepthMs
    -
    The timeShiftBufferDepth value in milliseconds, or C.TIME_UNSET if not - present.
    +
    The timeShiftBufferDepth value in milliseconds, or C.TIME_UNSET if not present.
  • @@ -430,8 +428,8 @@

    suggestedPresentationDelayMs

  • publishTimeMs

    public final long publishTimeMs
    -
    +
    The publishTime value in milliseconds since epoch, or C.TIME_UNSET if not + present.
  • diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.RepresentationInfo.html b/docs/doc/reference/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.RepresentationInfo.html index f23c341acd9..e9029a73e06 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.RepresentationInfo.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.RepresentationInfo.html @@ -151,8 +151,8 @@

    Field Summary

    Description -
    String -baseUrl +ImmutableList<BaseUrl> +baseUrls   @@ -203,8 +203,8 @@

    Constructor Summary

    Description -RepresentationInfo​(Format format, - String baseUrl, +RepresentationInfo​(Format format, + List<BaseUrl> baseUrls, SegmentBase segmentBase, String drmSchemeType, ArrayList<DrmInitData.SchemeData> drmSchemeDatas, @@ -255,13 +255,13 @@

    format

    public final Format format
    - + @@ -320,14 +320,14 @@

    revisionId

    Constructor Detail

    - +
    - + - +
    • parsePeriod

      protected Pair<Period,​Long> parsePeriod​(XmlPullParser xpp,
      -                                              String baseUrl,
      +                                              List<BaseUrl> parentBaseUrls,
                                                     long defaultStartMs,
                                                     long baseUrlAvailabilityTimeOffsetUs,
                                                     long availabilityStartTimeMs,
      @@ -887,14 +887,14 @@ 

      buildPeriod

      Descriptor assetIdentifier)
    - +
    - +
    - +
    • @@ -363,7 +363,7 @@

      Methods inherited from class java.lang. +
        @@ -371,7 +371,7 @@

        Constructor Detail

        MultiSegmentRepresentation

        public MultiSegmentRepresentation​(long revisionId,
                                           Format format,
        -                                  String baseUrl,
        +                                  List<BaseUrl> baseUrls,
                                           SegmentBase.MultiSegmentBase segmentBase,
                                           @Nullable
                                           List<Descriptor> inbandEventStreams)
        @@ -380,7 +380,7 @@

        MultiSegmentRepresentation

        Parameters:
        revisionId - Identifies the revision of the content.
        format - The format of the representation.
        -
        baseUrl - The base URL of the representation.
        +
        baseUrls - The base URLs of the representation.
        segmentBase - The segment base underlying the representation.
        inbandEventStreams - The in-band event streams in the representation. May be null.

    @@ -450,14 +450,14 @@

    getCacheKey

    • @@ -341,7 +341,7 @@

      contentLength

      Constructor Detail

      - +
        @@ -349,7 +349,7 @@

        Constructor Detail

        SingleSegmentRepresentation

        public SingleSegmentRepresentation​(long revisionId,
                                            Format format,
        -                                   String baseUrl,
        +                                   List<BaseUrl> baseUrls,
                                            SegmentBase.SingleSegmentBase segmentBase,
                                            @Nullable
                                            List<Descriptor> inbandEventStreams,
        @@ -360,7 +360,7 @@ 

        SingleSegmentRepresentation

        Parameters:
        revisionId - Identifies the revision of the content.
        format - The format of the representation.
        -
        baseUrl - The base URL of the representation.
        +
        baseUrls - The base urls of the representation.
        segmentBase - The segment base underlying the representation.
        inbandEventStreams - The in-band event streams in the representation. May be null.
        cacheKey - An optional key to be returned from getCacheKey(), or null.
        diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/dash/manifest/Representation.html b/docs/doc/reference/com/google/android/exoplayer2/source/dash/manifest/Representation.html index db762e193da..939d58dc95c 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/dash/manifest/Representation.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/dash/manifest/Representation.html @@ -189,10 +189,10 @@

        Field Summary

        Description -String -baseUrl +ImmutableList<BaseUrl> +baseUrls -
        The base URL of the representation.
        +
        The base URLs of the representation.
        @@ -280,9 +280,9 @@

        Method Summary

        static Representation -newInstance​(long revisionId, +newInstance​(long revisionId, Format format, - String baseUrl, + List<BaseUrl> baseUrls, SegmentBase segmentBase)
        Constructs a new instance.
        @@ -290,9 +290,9 @@

        Method Summary

        static Representation -newInstance​(long revisionId, +newInstance​(long revisionId, Format format, - String baseUrl, + List<BaseUrl> baseUrls, SegmentBase segmentBase, List<Descriptor> inbandEventStreams) @@ -301,9 +301,9 @@

        Method Summary

        static Representation -newInstance​(long revisionId, +newInstance​(long revisionId, Format format, - String baseUrl, + List<BaseUrl> baseUrls, SegmentBase segmentBase, List<Descriptor> inbandEventStreams, String cacheKey) @@ -372,14 +372,14 @@

        format

        The format of the representation.
      - +
      • -

        baseUrl

        -
        public final String baseUrl
        -
        The base URL of the representation.
        +

        baseUrls

        +
        public final ImmutableList<BaseUrl> baseUrls
        +
        The base URLs of the representation.
      @@ -412,7 +412,7 @@

      inbandEventStreams

      Method Detail

      - +
        @@ -420,21 +420,21 @@

        Method Detail

        newInstance

        public static Representation newInstance​(long revisionId,
                                                  Format format,
        -                                         String baseUrl,
        +                                         List<BaseUrl> baseUrls,
                                                  SegmentBase segmentBase)
        Constructs a new instance.
        Parameters:
        revisionId - Identifies the revision of the content.
        format - The format of the representation.
        -
        baseUrl - The base URL.
        +
        baseUrls - The list of base URLs of the representation.
        segmentBase - A segment base element for the representation.
        Returns:
        The constructed instance.
      - +
        @@ -442,7 +442,7 @@

        newInstance

        newInstance

        public static Representation newInstance​(long revisionId,
                                                  Format format,
        -                                         String baseUrl,
        +                                         List<BaseUrl> baseUrls,
                                                  SegmentBase segmentBase,
                                                  @Nullable
                                                  List<Descriptor> inbandEventStreams)
        @@ -451,7 +451,7 @@

        newInstance

        Parameters:
        revisionId - Identifies the revision of the content.
        format - The format of the representation.
        -
        baseUrl - The base URL.
        +
        baseUrls - The list of base URLs of the representation.
        segmentBase - A segment base element for the representation.
        inbandEventStreams - The in-band event streams in the representation. May be null.
        Returns:
        @@ -459,7 +459,7 @@

        newInstance

    - + +
  • com.google.android.exoplayer2.source.dash.BaseUrlExclusionList
  • com.google.android.exoplayer2.source.dash.DashMediaSource.Factory (implements com.google.android.exoplayer2.source.MediaSourceFactory)
  • com.google.android.exoplayer2.source.dash.DashUtil
  • com.google.android.exoplayer2.source.dash.DashWrappingSegmentIndex (implements com.google.android.exoplayer2.source.dash.DashSegmentIndex)
  • diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/hls/DefaultHlsExtractorFactory.html b/docs/doc/reference/com/google/android/exoplayer2/source/hls/DefaultHlsExtractorFactory.html index 580c21a9a7e..13dbbf691a3 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/hls/DefaultHlsExtractorFactory.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/hls/DefaultHlsExtractorFactory.html @@ -213,7 +213,7 @@

    Method Summary

    List<Format> muxedCaptionFormats, TimestampAdjuster timestampAdjuster, Map<String,​List<String>> responseHeaders, - ExtractorInput extractorInput)
    + ExtractorInput sniffingExtractorInput)
    Creates an Extractor for extracting HLS media chunks.
    @@ -295,7 +295,7 @@

    createExtractor

    List<Format> muxedCaptionFormats, TimestampAdjuster timestampAdjuster, Map<String,​List<String>> responseHeaders, - ExtractorInput extractorInput) + ExtractorInput sniffingExtractorInput) throws IOException
    Description copied from interface: HlsExtractorFactory
    Creates an Extractor for extracting HLS media chunks.
    @@ -310,7 +310,7 @@

    createExtractor

    timestampAdjuster - Adjuster corresponding to the provided discontinuity sequence number.
    responseHeaders - The HTTP response headers associated with the media segment or initialization section to extract.
    -
    extractorInput - The first extractor input that will be passed to the returned +
    sniffingExtractorInput - The first extractor input that will be passed to the returned extractor's Extractor.read(ExtractorInput, PositionHolder). Must only be used to call Extractor.sniff(ExtractorInput).
    Returns:
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.html b/docs/doc/reference/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.html index a51d39ad929..4bdb02e8614 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.html @@ -293,8 +293,9 @@

    Method Summary

    boolean -onPlaylistError​(Uri url, - long exclusionDurationMs) +onPlaylistError​(Uri url, + LoadErrorHandlingPolicy.LoadErrorInfo loadErrorInfo, + boolean forceRetry)
    Called if an error is encountered while loading a playlist.
    @@ -856,22 +857,24 @@

    onPlaylistChanged

    - + diff --git a/docs/doc/reference/com/google/android/exoplayer2/text/SubtitleOutputBuffer.html b/docs/doc/reference/com/google/android/exoplayer2/text/SubtitleOutputBuffer.html index 09ebc334f6c..41665a12c84 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/text/SubtitleOutputBuffer.html +++ b/docs/doc/reference/com/google/android/exoplayer2/text/SubtitleOutputBuffer.html @@ -340,8 +340,7 @@

    setContent

    Parameters:
    timeUs - The time of the start of the subtitle in microseconds.
    subtitle - The subtitle.
    -
    subsampleOffsetUs - An offset that must be added to the subtitle's event times, or - Format.OFFSET_SAMPLE_RELATIVE if timeUs should be added.
    +
    subsampleOffsetUs - An offset that must be added to the subtitle's event times, or Format.OFFSET_SAMPLE_RELATIVE if timeUs should be added.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/text/TextRenderer.html b/docs/doc/reference/com/google/android/exoplayer2/text/TextRenderer.html index fd7f9850d2a..e5e49705ffb 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/text/TextRenderer.html +++ b/docs/doc/reference/com/google/android/exoplayer2/text/TextRenderer.html @@ -320,7 +320,7 @@

    Method Summary

    Methods inherited from class com.google.android.exoplayer2.BaseRenderer

    -createRendererException, createRendererException, disable, enable, getCapabilities, getConfiguration, getFormatHolder, getIndex, getLastResetPositionUs, getMediaClock, getReadingPositionUs, getState, getStream, getStreamFormats, getTrackType, handleMessage, hasReadStreamToEnd, isCurrentStreamFinal, isSourceReady, maybeThrowStreamError, onEnabled, onReset, onStarted, onStopped, readSource, replaceStream, reset, resetPosition, setCurrentStreamFinal, setIndex, skipSource, start, stop, supportsMixedMimeTypeAdaptation +createRendererException, createRendererException, disable, enable, getCapabilities, getConfiguration, getFormatHolder, getIndex, getLastResetPositionUs, getMediaClock, getReadingPositionUs, getState, getStream, getStreamFormats, getTrackType, handleMessage, hasReadStreamToEnd, isCurrentStreamFinal, isSourceReady, maybeThrowStreamError, onEnabled, onReset, onStarted, onStopped, readSource, replaceStream, reset, resetPosition, setCurrentStreamFinal, setIndex, skipSource, start, stop, supportsMixedMimeTypeAdaptation
    • @@ -555,8 +555,8 @@

      onDisabled

      protected void onDisabled()
      Called when the renderer is disabled. -

      - The default implementation is a no-op.

      + +

      The default implementation is a no-op.

      Overrides:
      onDisabled in class BaseRenderer
      @@ -592,16 +592,15 @@

      isReady

      public boolean isReady()
      Description copied from interface: Renderer
      Whether the renderer is able to immediately render media from the current position. -

      - If the renderer is in the Renderer.STATE_STARTED state then returning true indicates that the - renderer has everything that it needs to continue playback. Returning false indicates that + +

      If the renderer is in the Renderer.STATE_STARTED state then returning true indicates that + the renderer has everything that it needs to continue playback. Returning false indicates that the player should pause until the renderer is ready. -

      - If the renderer is in the Renderer.STATE_ENABLED state then returning true indicates that the - renderer is ready for playback to be started. Returning false indicates that it is not. -

      - This method may be called when the renderer is in the following states: - Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

      + +

      If the renderer is in the Renderer.STATE_ENABLED state then returning true indicates that + the renderer is ready for playback to be started. Returning false indicates that it is not. + +

      This method may be called when the renderer is in the following states: Renderer.STATE_ENABLED, Renderer.STATE_STARTED.

      Specified by:
      isReady in interface Renderer
      diff --git a/docs/doc/reference/com/google/android/exoplayer2/text/cea/Cea608Decoder.html b/docs/doc/reference/com/google/android/exoplayer2/text/cea/Cea608Decoder.html index b8757e209ca..3c27a1913c4 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/text/cea/Cea608Decoder.html +++ b/docs/doc/reference/com/google/android/exoplayer2/text/cea/Cea608Decoder.html @@ -482,8 +482,8 @@

      setPositionUs

      public void setPositionUs​(long positionUs)
      Description copied from interface: SubtitleDecoder
      Informs the decoder of the current playback position. -

      - Must be called prior to each attempt to dequeue output buffers from the decoder.

      + +

      Must be called prior to each attempt to dequeue output buffers from the decoder.

      Specified by:
      setPositionUs in interface SubtitleDecoder
      diff --git a/docs/doc/reference/com/google/android/exoplayer2/text/cea/Cea708Decoder.html b/docs/doc/reference/com/google/android/exoplayer2/text/cea/Cea708Decoder.html index f378cf37f5d..9fd5c0dbbe8 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/text/cea/Cea708Decoder.html +++ b/docs/doc/reference/com/google/android/exoplayer2/text/cea/Cea708Decoder.html @@ -382,8 +382,8 @@

      setPositionUs

      public void setPositionUs​(long positionUs)
      Description copied from interface: SubtitleDecoder
      Informs the decoder of the current playback position. -

      - Must be called prior to each attempt to dequeue output buffers from the decoder.

      + +

      Must be called prior to each attempt to dequeue output buffers from the decoder.

      Specified by:
      setPositionUs in interface SubtitleDecoder
      diff --git a/docs/doc/reference/com/google/android/exoplayer2/text/dvb/DvbDecoder.html b/docs/doc/reference/com/google/android/exoplayer2/text/dvb/DvbDecoder.html index 205ec85f82a..414596a985e 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/text/dvb/DvbDecoder.html +++ b/docs/doc/reference/com/google/android/exoplayer2/text/dvb/DvbDecoder.html @@ -250,9 +250,9 @@

      DvbDecoder

      public DvbDecoder​(List<byte[]> initializationData)
      Parameters:
      -
      initializationData - The initialization data for the decoder. The initialization data - must consist of a single byte array containing 5 bytes: flag_pes_stripped (1), - composition_page (2), ancillary_page (2).
      +
      initializationData - The initialization data for the decoder. The initialization data must + consist of a single byte array containing 5 bytes: flag_pes_stripped (1), composition_page + (2), ancillary_page (2).
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/text/package-tree.html b/docs/doc/reference/com/google/android/exoplayer2/text/package-tree.html index e56d16c43da..a0b7249618c 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/text/package-tree.html +++ b/docs/doc/reference/com/google/android/exoplayer2/text/package-tree.html @@ -122,7 +122,7 @@

    Class Hierarchy

    -
  • com.google.android.exoplayer2.text.Cue
  • +
  • com.google.android.exoplayer2.text.Cue (implements com.google.android.exoplayer2.Bundleable)
  • com.google.android.exoplayer2.text.Cue.Builder
  • com.google.android.exoplayer2.decoder.SimpleDecoder<I,​O,​E> (implements com.google.android.exoplayer2.decoder.Decoder<I,​O,​E>)
      diff --git a/docs/doc/reference/com/google/android/exoplayer2/text/webvtt/WebvttCssStyle.html b/docs/doc/reference/com/google/android/exoplayer2/text/webvtt/WebvttCssStyle.html index 2b734d10d42..2e4ca98d51b 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/text/webvtt/WebvttCssStyle.html +++ b/docs/doc/reference/com/google/android/exoplayer2/text/webvtt/WebvttCssStyle.html @@ -372,7 +372,7 @@

      Method Summary

      WebvttCssStyle -setFontSizeUnit​(short unit) +setFontSizeUnit​(int unit)   @@ -621,7 +621,16 @@

      getSpecificityScore

      Set<String> classes, @Nullable String voice) -
      Returns a value in a score system compliant with the CSS Specificity rules.
      +
      Returns a value in a score system compliant with the CSS Specificity rules. + +

      The score works as follows: + +

        +
      • Id match adds 0x40000000 to the score. +
      • Each class and voice match adds 4 to the score. +
      • Tag matching adds 2 to the score. +
      • Universal selector matching scores 1. +
      Parameters:
      id - The id of the cue if present, null otherwise.
      @@ -631,14 +640,7 @@

      getSpecificityScore

      Returns:
      The score of the match, zero if there is no match.
      See Also:
      -
      CSS Cascading -

      The score works as follows: -

        -
      • Id match adds 0x40000000 to the score. -
      • Each class and voice match adds 4 to the score. -
      • Tag matching adds 2 to the score. -
      • Universal selector matching scores 1. -
      +
      CSS Cascading
    @@ -795,13 +797,14 @@

    setFontSize

    public WebvttCssStyle setFontSize​(float fontSize)
  • - + diff --git a/docs/doc/reference/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.Parameters.html b/docs/doc/reference/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.Parameters.html index bfa08069b7f..d02f0486dae 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.Parameters.html +++ b/docs/doc/reference/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.Parameters.html @@ -143,8 +143,9 @@

    Class DefaultTra
    public static final class DefaultTrackSelector.Parameters
    -extends TrackSelectionParameters
    -
    Extends TrackSelectionParameters by adding fields that are specific to DefaultTrackSelector.
    +extends TrackSelectionParameters +implements Parcelable +
    Extends DefaultTrackSelector.Parameters by adding fields that are specific to DefaultTrackSelector.
    @@ -238,133 +239,47 @@

    Field Summary

    static DefaultTrackSelector.Parameters -DEFAULT_WITHOUT_CONTEXT +DEFAULT -
    An instance with default values, except those obtained from the Context.
    +
    Deprecated. +
    This instance is not configured using Context constraints.
    +
    -boolean -exceedAudioConstraintsIfNecessary +static DefaultTrackSelector.Parameters +DEFAULT_WITHOUT_CONTEXT -
    Whether to exceed the maxAudioChannelCount and maxAudioBitrate constraints - when no selection can be made otherwise.
    +
    An instance with default values, except those obtained from the Context.
    -boolean -exceedRendererCapabilitiesIfNecessary +int +disabledTextTrackSelectionFlags -
    Whether to exceed renderer capabilities when no selection can be made otherwise.
    +
    Bitmask of selection flags that are disabled for text track selections.
    boolean -exceedVideoConstraintsIfNecessary +exceedAudioConstraintsIfNecessary -
    Whether to exceed the maxVideoWidth, maxVideoHeight and maxVideoBitrate constraints when no selection can be made otherwise.
    +
    Whether to exceed the TrackSelectionParameters.maxAudioChannelCount and TrackSelectionParameters.maxAudioBitrate constraints + when no selection can be made otherwise.
    boolean -forceHighestSupportedBitrate +exceedRendererCapabilitiesIfNecessary -
    Whether to force selection of the highest bitrate audio and video tracks that comply with all - other constraints.
    +
    Whether to exceed renderer capabilities when no selection can be made otherwise.
    boolean -forceLowestBitrate - -
    Whether to force selection of the single lowest bitrate audio and video tracks that comply - with all other constraints.
    - - - -int -maxAudioBitrate - -
    Maximum allowed audio bitrate in bits per second.
    - - - -int -maxAudioChannelCount - -
    Maximum allowed audio channel count.
    - - - -int -maxVideoBitrate - -
    Maximum allowed video bitrate in bits per second.
    - - - -int -maxVideoFrameRate - -
    Maximum allowed video frame rate in hertz.
    - - - -int -maxVideoHeight - -
    Maximum allowed video height in pixels.
    - - - -int -maxVideoWidth - -
    Maximum allowed video width in pixels.
    - - - -int -minVideoBitrate - -
    Minimum allowed video bitrate in bits per second.
    - - - -int -minVideoFrameRate - -
    Minimum allowed video frame rate in hertz.
    - - - -int -minVideoHeight - -
    Minimum allowed video height in pixels.
    - - - -int -minVideoWidth - -
    Minimum allowed video width in pixels.
    - - - -ImmutableList<String> -preferredAudioMimeTypes - -
    The preferred sample MIME types for audio tracks in order of preference, or an empty list for - no preference.
    - - - -ImmutableList<String> -preferredVideoMimeTypes +exceedVideoConstraintsIfNecessary -
    The preferred sample MIME types for video tracks in order of preference, or an empty list for - no preference.
    +
    Whether to exceed the TrackSelectionParameters.maxVideoWidth, TrackSelectionParameters.maxVideoHeight and TrackSelectionParameters.maxVideoBitrate constraints when no selection can be made otherwise.
    @@ -374,34 +289,13 @@

    Field Summary

    Whether to enable tunneling if possible.
    - -int -viewportHeight - -
    Viewport height in pixels.
    - - - -boolean -viewportOrientationMayChange - -
    Whether the viewport orientation may change during playback.
    - - - -int -viewportWidth - -
    Viewport width in pixels.
    - - - - - -
      -
    • -

      maxVideoWidth

      -
      public final int maxVideoWidth
      -
      Maximum allowed video width in pixels. The default value is Integer.MAX_VALUE (i.e. - no constraint). - -

      To constrain adaptive video track selections to be suitable for a given viewport (the - region of the display within which video will be played), use (viewportWidth, viewportHeight and viewportOrientationMayChange) instead.

      -
    • -
    - +
    • -

      maxVideoHeight

      -
      public final int maxVideoHeight
      -
      Maximum allowed video height in pixels. The default value is Integer.MAX_VALUE (i.e. - no constraint). - -

      To constrain adaptive video track selections to be suitable for a given viewport (the - region of the display within which video will be played), use (viewportWidth, viewportHeight and viewportOrientationMayChange) instead.

      -
    • -
    - - - -
      -
    • -

      maxVideoFrameRate

      -
      public final int maxVideoFrameRate
      -
      Maximum allowed video frame rate in hertz. The default value is Integer.MAX_VALUE - (i.e. no constraint).
      -
    • -
    - - - -
      -
    • -

      maxVideoBitrate

      -
      public final int maxVideoBitrate
      -
      Maximum allowed video bitrate in bits per second. The default value is Integer.MAX_VALUE (i.e. no constraint).
      -
    • -
    - - - -
      -
    • -

      minVideoWidth

      -
      public final int minVideoWidth
      -
      Minimum allowed video width in pixels. The default value is 0 (i.e. no constraint).
      -
    • -
    - - - - - + - +
    • -

      minVideoBitrate

      -
      public final int minVideoBitrate
      -
      Minimum allowed video bitrate in bits per second. The default value is 0 (i.e. no - constraint).
      +

      disabledTextTrackSelectionFlags

      +
      @SelectionFlags
      +public final int disabledTextTrackSelectionFlags
      +
      Bitmask of selection flags that are disabled for text track selections. See C.SelectionFlags. The default value is 0 (i.e. no flags).
    @@ -626,7 +463,7 @@

    minVideoBitrate

  • exceedVideoConstraintsIfNecessary

    public final boolean exceedVideoConstraintsIfNecessary
    -
    Whether to exceed the maxVideoWidth, maxVideoHeight and maxVideoBitrate constraints when no selection can be made otherwise. The default value is +
    Whether to exceed the TrackSelectionParameters.maxVideoWidth, TrackSelectionParameters.maxVideoHeight and TrackSelectionParameters.maxVideoBitrate constraints when no selection can be made otherwise. The default value is true.
  • @@ -653,74 +490,6 @@

    allowVideoNonSeamlessAdaptiveness

    The default value is true. - - - -
      -
    • -

      viewportWidth

      -
      public final int viewportWidth
      -
      Viewport width in pixels. Constrains video track selections for adaptive content so that only - tracks suitable for the viewport are selected. The default value is the physical width of the - primary display, in pixels.
      -
    • -
    - - - -
      -
    • -

      viewportHeight

      -
      public final int viewportHeight
      -
      Viewport height in pixels. Constrains video track selections for adaptive content so that - only tracks suitable for the viewport are selected. The default value is the physical height - of the primary display, in pixels.
      -
    • -
    - - - -
      -
    • -

      viewportOrientationMayChange

      -
      public final boolean viewportOrientationMayChange
      -
      Whether the viewport orientation may change during playback. Constrains video track - selections for adaptive content so that only tracks suitable for the viewport are selected. - The default value is true.
      -
    • -
    - - - -
      -
    • -

      preferredVideoMimeTypes

      -
      public final ImmutableList<String> preferredVideoMimeTypes
      -
      The preferred sample MIME types for video tracks in order of preference, or an empty list for - no preference. The default is an empty list.
      -
    • -
    - - - -
      -
    • -

      maxAudioChannelCount

      -
      public final int maxAudioChannelCount
      -
      Maximum allowed audio channel count. The default value is Integer.MAX_VALUE (i.e. no - constraint).
      -
    • -
    - - - -
      -
    • -

      maxAudioBitrate

      -
      public final int maxAudioBitrate
      -
      Maximum allowed audio bitrate in bits per second. The default value is Integer.MAX_VALUE (i.e. no constraint).
      -
    • -
    @@ -728,7 +497,7 @@

    maxAudioBitrate

  • exceedAudioConstraintsIfNecessary

    public final boolean exceedAudioConstraintsIfNecessary
    -
    Whether to exceed the maxAudioChannelCount and maxAudioBitrate constraints +
    Whether to exceed the TrackSelectionParameters.maxAudioChannelCount and TrackSelectionParameters.maxAudioBitrate constraints when no selection can be made otherwise. The default value is true.
  • @@ -766,39 +535,6 @@

    allowAudioMixedChannelCountAdaptiveness

    false
    . - - - -
      -
    • -

      preferredAudioMimeTypes

      -
      public final ImmutableList<String> preferredAudioMimeTypes
      -
      The preferred sample MIME types for audio tracks in order of preference, or an empty list for - no preference. The default is an empty list.
      -
    • -
    - - - -
      -
    • -

      forceLowestBitrate

      -
      public final boolean forceLowestBitrate
      -
      Whether to force selection of the single lowest bitrate audio and video tracks that comply - with all other constraints. The default value is false.
      -
    • -
    - - - -
      -
    • -

      forceHighestSupportedBitrate

      -
      public final boolean forceHighestSupportedBitrate
      -
      Whether to force selection of the highest bitrate audio and video tracks that comply with all - other constraints. The default value is false.
      -
    • -
    @@ -828,7 +564,7 @@

    tunnelingEnabled

    -
      +
      • allowMultipleAdaptiveSelections

        public final boolean allowMultipleAdaptiveSelections
        @@ -840,15 +576,6 @@

        allowMultipleAdaptiveSelections

        other track selection parameters.
      - - - -
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.ParametersBuilder.html b/docs/doc/reference/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.ParametersBuilder.html index ee7bf8b484e..168ceb60a44 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.ParametersBuilder.html +++ b/docs/doc/reference/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.ParametersBuilder.html @@ -226,14 +226,14 @@

    Method Summary

    DefaultTrackSelector.ParametersBuilder clearVideoSizeConstraints() - + DefaultTrackSelector.ParametersBuilder clearViewportSizeConstraints() -
    Equivalent to setViewportSize(Integer.MAX_VALUE, Integer.MAX_VALUE, + @@ -365,7 +365,7 @@

    Method Summary

    DefaultTrackSelector.ParametersBuilder setMaxVideoSizeSd() - + @@ -516,7 +516,7 @@

    Method Summary

    setViewportSizeToPhysicalDisplaySize​(Context context, boolean viewportOrientationMayChange) -
    Equivalent to calling setViewportSize(int, int, boolean) with the viewport size + @@ -588,8 +588,11 @@

    Method Detail

  • setMaxVideoSizeSd

    public DefaultTrackSelector.ParametersBuilder setMaxVideoSizeSd()
    - +
    Description copied from class: TrackSelectionParameters.Builder
    +
    +
    Overrides:
    +
    setMaxVideoSizeSd in class TrackSelectionParameters.Builder
    Returns:
    This builder.
    @@ -602,8 +605,11 @@

    setMaxVideoSizeSd

  • clearVideoSizeConstraints

    public DefaultTrackSelector.ParametersBuilder clearVideoSizeConstraints()
    - +
    Description copied from class: TrackSelectionParameters.Builder
    +
    +
    Overrides:
    +
    clearVideoSizeConstraints in class TrackSelectionParameters.Builder
    Returns:
    This builder.
    @@ -617,8 +623,11 @@

    clearVideoSizeConstraints

    setMaxVideoSize

    public DefaultTrackSelector.ParametersBuilder setMaxVideoSize​(int maxVideoWidth,
                                                                   int maxVideoHeight)
    +
    Description copied from class: TrackSelectionParameters.Builder
    Sets the maximum allowed video width and height.
    +
    Overrides:
    +
    setMaxVideoSize in class TrackSelectionParameters.Builder
    Parameters:
    maxVideoWidth - Maximum allowed video width in pixels.
    maxVideoHeight - Maximum allowed video height in pixels.
    @@ -634,8 +643,11 @@

    setMaxVideoSize

  • setMaxVideoFrameRate

    public DefaultTrackSelector.ParametersBuilder setMaxVideoFrameRate​(int maxVideoFrameRate)
    +
    Description copied from class: TrackSelectionParameters.Builder
    Sets the maximum allowed video frame rate.
    +
    Overrides:
    +
    setMaxVideoFrameRate in class TrackSelectionParameters.Builder
    Parameters:
    maxVideoFrameRate - Maximum allowed video frame rate in hertz.
    Returns:
    @@ -650,8 +662,11 @@

    setMaxVideoFrameRate

  • setMaxVideoBitrate

    public DefaultTrackSelector.ParametersBuilder setMaxVideoBitrate​(int maxVideoBitrate)
    +
    Description copied from class: TrackSelectionParameters.Builder
    Sets the maximum allowed video bitrate.
    +
    Overrides:
    +
    setMaxVideoBitrate in class TrackSelectionParameters.Builder
    Parameters:
    maxVideoBitrate - Maximum allowed video bitrate in bits per second.
    Returns:
    @@ -667,8 +682,11 @@

    setMaxVideoBitrate

    setMinVideoSize

    public DefaultTrackSelector.ParametersBuilder setMinVideoSize​(int minVideoWidth,
                                                                   int minVideoHeight)
    +
    Description copied from class: TrackSelectionParameters.Builder
    Sets the minimum allowed video width and height.
    +
    Overrides:
    +
    setMinVideoSize in class TrackSelectionParameters.Builder
    Parameters:
    minVideoWidth - Minimum allowed video width in pixels.
    minVideoHeight - Minimum allowed video height in pixels.
    @@ -684,8 +702,11 @@

    setMinVideoSize

  • setMinVideoFrameRate

    public DefaultTrackSelector.ParametersBuilder setMinVideoFrameRate​(int minVideoFrameRate)
    +
    Description copied from class: TrackSelectionParameters.Builder
    Sets the minimum allowed video frame rate.
    +
    Overrides:
    +
    setMinVideoFrameRate in class TrackSelectionParameters.Builder
    Parameters:
    minVideoFrameRate - Minimum allowed video frame rate in hertz.
    Returns:
    @@ -700,8 +721,11 @@

    setMinVideoFrameRate

  • setMinVideoBitrate

    public DefaultTrackSelector.ParametersBuilder setMinVideoBitrate​(int minVideoBitrate)
    +
    Description copied from class: TrackSelectionParameters.Builder
    Sets the minimum allowed video bitrate.
    +
    Overrides:
    +
    setMinVideoBitrate in class TrackSelectionParameters.Builder
    Parameters:
    minVideoBitrate - Minimum allowed video bitrate in bits per second.
    Returns:
    @@ -774,9 +798,12 @@

    setAllowVideoNonSeamlessAdaptiveness

    setViewportSizeToPhysicalDisplaySize

    public DefaultTrackSelector.ParametersBuilder setViewportSizeToPhysicalDisplaySize​(Context context,
                                                                                        boolean viewportOrientationMayChange)
    -
    Equivalent to calling setViewportSize(int, int, boolean) with the viewport size +
    Description copied from class: TrackSelectionParameters.Builder
    +
    +
    Overrides:
    +
    setViewportSizeToPhysicalDisplaySize in class TrackSelectionParameters.Builder
    Parameters:
    context - Any context.
    viewportOrientationMayChange - Whether the viewport orientation may change during @@ -793,9 +820,12 @@

    setViewportSizeToPhysicalDisplaySize

  • clearViewportSizeConstraints

    public DefaultTrackSelector.ParametersBuilder clearViewportSizeConstraints()
    -
    Equivalent to setViewportSize(Integer.MAX_VALUE, Integer.MAX_VALUE, + +
    +
    Overrides:
    +
    clearViewportSizeConstraints in class TrackSelectionParameters.Builder
    Returns:
    This builder.
    @@ -810,9 +840,12 @@

    setViewportSize

    public DefaultTrackSelector.ParametersBuilder setViewportSize​(int viewportWidth,
                                                                   int viewportHeight,
                                                                   boolean viewportOrientationMayChange)
    +
    Description copied from class: TrackSelectionParameters.Builder
    Sets the viewport size to constrain adaptive video selections so that only tracks suitable for the viewport are selected.
    +
    Overrides:
    +
    setViewportSize in class TrackSelectionParameters.Builder
    Parameters:
    viewportWidth - Viewport width in pixels.
    viewportHeight - Viewport height in pixels.
    @@ -831,8 +864,11 @@

    setViewportSize

    setPreferredVideoMimeType

    public DefaultTrackSelector.ParametersBuilder setPreferredVideoMimeType​(@Nullable
                                                                             String mimeType)
    +
    Description copied from class: TrackSelectionParameters.Builder
    Sets the preferred sample MIME type for video tracks.
    +
    Overrides:
    +
    setPreferredVideoMimeType in class TrackSelectionParameters.Builder
    Parameters:
    mimeType - The preferred MIME type for video tracks, or null to clear a previously set preference.
    @@ -848,8 +884,11 @@

    setPreferredVideoMimeType

  • setPreferredVideoMimeTypes

    public DefaultTrackSelector.ParametersBuilder setPreferredVideoMimeTypes​(String... mimeTypes)
    +
    Description copied from class: TrackSelectionParameters.Builder
    Sets the preferred sample MIME types for video tracks.
    +
    Overrides:
    +
    setPreferredVideoMimeTypes in class TrackSelectionParameters.Builder
    Parameters:
    mimeTypes - The preferred MIME types for video tracks in order of preference, or an empty list for no preference.
    @@ -927,8 +966,11 @@

    setPreferredAudioRoleFlags

  • setMaxAudioChannelCount

    public DefaultTrackSelector.ParametersBuilder setMaxAudioChannelCount​(int maxAudioChannelCount)
    +
    Description copied from class: TrackSelectionParameters.Builder
    Sets the maximum allowed audio channel count.
    +
    Overrides:
    +
    setMaxAudioChannelCount in class TrackSelectionParameters.Builder
    Parameters:
    maxAudioChannelCount - Maximum allowed audio channel count.
    Returns:
    @@ -943,8 +985,11 @@

    setMaxAudioChannelCount

  • setMaxAudioBitrate

    public DefaultTrackSelector.ParametersBuilder setMaxAudioBitrate​(int maxAudioBitrate)
    +
    Description copied from class: TrackSelectionParameters.Builder
    Sets the maximum allowed audio bitrate.
    +
    Overrides:
    +
    setMaxAudioBitrate in class TrackSelectionParameters.Builder
    Parameters:
    maxAudioBitrate - Maximum allowed audio bitrate in bits per second.
    Returns:
    @@ -1034,8 +1079,11 @@

    setAllowAudioMixedChannelCountAdaptiveness

    setPreferredAudioMimeType

    public DefaultTrackSelector.ParametersBuilder setPreferredAudioMimeType​(@Nullable
                                                                             String mimeType)
    +
    Description copied from class: TrackSelectionParameters.Builder
    Sets the preferred sample MIME type for audio tracks.
    +
    Overrides:
    +
    setPreferredAudioMimeType in class TrackSelectionParameters.Builder
    Parameters:
    mimeType - The preferred MIME type for audio tracks, or null to clear a previously set preference.
    @@ -1051,8 +1099,11 @@

    setPreferredAudioMimeType

  • setPreferredAudioMimeTypes

    public DefaultTrackSelector.ParametersBuilder setPreferredAudioMimeTypes​(String... mimeTypes)
    +
    Description copied from class: TrackSelectionParameters.Builder
    Sets the preferred sample MIME types for audio tracks.
    +
    Overrides:
    +
    setPreferredAudioMimeTypes in class TrackSelectionParameters.Builder
    Parameters:
    mimeTypes - The preferred MIME types for audio tracks in order of preference, or an empty list for no preference.
    @@ -1175,11 +1226,8 @@

    setSelectUndeterminedTextLanguage

    setDisabledTextTrackSelectionFlags

    public DefaultTrackSelector.ParametersBuilder setDisabledTextTrackSelectionFlags​(@SelectionFlags
                                                                                      int disabledTextTrackSelectionFlags)
    -
    Description copied from class: TrackSelectionParameters.Builder
    Sets a bitmask of selection flags that are disabled for text track selections.
    -
    Overrides:
    -
    setDisabledTextTrackSelectionFlags in class TrackSelectionParameters.Builder
    Parameters:
    disabledTextTrackSelectionFlags - A bitmask of C.SelectionFlags that are disabled for text track selections.
    @@ -1195,9 +1243,12 @@

    setDisabledTextTrackSelectionFlags

  • setForceLowestBitrate

    public DefaultTrackSelector.ParametersBuilder setForceLowestBitrate​(boolean forceLowestBitrate)
    +
    Description copied from class: TrackSelectionParameters.Builder
    Sets whether to force selection of the single lowest bitrate audio and video tracks that comply with all other constraints.
    +
    Overrides:
    +
    setForceLowestBitrate in class TrackSelectionParameters.Builder
    Parameters:
    forceLowestBitrate - Whether to force selection of the single lowest bitrate audio and video tracks.
    @@ -1213,9 +1264,12 @@

    setForceLowestBitrate

  • setForceHighestSupportedBitrate

    public DefaultTrackSelector.ParametersBuilder setForceHighestSupportedBitrate​(boolean forceHighestSupportedBitrate)
    +
    Description copied from class: TrackSelectionParameters.Builder
    Sets whether to force selection of the highest bitrate audio and video tracks that comply with all other constraints.
    +
    Overrides:
    +
    setForceHighestSupportedBitrate in class TrackSelectionParameters.Builder
    Parameters:
    forceHighestSupportedBitrate - Whether to force selection of the highest bitrate audio and video tracks.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.html b/docs/doc/reference/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.html index 219e7556e9a..e36472f387e 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.html +++ b/docs/doc/reference/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.html @@ -148,7 +148,7 @@

    Class DefaultTrackSelector<
    A default TrackSelector suitable for most use cases. Track selections are made according to configurable DefaultTrackSelector.Parameters, which can be set by calling setParameters(Parameters). -

    Modifying parameters

    +

    Modifying parameters

    To modify only some aspects of the parameters currently used by a selector, it's possible to obtain a DefaultTrackSelector.ParametersBuilder initialized with the current DefaultTrackSelector.Parameters. The desired @@ -181,7 +181,7 @@

    Modifying parameters

    Selection DefaultTrackSelector.Parameters support many different options, some of which are described below. -

    Selecting specific tracks

    +

    Selecting specific tracks

    Track selection overrides can be used to select specific tracks. To specify an override for a renderer, it's first necessary to obtain the tracks that have been mapped to it: @@ -208,7 +208,7 @@

    Selecting specific tracks

    .setSelectionOverride(rendererIndex, rendererTrackGroups, selectionOverride)); -

    Constraint based track selection

    +

    Constraint based track selection

    Whilst track selection overrides make it possible to select specific tracks, the recommended way of controlling which tracks are selected is by specifying constraints. For example consider the @@ -236,14 +236,14 @@

    Constraint based track selection

    only applied to periods whose tracks match those for which the override was set. -

    Disabling renderers

    +

    Disabling renderers

    Renderers can be disabled using DefaultTrackSelector.ParametersBuilder.setRendererDisabled(int, boolean). Disabling a renderer differs from setting a null override because the renderer is disabled unconditionally, whereas a null override is applied only when the track groups available to the renderer match the TrackGroupArray for which it was specified. -

    Tunneling

    +

    Tunneling

    Tunneled playback can be enabled in cases where the combination of renderers and selected tracks support it. Tunneled playback is enabled by passing an audio session ID to DefaultTrackSelector.ParametersBuilder.setTunnelingEnabled(boolean).
    @@ -285,7 +285,7 @@

    Nested Class Summary

    static class  DefaultTrackSelector.Parameters -
    Extends TrackSelectionParameters by adding fields that are specific to DefaultTrackSelector.
    +
    Extends DefaultTrackSelector.Parameters by adding fields that are specific to DefaultTrackSelector.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/trackselection/ExoTrackSelection.html b/docs/doc/reference/com/google/android/exoplayer2/trackselection/ExoTrackSelection.html index 8f402f06b36..3d1c5ea47c5 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/trackselection/ExoTrackSelection.html +++ b/docs/doc/reference/com/google/android/exoplayer2/trackselection/ExoTrackSelection.html @@ -286,7 +286,7 @@

    Method Summary

    void -onPlaybackSpeed​(float speed) +onPlaybackSpeed​(float playbackSpeed)
    Called to notify the selection of the current playback speed.
    @@ -432,12 +432,12 @@

    getSelectionData

    • onPlaybackSpeed

      -
      void onPlaybackSpeed​(float speed)
      +
      void onPlaybackSpeed​(float playbackSpeed)
      Called to notify the selection of the current playback speed. The playback speed may affect adaptive track selection.
      Parameters:
      -
      speed - The factor by which playback is sped up.
      +
      playbackSpeed - The factor by which playback is sped up.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/trackselection/MappingTrackSelector.html b/docs/doc/reference/com/google/android/exoplayer2/trackselection/MappingTrackSelector.html index 2361d274a07..cb94cbd21eb 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/trackselection/MappingTrackSelector.html +++ b/docs/doc/reference/com/google/android/exoplayer2/trackselection/MappingTrackSelector.html @@ -235,7 +235,7 @@

    Method Summary

    TrackSelectorResult selectTracks​(RendererCapabilities[] rendererCapabilities, TrackGroupArray trackGroups, - MediaSource.MediaPeriodId mediaPeriodId, + MediaSource.MediaPeriodId periodId, Timeline timeline)
    Called by the player to perform a track selection.
    @@ -340,7 +340,7 @@

    onSelectionActivated

    selectTracks

    public final TrackSelectorResult selectTracks​(RendererCapabilities[] rendererCapabilities,
                                                   TrackGroupArray trackGroups,
    -                                              MediaSource.MediaPeriodId mediaPeriodId,
    +                                              MediaSource.MediaPeriodId periodId,
                                                   Timeline timeline)
                                            throws ExoPlaybackException
    Description copied from class: TrackSelector
    @@ -352,7 +352,7 @@

    selectTracks

    rendererCapabilities - The RendererCapabilities of the renderers for which tracks are to be selected.
    trackGroups - The available track groups.
    -
    mediaPeriodId - The MediaSource.MediaPeriodId of the period for which tracks are to be selected.
    +
    periodId - The MediaSource.MediaPeriodId of the period for which tracks are to be selected.
    timeline - The Timeline holding the period for which tracks are to be selected.
    Returns:
    A TrackSelectorResult describing the track selections.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.Builder.html b/docs/doc/reference/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.Builder.html index 6220e9a8f98..be9e02a8d6b 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.Builder.html +++ b/docs/doc/reference/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.Builder.html @@ -25,7 +25,7 @@ catch(err) { } //--> -var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10}; +var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10,"i21":10,"i22":10,"i23":10,"i24":10,"i25":10,"i26":10,"i27":10}; var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -157,23 +157,31 @@

    Constructor Summary

    - + + + + + + + + +
    Constructors 
    ConstructorModifierConstructor Description
      Builder()
    Deprecated. -
    Context constraints will not be set when using this constructor.
    +
    Context constraints will not be set using this constructor.
      Builder​(Context context)
    Creates a builder with default initial values.
    protected Builder​(TrackSelectionParameters initialValues) 
  • @@ -201,40 +209,143 @@

    Method Summary

    TrackSelectionParameters.Builder -setDisabledTextTrackSelectionFlags​(int disabledTextTrackSelectionFlags) +clearVideoSizeConstraints() -
    Sets a bitmask of selection flags that are disabled for text track selections.
    + TrackSelectionParameters.Builder +clearViewportSizeConstraints() + + + + + +TrackSelectionParameters.Builder +setForceHighestSupportedBitrate​(boolean forceHighestSupportedBitrate) + +
    Sets whether to force selection of the highest bitrate audio and video tracks that comply + with all other constraints.
    + + + +TrackSelectionParameters.Builder +setForceLowestBitrate​(boolean forceLowestBitrate) + +
    Sets whether to force selection of the single lowest bitrate audio and video tracks that + comply with all other constraints.
    + + + +TrackSelectionParameters.Builder +setMaxAudioBitrate​(int maxAudioBitrate) + +
    Sets the maximum allowed audio bitrate.
    + + + +TrackSelectionParameters.Builder +setMaxAudioChannelCount​(int maxAudioChannelCount) + +
    Sets the maximum allowed audio channel count.
    + + + +TrackSelectionParameters.Builder +setMaxVideoBitrate​(int maxVideoBitrate) + +
    Sets the maximum allowed video bitrate.
    + + + +TrackSelectionParameters.Builder +setMaxVideoFrameRate​(int maxVideoFrameRate) + +
    Sets the maximum allowed video frame rate.
    + + + +TrackSelectionParameters.Builder +setMaxVideoSize​(int maxVideoWidth, + int maxVideoHeight) + +
    Sets the maximum allowed video width and height.
    + + + +TrackSelectionParameters.Builder +setMaxVideoSizeSd() + + + + + +TrackSelectionParameters.Builder +setMinVideoBitrate​(int minVideoBitrate) + +
    Sets the minimum allowed video bitrate.
    + + + +TrackSelectionParameters.Builder +setMinVideoFrameRate​(int minVideoFrameRate) + +
    Sets the minimum allowed video frame rate.
    + + + +TrackSelectionParameters.Builder +setMinVideoSize​(int minVideoWidth, + int minVideoHeight) + +
    Sets the minimum allowed video width and height.
    + + + +TrackSelectionParameters.Builder setPreferredAudioLanguage​(String preferredAudioLanguage)
    Sets the preferred language for audio and forced text tracks.
    - + TrackSelectionParameters.Builder setPreferredAudioLanguages​(String... preferredAudioLanguages)
    Sets the preferred languages for audio and forced text tracks.
    - + +TrackSelectionParameters.Builder +setPreferredAudioMimeType​(String mimeType) + +
    Sets the preferred sample MIME type for audio tracks.
    + + + +TrackSelectionParameters.Builder +setPreferredAudioMimeTypes​(String... mimeTypes) + +
    Sets the preferred sample MIME types for audio tracks.
    + + + TrackSelectionParameters.Builder setPreferredAudioRoleFlags​(int preferredAudioRoleFlags)
    Sets the preferred C.RoleFlags for audio tracks.
    - + TrackSelectionParameters.Builder setPreferredTextLanguage​(String preferredTextLanguage)
    Sets the preferred language for text tracks.
    - + TrackSelectionParameters.Builder setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings​(Context context) @@ -242,21 +353,35 @@

    Method Summary

    settings of CaptioningManager.
  • - + TrackSelectionParameters.Builder setPreferredTextLanguages​(String... preferredTextLanguages)
    Sets the preferred languages for text tracks.
    - + TrackSelectionParameters.Builder setPreferredTextRoleFlags​(int preferredTextRoleFlags)
    Sets the preferred C.RoleFlags for text tracks.
    - + +TrackSelectionParameters.Builder +setPreferredVideoMimeType​(String mimeType) + +
    Sets the preferred sample MIME type for video tracks.
    + + + +TrackSelectionParameters.Builder +setPreferredVideoMimeTypes​(String... mimeTypes) + +
    Sets the preferred sample MIME types for video tracks.
    + + + TrackSelectionParameters.Builder setSelectUndeterminedTextLanguage​(boolean selectUndeterminedTextLanguage) @@ -265,6 +390,25 @@

    Method Summary

    preferred language is unset.
  • + +TrackSelectionParameters.Builder +setViewportSize​(int viewportWidth, + int viewportHeight, + boolean viewportOrientationMayChange) + +
    Sets the viewport size to constrain adaptive video selections so that only tracks suitable + for the viewport are selected.
    + + + +TrackSelectionParameters.Builder +setViewportSizeToPhysicalDisplaySize​(Context context, + boolean viewportOrientationMayChange) + +
    Equivalent to calling setViewportSize(int, int, boolean) with the viewport size + obtained from Util.getCurrentDisplayModeSize(Context).
    + +
  • - +
  • @@ -327,6 +484,226 @@

    Builder

    Method Detail

    + + + + + + + + + + + +
      +
    • +

      setMaxVideoSize

      +
      public TrackSelectionParameters.Builder setMaxVideoSize​(int maxVideoWidth,
      +                                                        int maxVideoHeight)
      +
      Sets the maximum allowed video width and height.
      +
      +
      Parameters:
      +
      maxVideoWidth - Maximum allowed video width in pixels.
      +
      maxVideoHeight - Maximum allowed video height in pixels.
      +
      Returns:
      +
      This builder.
      +
      +
    • +
    + + + +
      +
    • +

      setMaxVideoFrameRate

      +
      public TrackSelectionParameters.Builder setMaxVideoFrameRate​(int maxVideoFrameRate)
      +
      Sets the maximum allowed video frame rate.
      +
      +
      Parameters:
      +
      maxVideoFrameRate - Maximum allowed video frame rate in hertz.
      +
      Returns:
      +
      This builder.
      +
      +
    • +
    + + + +
      +
    • +

      setMaxVideoBitrate

      +
      public TrackSelectionParameters.Builder setMaxVideoBitrate​(int maxVideoBitrate)
      +
      Sets the maximum allowed video bitrate.
      +
      +
      Parameters:
      +
      maxVideoBitrate - Maximum allowed video bitrate in bits per second.
      +
      Returns:
      +
      This builder.
      +
      +
    • +
    + + + +
      +
    • +

      setMinVideoSize

      +
      public TrackSelectionParameters.Builder setMinVideoSize​(int minVideoWidth,
      +                                                        int minVideoHeight)
      +
      Sets the minimum allowed video width and height.
      +
      +
      Parameters:
      +
      minVideoWidth - Minimum allowed video width in pixels.
      +
      minVideoHeight - Minimum allowed video height in pixels.
      +
      Returns:
      +
      This builder.
      +
      +
    • +
    + + + +
      +
    • +

      setMinVideoFrameRate

      +
      public TrackSelectionParameters.Builder setMinVideoFrameRate​(int minVideoFrameRate)
      +
      Sets the minimum allowed video frame rate.
      +
      +
      Parameters:
      +
      minVideoFrameRate - Minimum allowed video frame rate in hertz.
      +
      Returns:
      +
      This builder.
      +
      +
    • +
    + + + +
      +
    • +

      setMinVideoBitrate

      +
      public TrackSelectionParameters.Builder setMinVideoBitrate​(int minVideoBitrate)
      +
      Sets the minimum allowed video bitrate.
      +
      +
      Parameters:
      +
      minVideoBitrate - Minimum allowed video bitrate in bits per second.
      +
      Returns:
      +
      This builder.
      +
      +
    • +
    + + + + + + + + + + + +
      +
    • +

      setViewportSize

      +
      public TrackSelectionParameters.Builder setViewportSize​(int viewportWidth,
      +                                                        int viewportHeight,
      +                                                        boolean viewportOrientationMayChange)
      +
      Sets the viewport size to constrain adaptive video selections so that only tracks suitable + for the viewport are selected.
      +
      +
      Parameters:
      +
      viewportWidth - Viewport width in pixels.
      +
      viewportHeight - Viewport height in pixels.
      +
      viewportOrientationMayChange - Whether the viewport orientation may change during + playback.
      +
      Returns:
      +
      This builder.
      +
      +
    • +
    + + + +
      +
    • +

      setPreferredVideoMimeType

      +
      public TrackSelectionParameters.Builder setPreferredVideoMimeType​(@Nullable
      +                                                                  String mimeType)
      +
      Sets the preferred sample MIME type for video tracks.
      +
      +
      Parameters:
      +
      mimeType - The preferred MIME type for video tracks, or null to clear a + previously set preference.
      +
      Returns:
      +
      This builder.
      +
      +
    • +
    + + + +
      +
    • +

      setPreferredVideoMimeTypes

      +
      public TrackSelectionParameters.Builder setPreferredVideoMimeTypes​(String... mimeTypes)
      +
      Sets the preferred sample MIME types for video tracks.
      +
      +
      Parameters:
      +
      mimeTypes - The preferred MIME types for video tracks in order of preference, or an + empty list for no preference.
      +
      Returns:
      +
      This builder.
      +
      +
    • +
    @@ -380,6 +757,73 @@

    setPreferredAudioRoleFlags

  • + + + +
      +
    • +

      setMaxAudioChannelCount

      +
      public TrackSelectionParameters.Builder setMaxAudioChannelCount​(int maxAudioChannelCount)
      +
      Sets the maximum allowed audio channel count.
      +
      +
      Parameters:
      +
      maxAudioChannelCount - Maximum allowed audio channel count.
      +
      Returns:
      +
      This builder.
      +
      +
    • +
    + + + +
      +
    • +

      setMaxAudioBitrate

      +
      public TrackSelectionParameters.Builder setMaxAudioBitrate​(int maxAudioBitrate)
      +
      Sets the maximum allowed audio bitrate.
      +
      +
      Parameters:
      +
      maxAudioBitrate - Maximum allowed audio bitrate in bits per second.
      +
      Returns:
      +
      This builder.
      +
      +
    • +
    + + + +
      +
    • +

      setPreferredAudioMimeType

      +
      public TrackSelectionParameters.Builder setPreferredAudioMimeType​(@Nullable
      +                                                                  String mimeType)
      +
      Sets the preferred sample MIME type for audio tracks.
      +
      +
      Parameters:
      +
      mimeType - The preferred MIME type for audio tracks, or null to clear a + previously set preference.
      +
      Returns:
      +
      This builder.
      +
      +
    • +
    + + + +
      +
    • +

      setPreferredAudioMimeTypes

      +
      public TrackSelectionParameters.Builder setPreferredAudioMimeTypes​(String... mimeTypes)
      +
      Sets the preferred sample MIME types for audio tracks.
      +
      +
      Parameters:
      +
      mimeTypes - The preferred MIME types for audio tracks in order of preference, or an + empty list for no preference.
      +
      Returns:
      +
      This builder.
      +
      +
    • +
    @@ -471,19 +915,37 @@

    setSelectUndeterminedTextLanguage

  • - + + + +
      +
    • +

      setForceLowestBitrate

      +
      public TrackSelectionParameters.Builder setForceLowestBitrate​(boolean forceLowestBitrate)
      +
      Sets whether to force selection of the single lowest bitrate audio and video tracks that + comply with all other constraints.
      +
      +
      Parameters:
      +
      forceLowestBitrate - Whether to force selection of the single lowest bitrate audio and + video tracks.
      +
      Returns:
      +
      This builder.
      +
      +
    • +
    +
    • -

      setDisabledTextTrackSelectionFlags

      -
      public TrackSelectionParameters.Builder setDisabledTextTrackSelectionFlags​(@SelectionFlags
      -                                                                           int disabledTextTrackSelectionFlags)
      -
      Sets a bitmask of selection flags that are disabled for text track selections.
      +

      setForceHighestSupportedBitrate

      +
      public TrackSelectionParameters.Builder setForceHighestSupportedBitrate​(boolean forceHighestSupportedBitrate)
      +
      Sets whether to force selection of the highest bitrate audio and video tracks that comply + with all other constraints.
      Parameters:
      -
      disabledTextTrackSelectionFlags - A bitmask of C.SelectionFlags that are - disabled for text track selections.
      +
      forceHighestSupportedBitrate - Whether to force selection of the highest bitrate audio + and video tracks.
      Returns:
      This builder.
      diff --git a/docs/doc/reference/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.html b/docs/doc/reference/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.html index b2918fb67cd..fcfdea14653 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.html +++ b/docs/doc/reference/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.html @@ -88,13 +88,13 @@
    • Summary: 
    • Nested | 
    • Field | 
    • -
    • Constr | 
    • +
    • Constr | 
    • Method
  • @@ -215,13 +215,92 @@

    Field Summary

    +boolean +forceHighestSupportedBitrate + +
    Whether to force selection of the highest bitrate audio and video tracks that comply with all + other constraints.
    + + + +boolean +forceLowestBitrate + +
    Whether to force selection of the single lowest bitrate audio and video tracks that comply with + all other constraints.
    + + + int -disabledTextTrackSelectionFlags +maxAudioBitrate -
    Bitmask of selection flags that are disabled for text track selections.
    +
    Maximum allowed audio bitrate in bits per second.
    +int +maxAudioChannelCount + +
    Maximum allowed audio channel count.
    + + + +int +maxVideoBitrate + +
    Maximum allowed video bitrate in bits per second.
    + + + +int +maxVideoFrameRate + +
    Maximum allowed video frame rate in hertz.
    + + + +int +maxVideoHeight + +
    Maximum allowed video height in pixels.
    + + + +int +maxVideoWidth + +
    Maximum allowed video width in pixels.
    + + + +int +minVideoBitrate + +
    Minimum allowed video bitrate in bits per second.
    + + + +int +minVideoFrameRate + +
    Minimum allowed video frame rate in hertz.
    + + + +int +minVideoHeight + +
    Minimum allowed video height in pixels.
    + + + +int +minVideoWidth + +
    Minimum allowed video width in pixels.
    + + + ImmutableList<String> preferredAudioLanguages @@ -229,6 +308,14 @@

    Field Summary

    order of preference.
    + +ImmutableList<String> +preferredAudioMimeTypes + +
    The preferred sample MIME types for audio tracks in order of preference, or an empty list for + no preference.
    + + int preferredAudioRoleFlags @@ -251,12 +338,41 @@

    Field Summary

    +ImmutableList<String> +preferredVideoMimeTypes + +
    The preferred sample MIME types for video tracks in order of preference, or an empty list for + no preference.
    + + + boolean selectUndeterminedTextLanguage
    Whether a text track with undetermined language should be selected if no track with preferredTextLanguages is available, or if preferredTextLanguages is unset.
    + +int +viewportHeight + +
    Viewport height in pixels.
    + + + +boolean +viewportOrientationMayChange + +
    Whether the viewport orientation may change during playback.
    + + + +int +viewportWidth + +
    Viewport width in pixels.
    + +
    • @@ -268,6 +384,29 @@

      Fields inherited from interface android.os. + +
      + + + + + + + +
        +
      • +

        maxVideoWidth

        +
        public final int maxVideoWidth
        +
        Maximum allowed video width in pixels. The default value is Integer.MAX_VALUE (i.e. no + constraint). + +

        To constrain adaptive video track selections to be suitable for a given viewport (the region + of the display within which video will be played), use (viewportWidth, viewportHeight and viewportOrientationMayChange) instead.

        +
      • +
      + + + +
        +
      • +

        maxVideoHeight

        +
        public final int maxVideoHeight
        +
        Maximum allowed video height in pixels. The default value is Integer.MAX_VALUE (i.e. no + constraint). + +

        To constrain adaptive video track selections to be suitable for a given viewport (the region + of the display within which video will be played), use (viewportWidth, viewportHeight and viewportOrientationMayChange) instead.

        +
      • +
      + + + +
        +
      • +

        maxVideoFrameRate

        +
        public final int maxVideoFrameRate
        +
        Maximum allowed video frame rate in hertz. The default value is Integer.MAX_VALUE (i.e. + no constraint).
        +
      • +
      + + + +
        +
      • +

        maxVideoBitrate

        +
        public final int maxVideoBitrate
        +
        Maximum allowed video bitrate in bits per second. The default value is Integer.MAX_VALUE (i.e. no constraint).
        +
      • +
      + + + +
        +
      • +

        minVideoWidth

        +
        public final int minVideoWidth
        +
        Minimum allowed video width in pixels. The default value is 0 (i.e. no constraint).
        +
      • +
      + + + +
        +
      • +

        minVideoHeight

        +
        public final int minVideoHeight
        +
        Minimum allowed video height in pixels. The default value is 0 (i.e. no constraint).
        +
      • +
      + + + +
        +
      • +

        minVideoFrameRate

        +
        public final int minVideoFrameRate
        +
        Minimum allowed video frame rate in hertz. The default value is 0 (i.e. no constraint).
        +
      • +
      + + + +
        +
      • +

        minVideoBitrate

        +
        public final int minVideoBitrate
        +
        Minimum allowed video bitrate in bits per second. The default value is 0 (i.e. no constraint).
        +
      • +
      + + + +
        +
      • +

        viewportWidth

        +
        public final int viewportWidth
        +
        Viewport width in pixels. Constrains video track selections for adaptive content so that only + tracks suitable for the viewport are selected. The default value is the physical width of the + primary display, in pixels.
        +
      • +
      + + + +
        +
      • +

        viewportHeight

        +
        public final int viewportHeight
        +
        Viewport height in pixels. Constrains video track selections for adaptive content so that only + tracks suitable for the viewport are selected. The default value is the physical height of the + primary display, in pixels.
        +
      • +
      + + + +
        +
      • +

        viewportOrientationMayChange

        +
        public final boolean viewportOrientationMayChange
        +
        Whether the viewport orientation may change during playback. Constrains video track selections + for adaptive content so that only tracks suitable for the viewport are selected. The default + value is true.
        +
      • +
      + + + +
        +
      • +

        preferredVideoMimeTypes

        +
        public final ImmutableList<String> preferredVideoMimeTypes
        +
        The preferred sample MIME types for video tracks in order of preference, or an empty list for + no preference. The default is an empty list.
        +
      • +
      @@ -397,6 +683,38 @@

      preferredAudioRoleFlags

      there is one, or the first track if there's no default. The default value is 0.

    + + + +
      +
    • +

      maxAudioChannelCount

      +
      public final int maxAudioChannelCount
      +
      Maximum allowed audio channel count. The default value is Integer.MAX_VALUE (i.e. no + constraint).
      +
    • +
    + + + +
      +
    • +

      maxAudioBitrate

      +
      public final int maxAudioBitrate
      +
      Maximum allowed audio bitrate in bits per second. The default value is Integer.MAX_VALUE (i.e. no constraint).
      +
    • +
    + + + +
      +
    • +

      preferredAudioMimeTypes

      +
      public final ImmutableList<String> preferredAudioMimeTypes
      +
      The preferred sample MIME types for audio tracks in order of preference, or an empty list for + no preference. The default is an empty list.
      +
    • +
    @@ -435,24 +753,45 @@

    selectUndeterminedTextLanguage

    default value is false. - +
    • -

      disabledTextTrackSelectionFlags

      -
      @SelectionFlags
      -public final int disabledTextTrackSelectionFlags
      -
      Bitmask of selection flags that are disabled for text track selections. See C.SelectionFlags. The default value is 0 (i.e. no flags).
      +

      forceLowestBitrate

      +
      public final boolean forceLowestBitrate
      +
      Whether to force selection of the single lowest bitrate audio and video tracks that comply with + all other constraints. The default value is false.
    - +
    • -

      CREATOR

      -
      public static final Parcelable.Creator<TrackSelectionParameters> CREATOR
      +

      forceHighestSupportedBitrate

      +
      public final boolean forceHighestSupportedBitrate
      +
      Whether to force selection of the highest bitrate audio and video tracks that comply with all + other constraints. The default value is false.
      +
    • +
    + + + + +
    + diff --git a/docs/doc/reference/com/google/android/exoplayer2/trackselection/TrackSelectionUtil.html b/docs/doc/reference/com/google/android/exoplayer2/trackselection/TrackSelectionUtil.html index 26fa5d0f64a..aa3d8483245 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/trackselection/TrackSelectionUtil.html +++ b/docs/doc/reference/com/google/android/exoplayer2/trackselection/TrackSelectionUtil.html @@ -25,7 +25,7 @@ catch(err) { } //--> -var data = {"i0":9,"i1":9,"i2":9}; +var data = {"i0":9,"i1":9,"i2":9,"i3":9}; var tabs = {65535:["t0","All Methods"],1:["t1","Static Methods"],8:["t4","Concrete Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -178,6 +178,14 @@

    Method Summary

    Description +static LoadErrorHandlingPolicy.FallbackOptions +createFallbackOptions​(ExoTrackSelection trackSelection) + +
    Returns the LoadErrorHandlingPolicy.FallbackOptions with the tracks of the given ExoTrackSelection and with a single location option indicating that there are no alternative + locations available.
    + + + static @NullableType ExoTrackSelection[] createTrackSelectionsForDefinitions​(@NullableType ExoTrackSelection.Definition[] definitions, TrackSelectionUtil.AdaptiveTrackSelectionFactory adaptiveTrackSelectionFactory) @@ -186,7 +194,7 @@

    Method Summary

    multi-track adaptive selection. - + static boolean hasTrackOfType​(TrackSelectionArray trackSelections, int trackType) @@ -194,7 +202,7 @@

    Method Summary

    Returns if a TrackSelectionArray has at least one track of the given type.
    - + static DefaultTrackSelector.Parameters updateParametersWithOverride​(DefaultTrackSelector.Parameters parameters, int rendererIndex, @@ -279,7 +287,7 @@

    updateParametersWithOverride

    -
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/trackselection/TrackSelector.html b/docs/doc/reference/com/google/android/exoplayer2/trackselection/TrackSelector.html index 2cd9c3ad250..78f23a73189 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/trackselection/TrackSelector.html +++ b/docs/doc/reference/com/google/android/exoplayer2/trackselection/TrackSelector.html @@ -139,7 +139,7 @@

    Class TrackSelector

    the player's Renderers. The DefaultTrackSelector implementation should be suitable for most use cases. -

    Interactions with the player

    +

    Interactions with the player

    The following interactions occur between the player and its track selector during playback. @@ -168,7 +168,7 @@

    Interactions with the player

    will call TrackSelector.InvalidationListener.onTrackSelectionsInvalidated(). -

    Renderer configuration

    +

    Renderer configuration

    The TrackSelectorResult returned by selectTracks(RendererCapabilities[], TrackGroupArray, MediaPeriodId, Timeline) contains not only TrackSelections for each @@ -180,7 +180,7 @@

    Renderer configuration

    configure renderers in a particular way if certain tracks are selected. Hence it makes sense to determine the track selection and corresponding renderer configurations in a single step. -

    Threading model

    +

    Threading model

    All calls made by the player into the track selector are on the player's internal playback thread. The track selector may call TrackSelector.InvalidationListener.onTrackSelectionsInvalidated() diff --git a/docs/doc/reference/com/google/android/exoplayer2/trackselection/package-summary.html b/docs/doc/reference/com/google/android/exoplayer2/trackselection/package-summary.html index 7064bd5762f..3f67e9ba0f0 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/trackselection/package-summary.html +++ b/docs/doc/reference/com/google/android/exoplayer2/trackselection/package-summary.html @@ -191,7 +191,7 @@

    Package com.google.android.exoplayer2.tra DefaultTrackSelector.Parameters -
    Extends TrackSelectionParameters by adding fields that are specific to DefaultTrackSelector.
    +
    Extends DefaultTrackSelector.Parameters by adding fields that are specific to DefaultTrackSelector.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/trackselection/package-tree.html b/docs/doc/reference/com/google/android/exoplayer2/trackselection/package-tree.html index 0a9be52427b..7464e1a1b05 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/trackselection/package-tree.html +++ b/docs/doc/reference/com/google/android/exoplayer2/trackselection/package-tree.html @@ -123,7 +123,7 @@

    Class Hierarchy

  • com.google.android.exoplayer2.trackselection.TrackSelectionArray
  • com.google.android.exoplayer2.trackselection.TrackSelectionParameters (implements android.os.Parcelable)
  • com.google.android.exoplayer2.trackselection.TrackSelectionParameters.Builder diff --git a/docs/doc/reference/com/google/android/exoplayer2/ui/CaptionStyleCompat.html b/docs/doc/reference/com/google/android/exoplayer2/ui/CaptionStyleCompat.html index adc3cb9589d..88ecb8da1fd 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ui/CaptionStyleCompat.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ui/CaptionStyleCompat.html @@ -476,12 +476,13 @@

    edgeType

    @EdgeType
     public final int edgeType
  • diff --git a/docs/doc/reference/com/google/android/exoplayer2/ui/DefaultMediaDescriptionAdapter.html b/docs/doc/reference/com/google/android/exoplayer2/ui/DefaultMediaDescriptionAdapter.html new file mode 100644 index 00000000000..a3d13215abb --- /dev/null +++ b/docs/doc/reference/com/google/android/exoplayer2/ui/DefaultMediaDescriptionAdapter.html @@ -0,0 +1,437 @@ + + + + +DefaultMediaDescriptionAdapter (ExoPlayer library) + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class DefaultMediaDescriptionAdapter

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.google.android.exoplayer2.ui.DefaultMediaDescriptionAdapter
      • +
      +
    • +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    + + + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/ui/DefaultTimeBar.html b/docs/doc/reference/com/google/android/exoplayer2/ui/DefaultTimeBar.html index fae48680262..1c7fbafebed 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ui/DefaultTimeBar.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ui/DefaultTimeBar.html @@ -145,7 +145,7 @@

    Class DefaultTimeBar

    A DefaultTimeBar can be customized by setting attributes, as outlined below. -

    Attributes

    +

    Attributes

    The following attributes can be set on a DefaultTimeBar when used in a layout XML file: @@ -1137,8 +1137,8 @@

    setKeyTimeIncrement

    public void setKeyTimeIncrement​(long time)
    Description copied from interface: TimeBar
    Sets the position increment for key presses and accessibility actions, in milliseconds. -

    - Clears any increment specified in a preceding call to TimeBar.setKeyCountIncrement(int).

    + +

    Clears any increment specified in a preceding call to TimeBar.setKeyCountIncrement(int).

    Specified by:
    setKeyTimeIncrement in interface TimeBar
    @@ -1158,8 +1158,8 @@

    setKeyCountIncrement

    Sets the position increment for key presses and accessibility actions, as a number of increments that divide the duration of the media. For example, passing 20 will cause key presses to increment/decrement the position by 1/20th of the duration (if known). -

    - Clears any increment specified in a preceding call to TimeBar.setKeyTimeIncrement(long).

    + +

    Clears any increment specified in a preceding call to TimeBar.setKeyTimeIncrement(long).

    Specified by:
    setKeyCountIncrement in interface TimeBar
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/ui/PlayerControlView.html b/docs/doc/reference/com/google/android/exoplayer2/ui/PlayerControlView.html index 25670a93bb9..587cdfab2b2 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ui/PlayerControlView.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ui/PlayerControlView.html @@ -25,7 +25,7 @@ catch(err) { } //--> -var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":42,"i17":42,"i18":10,"i19":10,"i20":10,"i21":42,"i22":10,"i23":10,"i24":10,"i25":10,"i26":10,"i27":10,"i28":10,"i29":10,"i30":10,"i31":10,"i32":10}; +var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":42,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10,"i21":10,"i22":10,"i23":10,"i24":10,"i25":10,"i26":10,"i27":10,"i28":10,"i29":10}; var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"],32:["t6","Deprecated Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -156,7 +156,7 @@

    Class PlayerControlView

    methods), overriding drawables, overriding the view's layout file, or by specifying a custom view layout file. -

    Attributes

    +

    Attributes

    The following attributes can be set on a PlayerControlView when used in a layout XML file: @@ -188,17 +188,6 @@

    Attributes

  • Corresponding method: setShowNextButton(boolean)
  • Default: true -
  • rewind_increment - The duration of the rewind applied when the user taps the - rewind button, in milliseconds. Use zero to disable the rewind button. - -
  • fastforward_increment - Like rewind_increment, but for fast forward. -
  • repeat_toggle_modes - A flagged enumeration value specifying which repeat mode toggle options are enabled. Valid values are: none, one, all, or one|all. @@ -228,7 +217,7 @@

    Attributes

    layout is overridden to specify a custom exo_progress (see below). -

    Overriding drawables

    +

    Overriding drawables

    The drawables used by PlayerControlView (with its default layout file) can be overridden by drawables with the same names defined in your application. The drawables that can be overridden @@ -249,7 +238,7 @@

    Overriding drawables

  • exo_controls_vr - The VR icon. -

    Overriding the layout file

    +

    Overriding the layout file

    To customize the layout of PlayerControlView throughout your app, or just for certain configurations, you can define exo_player_control_view.xml layout files in your @@ -328,7 +317,7 @@

    Overriding the layout file

    All child views are optional and so can be omitted if not required, however where defined they must be of the expected type. -

    Specifying a custom layout file

    +

    Specifying a custom layout file

    Defining your own exo_player_control_view.xml is useful to customize the layout of PlayerControlView throughout your application. It's also possible to customize the layout for a @@ -602,7 +591,9 @@

    Method Summary

    void setControlDispatcher​(ControlDispatcher controlDispatcher) - +
    Deprecated. +
    Use a ForwardingPlayer and pass it to setPlayer(Player) instead.
    +
    @@ -616,123 +607,96 @@

    Method Summary

    void -setFastForwardIncrementMs​(int fastForwardMs) - - - - - -void -setPlaybackPreparer​(PlaybackPreparer playbackPreparer) - -
    Deprecated. - -
    - - - -void setPlayer​(Player player)
    Sets the Player to control.
    - + void setProgressUpdateListener​(PlayerControlView.ProgressUpdateListener listener) - + void setRepeatToggleModes​(int repeatToggleModes)
    Sets which repeat toggle modes are enabled.
    - -void -setRewindIncrementMs​(int rewindMs) - - - - - + void setShowFastForwardButton​(boolean showFastForwardButton)
    Sets whether the fast forward button is shown.
    - + void setShowMultiWindowTimeBar​(boolean showMultiWindowTimeBar)
    Sets whether the time bar should show all windows, as opposed to just the current one.
    - + void setShowNextButton​(boolean showNextButton)
    Sets whether the next button is shown.
    - + void setShowPreviousButton​(boolean showPreviousButton)
    Sets whether the previous button is shown.
    - + void setShowRewindButton​(boolean showRewindButton)
    Sets whether the rewind button is shown.
    - + void setShowShuffleButton​(boolean showShuffleButton)
    Sets whether the shuffle button is shown.
    - + void setShowTimeoutMs​(int showTimeoutMs)
    Sets the playback controls timeout.
    - + void setShowVrButton​(boolean showVrButton)
    Sets whether the VR button is shown.
    - + void setTimeBarMinUpdateInterval​(int minUpdateIntervalMs)
    Sets the minimum interval between time bar position updates.
    - + void setVrButtonListener​(View.OnClickListener onClickListener)
    Sets listener for the VR button.
    - + void show() @@ -1024,36 +988,21 @@

    setProgressUpdateListener

  • - + - - - - @@ -1110,32 +1059,6 @@

    setShowNextButton

    - - - - - - - - diff --git a/docs/doc/reference/com/google/android/exoplayer2/ui/PlayerNotificationManager.Builder.html b/docs/doc/reference/com/google/android/exoplayer2/ui/PlayerNotificationManager.Builder.html index c1a757a1751..6d068b82a2a 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ui/PlayerNotificationManager.Builder.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ui/PlayerNotificationManager.Builder.html @@ -25,7 +25,7 @@ catch(err) { } //--> -var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10}; +var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10}; var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -156,12 +156,22 @@

    Constructor Summary

    Description +Builder​(Context context, + int notificationId, + String channelId) + +
    Creates an instance.
    + + + Builder​(Context context, int notificationId, String channelId, PlayerNotificationManager.MediaDescriptionAdapter mediaDescriptionAdapter) -
    Creates an instance.
    + @@ -233,54 +243,61 @@

    Method Summary

    PlayerNotificationManager.Builder +setMediaDescriptionAdapter​(PlayerNotificationManager.MediaDescriptionAdapter mediaDescriptionAdapter) + +
    The PlayerNotificationManager.MediaDescriptionAdapter to be queried for the notification contents.
    + + + +PlayerNotificationManager.Builder setNextActionIconResourceId​(int nextActionIconResourceId)
    The resource id of the drawable to be used as the icon of action PlayerNotificationManager.ACTION_NEXT.
    - + PlayerNotificationManager.Builder setNotificationListener​(PlayerNotificationManager.NotificationListener notificationListener) - + PlayerNotificationManager.Builder setPauseActionIconResourceId​(int pauseActionIconResourceId)
    The resource id of the drawable to be used as the icon of action PlayerNotificationManager.ACTION_PAUSE.
    - + PlayerNotificationManager.Builder setPlayActionIconResourceId​(int playActionIconResourceId)
    The resource id of the drawable to be used as the icon of action PlayerNotificationManager.ACTION_PLAY.
    - + PlayerNotificationManager.Builder setPreviousActionIconResourceId​(int previousActionIconResourceId)
    The resource id of the drawable to be used as the icon of action PlayerNotificationManager.ACTION_PREVIOUS.
    - + PlayerNotificationManager.Builder setRewindActionIconResourceId​(int rewindActionIconResourceId)
    The resource id of the drawable to be used as the icon of action PlayerNotificationManager.ACTION_REWIND.
    - + PlayerNotificationManager.Builder setSmallIconResourceId​(int smallIconResourceId)
    The resource id of the small icon of the notification shown in the status bar.
    - + PlayerNotificationManager.Builder setStopActionIconResourceId​(int stopActionIconResourceId) @@ -314,20 +331,34 @@

    Constructor Detail

    - + + + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/ui/PlayerNotificationManager.MediaDescriptionAdapter.html b/docs/doc/reference/com/google/android/exoplayer2/ui/PlayerNotificationManager.MediaDescriptionAdapter.html index 9beec0d3b91..dc1daf02080 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ui/PlayerNotificationManager.MediaDescriptionAdapter.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ui/PlayerNotificationManager.MediaDescriptionAdapter.html @@ -121,6 +121,10 @@

  • +
    All Known Implementing Classes:
    +
    DefaultMediaDescriptionAdapter
    +
    +
    Enclosing class:
    PlayerNotificationManager
    @@ -213,6 +217,8 @@

    getCurrentContentTitle

    Parameters:
    player - The Player for which a notification is being built.
    +
    Returns:
    +
    The content title for the current media item.
  • @@ -230,6 +236,8 @@

    createCurrentContentIntent

    Parameters:
    player - The Player for which a notification is being built.
    +
    Returns:
    +
    The content intent for the current media item, or null if no intent should be fired.
    @@ -247,6 +255,9 @@

    getCurrentContentText

    Parameters:
    player - The Player for which a notification is being built.
    +
    Returns:
    +
    The content text for the current media item, or null if no context text should be + displayed.
    @@ -264,6 +275,9 @@

    getCurrentSubText

    Parameters:
    player - The Player for which a notification is being built.
    +
    Returns:
    +
    The content subtext for the current media item, or null if no subtext should be + displayed.
    @@ -288,6 +302,9 @@

    getCurrentLargeIcon

    Parameters:
    player - The Player for which a notification is being built.
    callback - A PlayerNotificationManager.BitmapCallback to provide a Bitmap asynchronously.
    +
    Returns:
    +
    The large icon for the current media item, or null if the icon will be returned + through the PlayerNotificationManager.BitmapCallback or if no icon should be displayed.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/ui/PlayerNotificationManager.html b/docs/doc/reference/com/google/android/exoplayer2/ui/PlayerNotificationManager.html index 5713b875678..d23ecfc1937 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ui/PlayerNotificationManager.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ui/PlayerNotificationManager.html @@ -25,8 +25,8 @@ catch(err) { } //--> -var data = {"i0":10,"i1":41,"i2":41,"i3":41,"i4":41,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":42,"i15":10,"i16":42,"i17":10,"i18":10,"i19":42,"i20":10,"i21":10,"i22":42,"i23":42,"i24":10,"i25":10,"i26":10,"i27":10,"i28":10,"i29":10,"i30":10}; -var tabs = {65535:["t0","All Methods"],1:["t1","Static Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"],32:["t6","Deprecated Methods"]}; +var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":42,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10,"i21":10,"i22":10,"i23":10,"i24":10,"i25":10}; +var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"],32:["t6","Deprecated Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; var tableTab = "tableTab"; @@ -88,13 +88,13 @@
  • Summary: 
  • Nested | 
  • Field | 
  • -
  • Constr | 
  • +
  • Constr | 
  • Method
  • @@ -140,7 +140,7 @@

    Class PlayerNotificati

    If the player is released it must be removed from the manager by calling setPlayer(null). -

    Action customization

    +

    Action customization

    Playback actions can be included or omitted as follows: @@ -150,17 +150,29 @@

    Action customization

  • Corresponding setter: setUsePlayPauseActions(boolean)
  • Default: true -
  • rewindIncrementMs - Sets the rewind increment. If set to zero the rewind - action is not used. +
  • useRewindAction - Sets whether the rewind action is used. +
  • useRewindActionInCompactView - If useRewindAction is true, + sets whether the rewind action is also used in compact view (including the lock screen + notification). Else does nothing. + -
  • fastForwardIncrementMs - Sets the fast forward increment. If set to zero the - fast forward action is not used. +
  • useFastForwardAction - Sets whether the fast forward action is used. +
  • useFastForwardActionInCompactView - If useFastForwardAction is + true, sets whether the fast forward action is also used in compact view (including + the lock screen notification). Else does nothing. +
  • usePreviousAction - Whether the previous action is used.
      @@ -193,7 +205,7 @@

      Action customization

    -

    Overriding drawables

    +

    Overriding drawables

    The drawables used by PlayerNotificationManager can be overridden by drawables with the same names defined in your application. The drawables that can be overridden are: @@ -361,71 +373,6 @@

    Field Summary

  • - -
    - -
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/AssetDataSource.AssetDataSourceException.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/AssetDataSource.AssetDataSourceException.html index efaea35dab2..3a27f6c5fbe 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/AssetDataSource.AssetDataSourceException.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/AssetDataSource.AssetDataSourceException.html @@ -81,7 +81,7 @@ @@ -124,6 +124,9 @@

    Class A
  • java.io.IOException
  • + +
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/DataSourceInputStream.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/DataSourceInputStream.html index e0742c6eeeb..b612dd7e2f5 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/DataSourceInputStream.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/DataSourceInputStream.html @@ -295,8 +295,8 @@

    open

    public void open()
               throws IOException
    Optional call to open the underlying DataSource. -

    - Calling this method does nothing if the DataSource is already open. Calling this + +

    Calling this method does nothing if the DataSource is already open. Calling this method is optional, since the read and skip methods will automatically open the underlying DataSource if it's not open already.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/DefaultAllocator.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/DefaultAllocator.html index 5f71239faab..11cdbf631c5 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/DefaultAllocator.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/DefaultAllocator.html @@ -238,8 +238,7 @@

    Method Summary

    void trim() -
    Hints to the allocator that it should make a best effort to release any excess - Allocations.
    +
    Hints to the allocator that it should make a best effort to release any excess Allocations.
    @@ -293,8 +292,8 @@

    DefaultAllocator

    int individualAllocationSize, int initialAllocationCount)
    Constructs an instance with some Allocations created up front. -

    - Note: Allocations created up front will never be discarded by trim().

    + +

    Note: Allocations created up front will never be discarded by trim().

    Parameters:
    trimOnReset - Whether memory is freed when the allocator is reset. Should be true unless @@ -341,8 +340,8 @@

    allocate

    public Allocation allocate()
    Description copied from interface: Allocator
    Obtain an Allocation. -

    - When the caller has finished with the Allocation, it should be returned by calling + +

    When the caller has finished with the Allocation, it should be returned by calling Allocator.release(Allocation).

    Specified by:
    @@ -394,8 +393,7 @@

    release

    trim

    public void trim()
    Description copied from interface: Allocator
    -
    Hints to the allocator that it should make a best effort to release any excess - Allocations.
    +
    Hints to the allocator that it should make a best effort to release any excess Allocations.
    Specified by:
    trim in interface Allocator
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/DefaultBandwidthMeter.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/DefaultBandwidthMeter.html index ac430606360..2a57c81f665 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/DefaultBandwidthMeter.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/DefaultBandwidthMeter.html @@ -336,7 +336,7 @@

    Method Summary

    onBytesTransferred​(DataSource source, DataSpec dataSpec, boolean isNetwork, - int bytes) + int bytesTransferred)
    Called incrementally during a transfer.
    @@ -698,7 +698,7 @@

    onBytesTransferred

    public void onBytesTransferred​(DataSource source,
                                    DataSpec dataSpec,
                                    boolean isNetwork,
    -                               int bytes)
    + int bytesTransferred)
    Description copied from interface: TransferListener
    Called incrementally during a transfer.
    @@ -708,7 +708,7 @@

    onBytesTransferred

    source - The source performing the transfer.
    dataSpec - Describes the data being transferred.
    isNetwork - Whether the data is transferred through a network.
    -
    bytes - The number of bytes transferred since the previous call to this method
    +
    bytesTransferred - The number of bytes transferred since the previous call to this method.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/DefaultDataSource.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/DefaultDataSource.html index 1e4cec5fca3..f3e9c9ea1d4 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/DefaultDataSource.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/DefaultDataSource.html @@ -284,7 +284,7 @@

    Method Summary

    int read​(byte[] buffer, int offset, - int readLength) + int length)
    Reads up to length bytes of data from the input.
    @@ -472,7 +472,7 @@

    open

    read

    public int read​(byte[] buffer,
                     int offset,
    -                int readLength)
    +                int length)
              throws IOException
    Description copied from interface: DataReader
    Reads up to length bytes of data from the input. @@ -487,7 +487,7 @@

    read

    Parameters:
    buffer - A target array into which data should be written.
    offset - The offset into the target array at which to write.
    -
    readLength - The maximum number of bytes to read from the input.
    +
    length - The maximum number of bytes to read from the input.
    Returns:
    The number of bytes read, or C.RESULT_END_OF_INPUT if the input has ended. This may be less than length because the end of the input (or available data) was diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.Factory.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.Factory.html index 4101cc270ed..b72dd71210c 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.Factory.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.Factory.html @@ -25,7 +25,7 @@ catch(err) { } //--> -var data = {"i0":10,"i1":42,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10}; +var data = {"i0":10,"i1":42,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10}; var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"],32:["t6","Deprecated Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -230,19 +230,27 @@

    Method Summary

    DefaultHttpDataSource.Factory +setKeepPostFor302Redirects​(boolean keepPostFor302Redirects) + +
    Sets whether we should keep the POST method and body when we have HTTP 302 redirects for a + POST request.
    + + + +DefaultHttpDataSource.Factory setReadTimeoutMs​(int readTimeoutMs)
    Sets the read timeout, in milliseconds.
    - + DefaultHttpDataSource.Factory setTransferListener​(TransferListener transferListener)
    Sets the TransferListener that will be used.
    - + DefaultHttpDataSource.Factory setUserAgent​(String userAgent) @@ -451,6 +459,17 @@

    setTransferListener

    + + + +
      +
    • +

      setKeepPostFor302Redirects

      +
      public DefaultHttpDataSource.Factory setKeepPostFor302Redirects​(boolean keepPostFor302Redirects)
      +
      Sets whether we should keep the POST method and body when we have HTTP 302 redirects for a + POST request.
      +
    • +
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.html index 2b2a5e3f67c..30798524c24 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.html @@ -350,7 +350,7 @@

    Method Summary

    int read​(byte[] buffer, int offset, - int readLength) + int length)
    Reads up to length bytes of data from the input.
    @@ -684,7 +684,7 @@

    open

    read

    public int read​(byte[] buffer,
                     int offset,
    -                int readLength)
    +                int length)
              throws HttpDataSource.HttpDataSourceException
    Description copied from interface: DataReader
    Reads up to length bytes of data from the input. @@ -701,7 +701,7 @@

    read

    Parameters:
    buffer - A target array into which data should be written.
    offset - The offset into the target array at which to write.
    -
    readLength - The maximum number of bytes to read from the input.
    +
    length - The maximum number of bytes to read from the input.
    Returns:
    The number of bytes read, or C.RESULT_END_OF_INPUT if the input has ended. This may be less than length because the end of the input (or available data) was diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/DefaultLoadErrorHandlingPolicy.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/DefaultLoadErrorHandlingPolicy.html index 1149d29b832..34cff85ae8e 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/DefaultLoadErrorHandlingPolicy.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/DefaultLoadErrorHandlingPolicy.html @@ -25,7 +25,7 @@ catch(err) { } //--> -var data = {"i0":10,"i1":10,"i2":10}; +var data = {"i0":10,"i1":10,"i2":10,"i3":10}; var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -155,7 +155,7 @@

    Nested Class Summary

    Nested classes/interfaces inherited from interface com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy

    -LoadErrorHandlingPolicy.LoadErrorInfo +LoadErrorHandlingPolicy.FallbackOptions, LoadErrorHandlingPolicy.FallbackSelection, LoadErrorHandlingPolicy.FallbackType, LoadErrorHandlingPolicy.LoadErrorInfo @@ -175,13 +175,20 @@

    Field Summary

    Description +static long +DEFAULT_LOCATION_EXCLUSION_MS + +
    The default duration for which a location is excluded in milliseconds.
    + + + static int DEFAULT_MIN_LOADABLE_RETRY_COUNT
    The default minimum number of times to retry loading data prior to propagating the error.
    - + static int DEFAULT_MIN_LOADABLE_RETRY_COUNT_PROGRESSIVE_LIVE @@ -189,14 +196,30 @@

    Field Summary

    streams.
    - + static long DEFAULT_TRACK_BLACKLIST_MS +
    Deprecated. + +
    + + + +static long +DEFAULT_TRACK_EXCLUSION_MS +
    The default duration for which a track is excluded in milliseconds.
    +

    @@ -244,11 +267,12 @@

    Method Summary

    Description -long -getBlacklistDurationMsFor​(LoadErrorHandlingPolicy.LoadErrorInfo loadErrorInfo) +LoadErrorHandlingPolicy.FallbackSelection +getFallbackSelectionFor​(LoadErrorHandlingPolicy.FallbackOptions fallbackOptions, + LoadErrorHandlingPolicy.LoadErrorInfo loadErrorInfo) -
    Returns the exclusion duration, given by DEFAULT_TRACK_BLACKLIST_MS, if the load error - was an HttpDataSource.InvalidResponseCodeException with response code HTTP 404, 410 or 416, or C.TIME_UNSET otherwise.
    +
    Returns whether a loader should fall back to using another resource on encountering an error, + and if so the duration for which the failing resource should be excluded.
    @@ -266,6 +290,13 @@

    Method Summary

    + +protected boolean +isEligibleForFallback​(IOException exception) + +
    Returns whether an error should trigger a fallback if possible.
    + + @@ -326,20 +357,51 @@

    DEFAULT_MIN_LOADABLE_RETRY_COUNT_PROGRESSIVE_LIVE

    + + + +
      +
    • +

      DEFAULT_TRACK_EXCLUSION_MS

      +
      public static final long DEFAULT_TRACK_EXCLUSION_MS
      +
      The default duration for which a track is excluded in milliseconds.
      +
      +
      See Also:
      +
      Constant Field Values
      +
      +
    • +
    -
      +
      • DEFAULT_TRACK_BLACKLIST_MS

        -
        public static final long DEFAULT_TRACK_BLACKLIST_MS
        -
        The default duration for which a track is excluded in milliseconds.
        +
        @Deprecated
        +public static final long DEFAULT_TRACK_BLACKLIST_MS
        +
        Deprecated. + +
        See Also:
        Constant Field Values
      + + + +
        +
      • +

        DEFAULT_LOCATION_EXCLUSION_MS

        +
        public static final long DEFAULT_LOCATION_EXCLUSION_MS
        +
        The default duration for which a location is excluded in milliseconds.
        +
        +
        See Also:
        +
        Constant Field Values
        +
        +
      • +
    @@ -386,23 +448,34 @@

    DefaultLoadErrorHandlingPolicy

    Method Detail

    - + @@ -421,14 +494,15 @@

    getRetryDelayMsFor

    Parameters:
    loadErrorInfo - A LoadErrorHandlingPolicy.LoadErrorInfo holding information about the load error.
    Returns:
    -
    The number of milliseconds to wait before attempting the load again, or C.TIME_UNSET if the error is fatal and should not be retried.
    +
    The duration to wait before retrying in milliseconds, or C.TIME_UNSET if the + error is fatal and should not be retried.
    -
      +
      • getMinimumLoadableRetryCount

        public int getMinimumLoadableRetryCount​(int dataType)
        @@ -438,16 +512,26 @@

        getMinimumLoadableRetryCount

        Specified by:
        getMinimumLoadableRetryCount in interface LoadErrorHandlingPolicy
        Parameters:
        -
        dataType - One of the C.DATA_TYPE_* constants indicating the type of data to - load.
        +
        dataType - One of the C.DATA_TYPE_* constants indicating the type of data being + loaded.
        Returns:
        -
        The minimum number of times to retry a load in the case of a load error, before - propagating the error.
        +
        The minimum number of times to retry a load before a load error that can be retried may + be considered fatal.
        See Also:
        Loader.startLoading(Loadable, Callback, int)
      + + + +
        +
      • +

        isEligibleForFallback

        +
        protected boolean isEligibleForFallback​(IOException exception)
        +
        Returns whether an error should trigger a fallback if possible.
        +
      • +
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/DummyDataSource.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/DummyDataSource.html index 2f3277a5989..3161c8ea2a4 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/DummyDataSource.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/DummyDataSource.html @@ -236,7 +236,7 @@

    Method Summary

    int read​(byte[] buffer, int offset, - int readLength) + int length)
    Reads up to length bytes of data from the input.
    @@ -369,7 +369,7 @@

    open

    read

    public int read​(byte[] buffer,
                     int offset,
    -                int readLength)
    + int length)
    Description copied from interface: DataReader
    Reads up to length bytes of data from the input. @@ -383,7 +383,7 @@

    read

    Parameters:
    buffer - A target array into which data should be written.
    offset - The offset into the target array at which to write.
    -
    readLength - The maximum number of bytes to read from the input.
    +
    length - The maximum number of bytes to read from the input.
    Returns:
    The number of bytes read, or C.RESULT_END_OF_INPUT if the input has ended. This may be less than length because the end of the input (or available data) was diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/FileDataSource.FileDataSourceException.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/FileDataSource.FileDataSourceException.html index aee4749d9f0..59154b326d0 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/FileDataSource.FileDataSourceException.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/FileDataSource.FileDataSourceException.html @@ -81,7 +81,7 @@ @@ -124,6 +124,9 @@

    Class Fil
  • java.io.IOException
  • + +
    • @@ -147,7 +152,7 @@

      Class Fil
      public static class FileDataSource.FileDataSourceException
      -extends IOException
      +extends DataSourceException
      Thrown when a FileDataSource encounters an error reading a file.
      See Also:
      @@ -159,6 +164,23 @@

      Class Fil
      diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/HttpDataSource.HttpDataSourceException.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/HttpDataSource.HttpDataSourceException.html index 591fe8cf20b..4385a27604b 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/HttpDataSource.HttpDataSourceException.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/HttpDataSource.HttpDataSourceException.html @@ -25,6 +25,12 @@ catch(err) { } //--> +var data = {"i0":9}; +var tabs = {65535:["t0","All Methods"],1:["t1","Static Methods"],8:["t4","Concrete Methods"]}; +var altColor = "altColor"; +var rowColor = "rowColor"; +var tableTab = "tableTab"; +var activeTableTab = "activeTableTab"; var pathtoroot = "../../../../../"; var useModuleDirectories = false; loadScripts(document, 'script'); @@ -89,7 +95,7 @@
    • Detail: 
    • Field | 
    • Constr | 
    • -
    • Method
    • +
    • Method
    @@ -124,6 +130,9 @@

    Class Htt
  • java.io.IOException
  • + +
    @@ -247,26 +273,81 @@

    Constructor Summary

    HttpDataSourceException​(DataSpec dataSpec, int type) -  + + + +HttpDataSourceException​(DataSpec dataSpec, + int errorCode, + int type) + +
    Constructs an HttpDataSourceException.
    + + + HttpDataSourceException​(IOException cause, DataSpec dataSpec, int type) -  + + + + + +HttpDataSourceException​(IOException cause, + DataSpec dataSpec, + int errorCode, + int type) + +
    Constructs an HttpDataSourceException.
    + HttpDataSourceException​(String message, DataSpec dataSpec, int type) -  + + + +HttpDataSourceException​(String message, + DataSpec dataSpec, + int errorCode, + int type) + +
    Constructs an HttpDataSourceException.
    + + + HttpDataSourceException​(String message, IOException cause, DataSpec dataSpec, int type) -  + + + + + +HttpDataSourceException​(String message, + IOException cause, + DataSpec dataSpec, + int errorCode, + int type) + +
    Constructs an HttpDataSourceException.
    + @@ -279,6 +360,31 @@

    Constructor Summary

    Method Summary

    + + + + + + + + + + + + +
    All Methods Static Methods Concrete Methods 
    Modifier and TypeMethodDescription
    static HttpDataSource.HttpDataSourceExceptioncreateForIOException​(IOException cause, + DataSpec dataSpec, + int type) +
    Returns a HttpDataSourceException whose error code is assigned according to the cause + and type.
    +
    + - +
    • -

      type

      -
      @Type
      -public final int type
      +

      dataSpec

      +
      public final DataSpec dataSpec
      +
      The DataSpec associated with the current connection.
    - +
    • -

      dataSpec

      -
      public final DataSpec dataSpec
      -
      The DataSpec associated with the current connection.
      +

      type

      +
      @Type
      +public final int type
    @@ -384,9 +493,33 @@

    Constructor Detail

    + + + + @@ -395,10 +528,37 @@

    HttpDataSourceException

    + + + + @@ -407,23 +567,104 @@

    HttpDataSourceException

    + + + + + + + + + + + + +
    +
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/HttpDataSource.InvalidContentTypeException.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/HttpDataSource.InvalidContentTypeException.html index 6e7474b861d..a7a1f22c737 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/HttpDataSource.InvalidContentTypeException.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/HttpDataSource.InvalidContentTypeException.html @@ -124,6 +124,9 @@

    Class
  • java.io.IOException
  • +
  • @@ -241,6 +253,20 @@

    Constructor Summary

    Method Summary

    + + @@ -248,31 +260,34 @@

    Constructor Summary

    Description +InvalidResponseCodeException​(int responseCode, + String responseMessage, + IOException cause, + Map<String,​List<String>> headerFields, + DataSpec dataSpec, + byte[] responseBody) +  + + InvalidResponseCodeException​(int responseCode, String responseMessage, Map<String,​List<String>> headerFields, DataSpec dataSpec) - -InvalidResponseCodeException​(int responseCode, - String responseMessage, - Map<String,​List<String>> headerFields, - DataSpec dataSpec, - byte[] responseBody) -  - InvalidResponseCodeException​(int responseCode, Map<String,​List<String>> headerFields, DataSpec dataSpec) @@ -288,6 +303,20 @@

    Constructor Summary

    Method Summary

    + + @@ -396,11 +426,12 @@

    InvalidResponseCodeException

    Map<String,​List<String>> headerFields, DataSpec dataSpec) - +
      @@ -409,6 +440,8 @@

      InvalidResponseCodeException

      public InvalidResponseCodeException​(int responseCode,
                                           @Nullable
                                           String responseMessage,
      +                                    @Nullable
      +                                    IOException cause,
                                           Map<String,​List<String>> headerFields,
                                           DataSpec dataSpec,
                                           byte[] responseBody)
      diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/HttpDataSource.RequestProperties.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/HttpDataSource.RequestProperties.html index bfc3d24a6b6..b43a3548a74 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/HttpDataSource.RequestProperties.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/HttpDataSource.RequestProperties.html @@ -135,9 +135,9 @@

      Class HttpDataS
      public static final class HttpDataSource.RequestProperties
       extends Object
      -
      Stores HTTP request properties (aka HTTP headers) and provides methods to modify the headers - in a thread safe way to avoid the potential of creating snapshots of an inconsistent or - unintended state.
      +
      Stores HTTP request properties (aka HTTP headers) and provides methods to modify the headers in + a thread safe way to avoid the potential of creating snapshots of an inconsistent or unintended + state.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/HttpDataSource.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/HttpDataSource.html index 5da301039f9..2c98063ba63 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/HttpDataSource.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/HttpDataSource.html @@ -198,9 +198,9 @@

    Nested Class Summary

    static class  HttpDataSource.RequestProperties -
    Stores HTTP request properties (aka HTTP headers) and provides methods to modify the headers - in a thread safe way to avoid the potential of creating snapshots of an inconsistent or - unintended state.
    +
    Stores HTTP request properties (aka HTTP headers) and provides methods to modify the headers in + a thread safe way to avoid the potential of creating snapshots of an inconsistent or unintended + state.
    @@ -293,7 +293,7 @@

    Method Summary

    int read​(byte[] buffer, int offset, - int readLength) + int length)
    Reads up to length bytes of data from the input.
    @@ -405,7 +405,7 @@

    close

    read

    int read​(byte[] buffer,
              int offset,
    -         int readLength)
    +         int length)
       throws HttpDataSource.HttpDataSourceException
    Description copied from interface: DataReader
    Reads up to length bytes of data from the input. @@ -420,7 +420,7 @@

    read

    Parameters:
    buffer - A target array into which data should be written.
    offset - The offset into the target array at which to write.
    -
    readLength - The maximum number of bytes to read from the input.
    +
    length - The maximum number of bytes to read from the input.
    Returns:
    The number of bytes read, or C.RESULT_END_OF_INPUT if the input has ended. This may be less than length because the end of the input (or available data) was diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/LoadErrorHandlingPolicy.FallbackOptions.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/LoadErrorHandlingPolicy.FallbackOptions.html new file mode 100644 index 00000000000..319d46499ba --- /dev/null +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/LoadErrorHandlingPolicy.FallbackOptions.html @@ -0,0 +1,416 @@ + + + + +LoadErrorHandlingPolicy.FallbackOptions (ExoPlayer library) + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class LoadErrorHandlingPolicy.FallbackOptions

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.FallbackOptions
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing interface:
      +
      LoadErrorHandlingPolicy
      +
      +
      +
      public static final class LoadErrorHandlingPolicy.FallbackOptions
      +extends Object
      +
      Holds information about the available fallback options.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Field Detail

        + + + +
          +
        • +

          numberOfLocations

          +
          public final int numberOfLocations
          +
          The number of available locations.
          +
        • +
        + + + +
          +
        • +

          numberOfExcludedLocations

          +
          public final int numberOfExcludedLocations
          +
          The number of locations that are already excluded.
          +
        • +
        + + + +
          +
        • +

          numberOfTracks

          +
          public final int numberOfTracks
          +
          The number of tracks.
          +
        • +
        + + + +
          +
        • +

          numberOfExcludedTracks

          +
          public final int numberOfExcludedTracks
          +
          The number of tracks that are already excluded.
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          FallbackOptions

          +
          public FallbackOptions​(int numberOfLocations,
          +                       int numberOfExcludedLocations,
          +                       int numberOfTracks,
          +                       int numberOfExcludedTracks)
          +
          Creates an instance.
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          isFallbackAvailable

          +
          public boolean isFallbackAvailable​(@FallbackType
          +                                   int type)
          +
          Returns whether a fallback is available for the given fallback type.
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + + + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/LoadErrorHandlingPolicy.FallbackSelection.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/LoadErrorHandlingPolicy.FallbackSelection.html new file mode 100644 index 00000000000..9c0bf0ceaba --- /dev/null +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/LoadErrorHandlingPolicy.FallbackSelection.html @@ -0,0 +1,344 @@ + + + + +LoadErrorHandlingPolicy.FallbackSelection (ExoPlayer library) + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class LoadErrorHandlingPolicy.FallbackSelection

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.FallbackSelection
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing interface:
      +
      LoadErrorHandlingPolicy
      +
      +
      +
      public static final class LoadErrorHandlingPolicy.FallbackSelection
      +extends Object
      +
      A selected fallback option.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Field Detail

        + + + +
          +
        • +

          type

          +
          @FallbackType
          +public final int type
          +
          The type of fallback.
          +
        • +
        + + + +
          +
        • +

          exclusionDurationMs

          +
          public final long exclusionDurationMs
          +
          The duration for which the failing resource should be excluded, in milliseconds.
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          FallbackSelection

          +
          public FallbackSelection​(@FallbackType
          +                         int type,
          +                         long exclusionDurationMs)
          +
          Creates an instance.
          +
          +
          Parameters:
          +
          type - The type of fallback.
          +
          exclusionDurationMs - The duration for which the failing resource should be excluded, in + milliseconds. Must be non-negative.
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + + + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/LoadErrorHandlingPolicy.FallbackType.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/LoadErrorHandlingPolicy.FallbackType.html new file mode 100644 index 00000000000..74accacca21 --- /dev/null +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/LoadErrorHandlingPolicy.FallbackType.html @@ -0,0 +1,185 @@ + + + + +LoadErrorHandlingPolicy.FallbackType (ExoPlayer library) + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Annotation Type LoadErrorHandlingPolicy.FallbackType

    +
    +
    +
    + +
    +
    +
    + +
    + +
    + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/LoadErrorHandlingPolicy.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/LoadErrorHandlingPolicy.html index 253bb32aea1..2a16b6f4947 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/LoadErrorHandlingPolicy.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/LoadErrorHandlingPolicy.html @@ -25,8 +25,8 @@ catch(err) { } //--> -var data = {"i0":50,"i1":18,"i2":6,"i3":50,"i4":18,"i5":18}; -var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],4:["t3","Abstract Methods"],16:["t5","Default Methods"],32:["t6","Deprecated Methods"]}; +var data = {"i0":6,"i1":6,"i2":6,"i3":18}; +var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],4:["t3","Abstract Methods"],16:["t5","Default Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; var tableTab = "tableTab"; @@ -87,13 +87,13 @@ @@ -126,16 +126,18 @@

    Interface LoadErrorH
    public interface LoadErrorHandlingPolicy
    -
    Defines how errors encountered by loaders are handled. +
    A policy that defines how load errors are handled. -

    A loader that can choose between one of a number of resources can exclude a resource when a - load error occurs. In this case, getBlacklistDurationMsFor(int, long, IOException, int) - defines whether the resource should be excluded. Exclusion will succeed unless all of the - alternatives are already excluded. +

    Some loaders are able to choose between a number of alternate resources. Such loaders will + call getFallbackSelectionFor(FallbackOptions, LoadErrorInfo) when a load error occurs. + The LoadErrorHandlingPolicy.FallbackSelection returned by the policy defines whether the loader should fall back + to using another resource, and if so the duration for which the failing resource should be + excluded. -

    When exclusion does not take place, getRetryDelayMsFor(int, long, IOException, int) - defines whether the load is retried. An error that's not retried will always be propagated. An - error that is retried will be propagated according to getMinimumLoadableRetryCount(int). +

    When fallback does not take place, a loader will call getRetryDelayMsFor(LoadErrorInfo). The value returned by the policy defines whether the failed + load can be retried, and if so the duration to wait before retrying. If the policy indicates that + a load error should not be retried, it will be considered fatal by the loader. The loader may + also consider load errors that can be retried fatal if at least getMinimumLoadableRetryCount(int) retries have been attempted.

    Methods are invoked on the playback thread.

    @@ -160,6 +162,27 @@

    Nested Class Summary

    static class  +LoadErrorHandlingPolicy.FallbackOptions + +
    Holds information about the available fallback options.
    + + + +static class  +LoadErrorHandlingPolicy.FallbackSelection + +
    A selected fallback option.
    + + + +static interface  +LoadErrorHandlingPolicy.FallbackType + +
    Fallback type.
    + + + +static class  LoadErrorHandlingPolicy.LoadErrorInfo
    Holds information about a load task error.
    @@ -169,6 +192,40 @@

    Nested Class Summary

    + +
    +
      +
    • + + +

      Field Summary

      + + + + + + + + + + + + + + + + + +
      Fields 
      Modifier and TypeFieldDescription
      static intFALLBACK_TYPE_LOCATION +
      Fallback to the same resource at a different location (i.e., a different URL through which the + exact same data can be requested).
      +
      static intFALLBACK_TYPE_TRACK +
      Fallback to a different track (i.e., a different representation of the same content; for + example the same video encoded at a different bitrate or resolution).
      +
      +
    • +
    +
      @@ -177,60 +234,38 @@

      Nested Class Summary

      Method Summary

      - + - - + + - - - - - - - - - - - - + + - + @@ -607,8 +607,8 @@

      maybeThrowError

      throws IOException
      Description copied from interface: LoaderErrorThrower
      Throws a fatal error, or a non-fatal error if loading is currently backed off and the current - Loader.Loadable has incurred a number of errors greater than the specified minimum number - of retries. Else does nothing.
      + Loader.Loadable has incurred a number of errors greater than the specified minimum number of + retries. Else does nothing.
      Specified by:
      maybeThrowError in interface LoaderErrorThrower
      diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/LoaderErrorThrower.Dummy.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/LoaderErrorThrower.Dummy.html index 1668d01983b..e9b816c7314 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/LoaderErrorThrower.Dummy.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/LoaderErrorThrower.Dummy.html @@ -213,8 +213,8 @@

      Method Summary

      All Methods Instance Methods Abstract Methods Default Methods Deprecated Methods All Methods Instance Methods Abstract Methods Default Methods 
      Modifier and Type Method Description
      default longgetBlacklistDurationMsFor​(int dataType, - long loadDurationMs, - IOException exception, - int errorCount)LoadErrorHandlingPolicy.FallbackSelectiongetFallbackSelectionFor​(LoadErrorHandlingPolicy.FallbackOptions fallbackOptions, + LoadErrorHandlingPolicy.LoadErrorInfo loadErrorInfo) -
      Deprecated. - -
      +
      Returns whether a loader should fall back to using another resource on encountering an error, + and if so the duration for which the failing resource should be excluded.
      default longgetBlacklistDurationMsFor​(LoadErrorHandlingPolicy.LoadErrorInfo loadErrorInfo) -
      Returns the number of milliseconds for which a resource associated to a provided load error - should be excluded, or C.TIME_UNSET if the resource should not be excluded.
      -
      int getMinimumLoadableRetryCount​(int dataType) -
      Returns the minimum number of times to retry a load in the case of a load error, before - propagating the error.
      +
      Returns the minimum number of times to retry a load before a load error that can be retried may + be considered fatal.
      default longgetRetryDelayMsFor​(int dataType, - long loadDurationMs, - IOException exception, - int errorCount) -
      Deprecated. - -
      -
      default long
      long getRetryDelayMsFor​(LoadErrorHandlingPolicy.LoadErrorInfo loadErrorInfo) -
      Returns the number of milliseconds to wait before attempting the load again, or C.TIME_UNSET if the error is fatal and should not be retried.
      +
      Returns whether a loader can retry on encountering an error, and if so the duration to wait + before retrying.
      default void onLoadTaskConcluded​(long loadTaskId) @@ -247,61 +282,74 @@

      Method Summary

      • - +
          -
        • +
        • -

          Method Detail

          - +

          Field Detail

          +
          • -

            getBlacklistDurationMsFor

            -
            @Deprecated
            -default long getBlacklistDurationMsFor​(int dataType,
            -                                       long loadDurationMs,
            -                                       IOException exception,
            -                                       int errorCount)
            -
            Deprecated. - -
            +

            FALLBACK_TYPE_LOCATION

            +
            static final int FALLBACK_TYPE_LOCATION
            +
            Fallback to the same resource at a different location (i.e., a different URL through which the + exact same data can be requested).
            +
            +
            See Also:
            +
            Constant Field Values
            +
          - + -
            +
            • -

              getBlacklistDurationMsFor

              -
              default long getBlacklistDurationMsFor​(LoadErrorHandlingPolicy.LoadErrorInfo loadErrorInfo)
              -
              Returns the number of milliseconds for which a resource associated to a provided load error - should be excluded, or C.TIME_UNSET if the resource should not be excluded.
              +

              FALLBACK_TYPE_TRACK

              +
              static final int FALLBACK_TYPE_TRACK
              +
              Fallback to a different track (i.e., a different representation of the same content; for + example the same video encoded at a different bitrate or resolution).
              -
              Parameters:
              -
              loadErrorInfo - A LoadErrorHandlingPolicy.LoadErrorInfo holding information about the load error.
              -
              Returns:
              -
              The exclusion duration in milliseconds, or C.TIME_UNSET if the resource should - not be excluded.
              +
              See Also:
              +
              Constant Field Values
            - + +
          +
        + +
        +
          +
        • + + +

          Method Detail

          + @@ -310,17 +358,19 @@

          getRetryDelayMsFor

          • getRetryDelayMsFor

            -
            default long getRetryDelayMsFor​(LoadErrorHandlingPolicy.LoadErrorInfo loadErrorInfo)
            -
            Returns the number of milliseconds to wait before attempting the load again, or C.TIME_UNSET if the error is fatal and should not be retried. +
            long getRetryDelayMsFor​(LoadErrorHandlingPolicy.LoadErrorInfo loadErrorInfo)
            +
            Returns whether a loader can retry on encountering an error, and if so the duration to wait + before retrying. A return value of C.TIME_UNSET indicates that the error is fatal and + should not be retried. -

            Loaders may ignore the retry delay returned by this method in order to wait for a specific - event before retrying. However, the load is retried if and only if this method does not return - C.TIME_UNSET.

            +

            For loads that can be retried, loaders may ignore the retry delay returned by this method in + order to wait for a specific event before retrying.

            Parameters:
            loadErrorInfo - A LoadErrorHandlingPolicy.LoadErrorInfo holding information about the load error.
            Returns:
            -
            The number of milliseconds to wait before attempting the load again, or C.TIME_UNSET if the error is fatal and should not be retried.
            +
            The duration to wait before retrying in milliseconds, or C.TIME_UNSET if the + error is fatal and should not be retried.
          @@ -344,15 +394,15 @@

          onLoadTaskConcluded

        • getMinimumLoadableRetryCount

          int getMinimumLoadableRetryCount​(int dataType)
          -
          Returns the minimum number of times to retry a load in the case of a load error, before - propagating the error.
          +
          Returns the minimum number of times to retry a load before a load error that can be retried may + be considered fatal.
          Parameters:
          -
          dataType - One of the C.DATA_TYPE_* constants indicating the type of data to - load.
          +
          dataType - One of the C.DATA_TYPE_* constants indicating the type of data being + loaded.
          Returns:
          -
          The minimum number of times to retry a load in the case of a load error, before - propagating the error.
          +
          The minimum number of times to retry a load before a load error that can be retried may + be considered fatal.
          See Also:
          Loader.startLoading(Loadable, Callback, int)
          @@ -410,13 +460,13 @@

          getMinimumLoadableRetryCount

          diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/Loader.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/Loader.html index 475e85eace4..f3baf718cfa 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/Loader.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/Loader.html @@ -335,8 +335,8 @@

          Method Summary

      maybeThrowError​(int minRetryCount)
      Throws a fatal error, or a non-fatal error if loading is currently backed off and the current - Loader.Loadable has incurred a number of errors greater than the specified minimum number - of retries.
      + Loader.Loadable has incurred a number of errors greater than the specified minimum number of + retries.
      maybeThrowError​(int minRetryCount)
      Throws a fatal error, or a non-fatal error if loading is currently backed off and the current - Loader.Loadable has incurred a number of errors greater than the specified minimum number - of retries.
      + Loader.Loadable has incurred a number of errors greater than the specified minimum number of + retries.
      @@ -286,8 +286,8 @@

      maybeThrowError

      public void maybeThrowError​(int minRetryCount)
      Description copied from interface: LoaderErrorThrower
      Throws a fatal error, or a non-fatal error if loading is currently backed off and the current - Loader.Loadable has incurred a number of errors greater than the specified minimum number - of retries. Else does nothing.
      + Loader.Loadable has incurred a number of errors greater than the specified minimum number of + retries. Else does nothing.
    Specified by:
    maybeThrowError in interface LoaderErrorThrower
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/LoaderErrorThrower.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/LoaderErrorThrower.html index 72ce2a24c5b..f8d97d80d90 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/LoaderErrorThrower.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/LoaderErrorThrower.html @@ -186,8 +186,8 @@

    Method Summary

    maybeThrowError​(int minRetryCount)
    Throws a fatal error, or a non-fatal error if loading is currently backed off and the current - Loader.Loadable has incurred a number of errors greater than the specified minimum number - of retries.
    + Loader.Loadable has incurred a number of errors greater than the specified minimum number of + retries.

    @@ -233,8 +233,8 @@

    maybeThrowError

    void maybeThrowError​(int minRetryCount)
                   throws IOException
    Throws a fatal error, or a non-fatal error if loading is currently backed off and the current - Loader.Loadable has incurred a number of errors greater than the specified minimum number - of retries. Else does nothing.
    + Loader.Loadable has incurred a number of errors greater than the specified minimum number of + retries. Else does nothing.
    Parameters:
    minRetryCount - A minimum retry count that must be exceeded for a non-fatal error to be diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/PriorityDataSource.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/PriorityDataSource.html index 53fed6430d8..03587a0e21c 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/PriorityDataSource.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/PriorityDataSource.html @@ -246,7 +246,7 @@

    Method Summary

    int read​(byte[] buffer, int offset, - int max) + int length)
    Reads up to length bytes of data from the input.
    @@ -370,7 +370,7 @@

    open

    read

    public int read​(byte[] buffer,
                     int offset,
    -                int max)
    +                int length)
              throws IOException
    Description copied from interface: DataReader
    Reads up to length bytes of data from the input. @@ -385,7 +385,7 @@

    read

    Parameters:
    buffer - A target array into which data should be written.
    offset - The offset into the target array at which to write.
    -
    max - The maximum number of bytes to read from the input.
    +
    length - The maximum number of bytes to read from the input.
    Returns:
    The number of bytes read, or C.RESULT_END_OF_INPUT if the input has ended. This may be less than length because the end of the input (or available data) was diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/RawResourceDataSource.RawResourceDataSourceException.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/RawResourceDataSource.RawResourceDataSourceException.html index 465cea787fb..2c3b178c47e 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/RawResourceDataSource.RawResourceDataSourceException.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/RawResourceDataSource.RawResourceDataSourceException.html @@ -81,7 +81,7 @@ @@ -124,6 +124,9 @@

    java.io.IOException
    • +
    • com.google.android.exoplayer2.upstream.DataSourceException
    • +
    • +
      • com.google.android.exoplayer2.upstream.RawResourceDataSource.RawResourceDataSourceException
    • @@ -134,6 +137,8 @@

      • @@ -147,7 +152,7 @@

        RawResourceDataSource.RawResourceDataSourceException -extends IOException +extends DataSourceException
        Thrown when an IOException is encountered reading from a raw resource.
        See Also:
        @@ -159,6 +164,23 @@

        • + +
          + +
            @@ -174,11 +196,27 @@

            Constructor Summary

            RawResourceDataSourceException​(String message) -  + + + -RawResourceDataSourceException​(Throwable e) -  +RawResourceDataSourceException​(String message, + Throwable cause, + int errorCode) + +
            Creates a new instance.
            + + + +RawResourceDataSourceException​(Throwable cause) + + + @@ -192,6 +230,13 @@

            Constructor Summary

            Method Summary

            +
            • @@ -227,16 +272,39 @@

              Constructor Detail

              + + + +
              • RawResourceDataSourceException

                -
                public RawResourceDataSourceException​(Throwable e)
                +
                public RawResourceDataSourceException​(@Nullable
                +                                      String message,
                +                                      @Nullable
                +                                      Throwable cause,
                +                                      @ErrorCode
                +                                      int errorCode)
                +
                Creates a new instance.
            • @@ -291,7 +359,7 @@

              RawResourceDataSourceException

              diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/RawResourceDataSource.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/RawResourceDataSource.html index b5b438fdfbd..c5816259843 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/RawResourceDataSource.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/RawResourceDataSource.html @@ -286,7 +286,7 @@

              Method Summary

              int read​(byte[] buffer, int offset, - int readLength) + int length)
              Reads up to length bytes of data from the input.
              @@ -440,7 +440,7 @@

              open

              read

              public int read​(byte[] buffer,
                               int offset,
              -                int readLength)
              +                int length)
                        throws RawResourceDataSource.RawResourceDataSourceException
              Description copied from interface: DataReader
              Reads up to length bytes of data from the input. @@ -453,7 +453,7 @@

              read

              Parameters:
              buffer - A target array into which data should be written.
              offset - The offset into the target array at which to write.
              -
              readLength - The maximum number of bytes to read from the input.
              +
              length - The maximum number of bytes to read from the input.
              Returns:
              The number of bytes read, or C.RESULT_END_OF_INPUT if the input has ended. This may be less than length because the end of the input (or available data) was diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/ResolvingDataSource.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/ResolvingDataSource.html index 832e55d834e..780b84da36f 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/ResolvingDataSource.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/ResolvingDataSource.html @@ -251,7 +251,7 @@

              Method Summary

              int read​(byte[] buffer, int offset, - int readLength) + int length)
              Reads up to length bytes of data from the input.
              @@ -373,7 +373,7 @@

              open

              read

              public int read​(byte[] buffer,
                               int offset,
              -                int readLength)
              +                int length)
                        throws IOException
              Description copied from interface: DataReader
              Reads up to length bytes of data from the input. @@ -388,7 +388,7 @@

              read

              Parameters:
              buffer - A target array into which data should be written.
              offset - The offset into the target array at which to write.
              -
              readLength - The maximum number of bytes to read from the input.
              +
              length - The maximum number of bytes to read from the input.
              Returns:
              The number of bytes read, or C.RESULT_END_OF_INPUT if the input has ended. This may be less than length because the end of the input (or available data) was diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/StatsDataSource.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/StatsDataSource.html index 9df21501ab8..018b0349251 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/StatsDataSource.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/StatsDataSource.html @@ -259,7 +259,7 @@

              Method Summary

              int read​(byte[] buffer, int offset, - int readLength) + int length)
              Reads up to length bytes of data from the input.
              @@ -428,7 +428,7 @@

              open

              read

              public int read​(byte[] buffer,
                               int offset,
              -                int readLength)
              +                int length)
                        throws IOException
              Description copied from interface: DataReader
              Reads up to length bytes of data from the input. @@ -443,7 +443,7 @@

              read

              Parameters:
              buffer - A target array into which data should be written.
              offset - The offset into the target array at which to write.
              -
              readLength - The maximum number of bytes to read from the input.
              +
              length - The maximum number of bytes to read from the input.
              Returns:
              The number of bytes read, or C.RESULT_END_OF_INPUT if the input has ended. This may be less than length because the end of the input (or available data) was diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/TeeDataSource.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/TeeDataSource.html index 902e8cc2561..576ff633f68 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/TeeDataSource.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/TeeDataSource.html @@ -236,7 +236,7 @@

              Method Summary

              int read​(byte[] buffer, int offset, - int max) + int length)
              Reads up to length bytes of data from the input.
              @@ -358,7 +358,7 @@

              open

              read

              public int read​(byte[] buffer,
                               int offset,
              -                int max)
              +                int length)
                        throws IOException
              Description copied from interface: DataReader
              Reads up to length bytes of data from the input. @@ -373,7 +373,7 @@

              read

              Parameters:
              buffer - A target array into which data should be written.
              offset - The offset into the target array at which to write.
              -
              max - The maximum number of bytes to read from the input.
              +
              length - The maximum number of bytes to read from the input.
              Returns:
              The number of bytes read, or C.RESULT_END_OF_INPUT if the input has ended. This may be less than length because the end of the input (or available data) was diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/TransferListener.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/TransferListener.html index 315a0c04e19..229d37e391e 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/TransferListener.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/TransferListener.html @@ -268,7 +268,7 @@

              onBytesTransferred

              source - The source performing the transfer.
              dataSpec - Describes the data being transferred.
              isNetwork - Whether the data is transferred through a network.
              -
              bytesTransferred - The number of bytes transferred since the previous call to this method
              +
              bytesTransferred - The number of bytes transferred since the previous call to this method.

      diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/UdpDataSource.UdpDataSourceException.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/UdpDataSource.UdpDataSourceException.html index 1f5bf3f9193..a4bb05412f5 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/UdpDataSource.UdpDataSourceException.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/UdpDataSource.UdpDataSourceException.html @@ -81,7 +81,7 @@ @@ -124,6 +124,9 @@

      Class UdpDa
    • java.io.IOException
    +
  • +
    • @@ -147,7 +152,7 @@

      Class UdpDa


    public static final class UdpDataSource.UdpDataSourceException
    -extends IOException
    +extends DataSourceException
    Thrown when an error is encountered when trying to read from a UdpDataSource.
    See Also:
    @@ -159,6 +164,23 @@

    Class UdpDa
    • + +
      + +
        @@ -173,8 +195,11 @@

        Constructor Summary

        Description -UdpDataSourceException​(IOException cause) -  +UdpDataSourceException​(Throwable cause, + int errorCode) + +
        Creates a UdpDataSourceException.
        + @@ -188,6 +213,13 @@

        Constructor Summary

        Method Summary

        +
        • @@ -217,13 +249,21 @@

          Methods inherited from class java.lang. +
          • UdpDataSourceException

            -
            public UdpDataSourceException​(IOException cause)
            +
            public UdpDataSourceException​(Throwable cause,
            +                              @ErrorCode
            +                              int errorCode)
            +
            Creates a UdpDataSourceException.
            +
            +
            Parameters:
            +
            cause - The error cause.
            +
            errorCode - Reason of the error, should be one of the ERROR_CODE_IO_* in PlaybackException.ErrorCode.
            +

        • @@ -278,7 +318,7 @@

          UdpDataSourceException

          diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/UdpDataSource.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/UdpDataSource.html index 44dd5c305c2..c2d797ff27e 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/UdpDataSource.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/UdpDataSource.html @@ -297,7 +297,7 @@

          Method Summary

          int read​(byte[] buffer, int offset, - int readLength) + int length)
          Reads up to length bytes of data from the input.
          @@ -489,7 +489,7 @@

          open

          read

          public int read​(byte[] buffer,
                           int offset,
          -                int readLength)
          +                int length)
                    throws UdpDataSource.UdpDataSourceException
          Description copied from interface: DataReader
          Reads up to length bytes of data from the input. @@ -502,7 +502,7 @@

          read

          Parameters:
          buffer - A target array into which data should be written.
          offset - The offset into the target array at which to write.
          -
          readLength - The maximum number of bytes to read from the input.
          +
          length - The maximum number of bytes to read from the input.
          Returns:
          The number of bytes read, or C.RESULT_END_OF_INPUT if the input has ended. This may be less than length because the end of the input (or available data) was diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/cache/Cache.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/cache/Cache.html index 672be10437d..f8066092e49 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/cache/Cache.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/cache/Cache.html @@ -128,7 +128,7 @@

          Interface Cache

          public interface Cache
          A cache that supports partial caching of resources. -

          Terminology

          +

          Terminology

          • A resource is a complete piece of logical data, for example a complete media file. diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/cache/CacheDataSource.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/cache/CacheDataSource.html index 85326678303..2e109706773 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/cache/CacheDataSource.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/cache/CacheDataSource.html @@ -371,7 +371,7 @@

            Method Summary

            int read​(byte[] buffer, int offset, - int readLength) + int length)
            Reads up to length bytes of data from the input.
            @@ -422,9 +422,9 @@

            FLAG_BLOCK_ON_CACHE

          • FLAG_IGNORE_CACHE_ON_ERROR

            public static final int FLAG_IGNORE_CACHE_ON_ERROR
            -
            A flag indicating whether the cache is bypassed following any cache related error. If set - then cache related exceptions may be thrown for one cycle of open, read and close calls. - Subsequent cycles of these calls will then bypass the cache.
            +
            A flag indicating whether the cache is bypassed following any cache related error. If set then + cache related exceptions may be thrown for one cycle of open, read and close calls. Subsequent + cycles of these calls will then bypass the cache.
            See Also:
            Constant Field Values
            @@ -693,7 +693,7 @@

            open

            read

            public int read​(byte[] buffer,
                             int offset,
            -                int readLength)
            +                int length)
                      throws IOException
            Description copied from interface: DataReader
            Reads up to length bytes of data from the input. @@ -708,7 +708,7 @@

            read

            Parameters:
            buffer - A target array into which data should be written.
            offset - The offset into the target array at which to write.
            -
            readLength - The maximum number of bytes to read from the input.
            +
            length - The maximum number of bytes to read from the input.
            Returns:
            The number of bytes read, or C.RESULT_END_OF_INPUT if the input has ended. This may be less than length because the end of the input (or available data) was diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/cache/CachedRegionTracker.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/cache/CachedRegionTracker.html index 81c6b251591..f3118b479ab 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/cache/CachedRegionTracker.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/cache/CachedRegionTracker.html @@ -213,8 +213,8 @@

            Method Summary

            int getRegionEndTimeMs​(long byteOffset) -
            When provided with a byte offset, this method locates the cached region within which the - offset falls, and returns the approximate end position in milliseconds of that region.
            +
            When provided with a byte offset, this method locates the cached region within which the offset + falls, and returns the approximate end position in milliseconds of that region.
            @@ -344,16 +344,15 @@

            release

          • getRegionEndTimeMs

            public int getRegionEndTimeMs​(long byteOffset)
            -
            When provided with a byte offset, this method locates the cached region within which the - offset falls, and returns the approximate end position in milliseconds of that region. If the - byte offset does not fall within a cached region then NOT_CACHED is returned. - If the cached region extends to the end of the stream, CACHED_TO_END is returned.
            +
            When provided with a byte offset, this method locates the cached region within which the offset + falls, and returns the approximate end position in milliseconds of that region. If the byte + offset does not fall within a cached region then NOT_CACHED is returned. If the cached + region extends to the end of the stream, CACHED_TO_END is returned.
            Parameters:
            byteOffset - The byte offset in the underlying stream.
            Returns:
            -
            The end position of the corresponding cache region, NOT_CACHED, or - CACHED_TO_END.
            +
            The end position of the corresponding cache region, NOT_CACHED, or CACHED_TO_END.
          diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/cache/DefaultContentMetadata.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/cache/DefaultContentMetadata.html index e2994364c6d..7e5427041aa 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/cache/DefaultContentMetadata.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/cache/DefaultContentMetadata.html @@ -216,7 +216,7 @@

          Method Summary

          boolean -contains​(String name) +contains​(String key)
          Returns whether the metadata is available.
          @@ -242,7 +242,7 @@

          Method Summary

          byte[] -get​(String name, +get​(String key, byte[] defaultValue)
          Returns a metadata value.
          @@ -250,7 +250,7 @@

          Method Summary

          long -get​(String name, +get​(String key, long defaultValue)
          Returns a metadata value.
          @@ -258,7 +258,7 @@

          Method Summary

          String -get​(String name, +get​(String key, String defaultValue)
          Returns a metadata value.
          @@ -373,7 +373,7 @@

          entrySet

        • get

          @Nullable
          -public final byte[] get​(String name,
          +public final byte[] get​(String key,
                                   @Nullable
                                   byte[] defaultValue)
          Description copied from interface: ContentMetadata
          @@ -382,7 +382,7 @@

          get

          Specified by:
          get in interface ContentMetadata
          Parameters:
          -
          name - Key of the metadata to be returned.
          +
          key - Key of the metadata to be returned.
          defaultValue - Value to return if the metadata doesn't exist.
          Returns:
          The metadata value.
          @@ -396,7 +396,7 @@

          get

        • get

          @Nullable
          -public final String get​(String name,
          +public final String get​(String key,
                                   @Nullable
                                   String defaultValue)
          Description copied from interface: ContentMetadata
          @@ -405,7 +405,7 @@

          get

          Specified by:
          get in interface ContentMetadata
          Parameters:
          -
          name - Key of the metadata to be returned.
          +
          key - Key of the metadata to be returned.
          defaultValue - Value to return if the metadata doesn't exist.
          Returns:
          The metadata value.
          @@ -418,7 +418,7 @@

          get

          • get

            -
            public final long get​(String name,
            +
            public final long get​(String key,
                                   long defaultValue)
            Description copied from interface: ContentMetadata
            Returns a metadata value.
            @@ -426,7 +426,7 @@

            get

            Specified by:
            get in interface ContentMetadata
            Parameters:
            -
            name - Key of the metadata to be returned.
            +
            key - Key of the metadata to be returned.
            defaultValue - Value to return if the metadata doesn't exist.
            Returns:
            The metadata value.
            @@ -439,7 +439,7 @@

            get

            • contains

              -
              public final boolean contains​(String name)
              +
              public final boolean contains​(String key)
              Description copied from interface: ContentMetadata
              Returns whether the metadata is available.
              diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/cache/NoOpCacheEvictor.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/cache/NoOpCacheEvictor.html index ec083f00bc9..6e37e07a75a 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/cache/NoOpCacheEvictor.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/cache/NoOpCacheEvictor.html @@ -218,7 +218,7 @@

              Method Summary

              onStartFile​(Cache cache, String key, long position, - long maxLength) + long length)
              Called when a writer starts writing to the cache.
              @@ -315,7 +315,7 @@

              onStartFile

              public void onStartFile​(Cache cache,
                                       String key,
                                       long position,
              -                        long maxLength)
              + long length)
            Description copied from interface: CacheEvictor
            Called when a writer starts writing to the cache.
            @@ -325,7 +325,7 @@

            onStartFile

            cache - The source of the event.
            key - The key being written.
            position - The starting position of the data being written.
            -
            maxLength - The length of the data being written, or C.LENGTH_UNSET if unknown.
            +
            length - The length of the data being written, or C.LENGTH_UNSET if unknown.
          diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/crypto/AesCipherDataSink.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/crypto/AesCipherDataSink.html index 2c07727ed89..b80af075a5a 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/crypto/AesCipherDataSink.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/crypto/AesCipherDataSink.html @@ -223,7 +223,7 @@

          Method Summary

          void -write​(byte[] data, +write​(byte[] buffer, int offset, int length) @@ -335,7 +335,7 @@

          open

          • write

            -
            public void write​(byte[] data,
            +
            public void write​(byte[] buffer,
                               int offset,
                               int length)
                        throws IOException
            @@ -345,7 +345,7 @@

            write

            Specified by:
            write in interface DataSink
            Parameters:
            -
            data - The buffer from which data should be consumed.
            +
            buffer - The buffer from which data should be consumed.
            offset - The offset of the data to consume in buffer.
            length - The length of the data to consume, in bytes.
            Throws:
            diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/crypto/AesCipherDataSource.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/crypto/AesCipherDataSource.html index bbc22ba7734..28403c9b43c 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/crypto/AesCipherDataSource.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/crypto/AesCipherDataSource.html @@ -234,9 +234,9 @@

            Method Summary

            int -read​(byte[] data, +read​(byte[] buffer, int offset, - int readLength) + int length)
            Reads up to length bytes of data from the input.
            @@ -351,9 +351,9 @@

            open

            @@ -222,6 +227,7 @@

            Annotation Type Hierarchy

          • com.google.android.exoplayer2.upstream.DataSpec.Flags (implements java.lang.annotation.Annotation)
          • com.google.android.exoplayer2.upstream.DataSpec.HttpMethod (implements java.lang.annotation.Annotation)
          • com.google.android.exoplayer2.upstream.HttpDataSource.HttpDataSourceException.Type (implements java.lang.annotation.Annotation)
          • +
          • com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.FallbackType (implements java.lang.annotation.Annotation)
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/util/AtomicFile.html b/docs/doc/reference/com/google/android/exoplayer2/util/AtomicFile.html index 2d4cd228627..cc824441893 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/util/AtomicFile.html +++ b/docs/doc/reference/com/google/android/exoplayer2/util/AtomicFile.html @@ -294,8 +294,8 @@

    startWrite

    throws IOException
    Start a new write operation on the file. This returns an OutputStream to which you can write the new file data. If the whole data is written successfully you must call - endWrite(OutputStream). On failure you should call OutputStream.close() - only to free up resources used by it. + endWrite(OutputStream). On failure you should call OutputStream.close() only + to free up resources used by it.

    Example usage: diff --git a/docs/doc/reference/com/google/android/exoplayer2/util/BundleableUtils.html b/docs/doc/reference/com/google/android/exoplayer2/util/BundleableUtils.html new file mode 100644 index 00000000000..74e3ce18597 --- /dev/null +++ b/docs/doc/reference/com/google/android/exoplayer2/util/BundleableUtils.html @@ -0,0 +1,370 @@ + + + + +BundleableUtils (ExoPlayer library) + + + + + + + + + + + + +

    JavaScript is disabled on your browser.
    + +
    + +
    + +
    +
    + +

    Class BundleableUtils

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.google.android.exoplayer2.util.BundleableUtils
      • +
      +
    • +
    +
    +
      +
    • +
      +
      public final class BundleableUtils
      +extends Object
      +
      Utilities for Bundleable.
      +
    • +
    +
    +
    + +
    +
    + +
    +
    +
    + +
    + +
    + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/util/DebugTextViewHelper.html b/docs/doc/reference/com/google/android/exoplayer2/util/DebugTextViewHelper.html index 694c5eb857c..22623a7b091 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/util/DebugTextViewHelper.html +++ b/docs/doc/reference/com/google/android/exoplayer2/util/DebugTextViewHelper.html @@ -218,7 +218,7 @@

    Method Summary

    void onPlayWhenReadyChanged​(boolean playWhenReady, - int playbackState) + int reason)
    Called when the value returned from Player.getPlayWhenReady() changes.
    @@ -269,14 +269,14 @@

    Methods inherited from class java.lang.Player.EventListener

    -onLoadingChanged, onPlayerStateChanged, onPositionDiscontinuity, onSeekProcessed, onTimelineChanged +onLoadingChanged, onMaxSeekToPreviousPositionChanged, onPlayerStateChanged, onPositionDiscontinuity, onSeekProcessed, onStaticMetadataChanged

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/util/EventLogger.html b/docs/doc/reference/com/google/android/exoplayer2/util/EventLogger.html index 0b9bc335941..c2f2e354f16 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/util/EventLogger.html +++ b/docs/doc/reference/com/google/android/exoplayer2/util/EventLogger.html @@ -25,7 +25,7 @@ catch(err) { } //--> -var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10,"i21":10,"i22":10,"i23":10,"i24":10,"i25":10,"i26":10,"i27":10,"i28":10,"i29":10,"i30":10,"i31":10,"i32":10,"i33":10,"i34":10,"i35":10,"i36":10,"i37":10,"i38":10,"i39":10,"i40":10,"i41":10,"i42":10,"i43":10,"i44":10,"i45":10,"i46":10,"i47":10,"i48":10}; +var data = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10,"i21":10,"i22":10,"i23":10,"i24":10,"i25":10,"i26":10,"i27":10,"i28":10,"i29":10,"i30":10,"i31":10,"i32":10,"i33":10,"i34":10,"i35":10,"i36":10,"i37":10,"i38":10,"i39":10,"i40":10,"i41":10,"i42":10,"i43":10,"i44":10,"i45":10,"i46":10,"i47":10}; var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -172,7 +172,7 @@

    Field Summary

    Fields inherited from interface com.google.android.exoplayer2.analytics.AnalyticsListener

    -EVENT_AUDIO_ATTRIBUTES_CHANGED, EVENT_AUDIO_CODEC_ERROR, EVENT_AUDIO_DECODER_INITIALIZED, EVENT_AUDIO_DECODER_RELEASED, EVENT_AUDIO_DISABLED, EVENT_AUDIO_ENABLED, EVENT_AUDIO_INPUT_FORMAT_CHANGED, EVENT_AUDIO_POSITION_ADVANCING, EVENT_AUDIO_SESSION_ID, EVENT_AUDIO_SINK_ERROR, EVENT_AUDIO_UNDERRUN, EVENT_BANDWIDTH_ESTIMATE, EVENT_DOWNSTREAM_FORMAT_CHANGED, EVENT_DRM_KEYS_LOADED, EVENT_DRM_KEYS_REMOVED, EVENT_DRM_KEYS_RESTORED, EVENT_DRM_SESSION_ACQUIRED, EVENT_DRM_SESSION_MANAGER_ERROR, EVENT_DRM_SESSION_RELEASED, EVENT_DROPPED_VIDEO_FRAMES, EVENT_IS_LOADING_CHANGED, EVENT_IS_PLAYING_CHANGED, EVENT_LOAD_CANCELED, EVENT_LOAD_COMPLETED, EVENT_LOAD_ERROR, EVENT_LOAD_STARTED, EVENT_MEDIA_ITEM_TRANSITION, EVENT_MEDIA_METADATA_CHANGED, EVENT_METADATA, EVENT_PLAY_WHEN_READY_CHANGED, EVENT_PLAYBACK_PARAMETERS_CHANGED, EVENT_PLAYBACK_STATE_CHANGED, EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED, EVENT_PLAYER_ERROR, EVENT_PLAYER_RELEASED, EVENT_POSITION_DISCONTINUITY, EVENT_RENDERED_FIRST_FRAME, EVENT_REPEAT_MODE_CHANGED, EVENT_SHUFFLE_MODE_ENABLED_CHANGED, EVENT_SKIP_SILENCE_ENABLED_CHANGED, EVENT_STATIC_METADATA_CHANGED, EVENT_SURFACE_SIZE_CHANGED, EVENT_TIMELINE_CHANGED, EVENT_TRACKS_CHANGED, EVENT_UPSTREAM_DISCARDED, EVENT_VIDEO_CODEC_ERROR, EVENT_VIDEO_DECODER_INITIALIZED, EVENT_VIDEO_DECODER_RELEASED, EVENT_VIDEO_DISABLED, EVENT_VIDEO_ENABLED, EVENT_VIDEO_FRAME_PROCESSING_OFFSET, EVENT_VIDEO_INPUT_FORMAT_CHANGED, EVENT_VIDEO_SIZE_CHANGED, EVENT_VOLUME_CHANGED +EVENT_AUDIO_ATTRIBUTES_CHANGED, EVENT_AUDIO_CODEC_ERROR, EVENT_AUDIO_DECODER_INITIALIZED, EVENT_AUDIO_DECODER_RELEASED, EVENT_AUDIO_DISABLED, EVENT_AUDIO_ENABLED, EVENT_AUDIO_INPUT_FORMAT_CHANGED, EVENT_AUDIO_POSITION_ADVANCING, EVENT_AUDIO_SESSION_ID, EVENT_AUDIO_SINK_ERROR, EVENT_AUDIO_UNDERRUN, EVENT_AVAILABLE_COMMANDS_CHANGED, EVENT_BANDWIDTH_ESTIMATE, EVENT_DOWNSTREAM_FORMAT_CHANGED, EVENT_DRM_KEYS_LOADED, EVENT_DRM_KEYS_REMOVED, EVENT_DRM_KEYS_RESTORED, EVENT_DRM_SESSION_ACQUIRED, EVENT_DRM_SESSION_MANAGER_ERROR, EVENT_DRM_SESSION_RELEASED, EVENT_DROPPED_VIDEO_FRAMES, EVENT_IS_LOADING_CHANGED, EVENT_IS_PLAYING_CHANGED, EVENT_LOAD_CANCELED, EVENT_LOAD_COMPLETED, EVENT_LOAD_ERROR, EVENT_LOAD_STARTED, EVENT_MAX_SEEK_TO_PREVIOUS_POSITION_CHANGED, EVENT_MEDIA_ITEM_TRANSITION, EVENT_MEDIA_METADATA_CHANGED, EVENT_METADATA, EVENT_PLAY_WHEN_READY_CHANGED, EVENT_PLAYBACK_PARAMETERS_CHANGED, EVENT_PLAYBACK_STATE_CHANGED, EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED, EVENT_PLAYER_ERROR, EVENT_PLAYER_RELEASED, EVENT_PLAYLIST_METADATA_CHANGED, EVENT_POSITION_DISCONTINUITY, EVENT_RENDERED_FIRST_FRAME, EVENT_REPEAT_MODE_CHANGED, EVENT_SEEK_BACK_INCREMENT_CHANGED, EVENT_SEEK_FORWARD_INCREMENT_CHANGED, EVENT_SHUFFLE_MODE_ENABLED_CHANGED, EVENT_SKIP_SILENCE_ENABLED_CHANGED, EVENT_STATIC_METADATA_CHANGED, EVENT_SURFACE_SIZE_CHANGED, EVENT_TIMELINE_CHANGED, EVENT_TRACKS_CHANGED, EVENT_UPSTREAM_DISCARDED, EVENT_VIDEO_CODEC_ERROR, EVENT_VIDEO_DECODER_INITIALIZED, EVENT_VIDEO_DECODER_RELEASED, EVENT_VIDEO_DISABLED, EVENT_VIDEO_ENABLED, EVENT_VIDEO_FRAME_PROCESSING_OFFSET, EVENT_VIDEO_INPUT_FORMAT_CHANGED, EVENT_VIDEO_SIZE_CHANGED, EVENT_VOLUME_CHANGED @@ -261,7 +261,7 @@

    Method Summary

    void onAudioDisabled​(AnalyticsListener.EventTime eventTime, - DecoderCounters counters) + DecoderCounters decoderCounters)
    Called when an audio renderer is disabled.
    @@ -269,7 +269,7 @@

    Method Summary

    void onAudioEnabled​(AnalyticsListener.EventTime eventTime, - DecoderCounters counters) + DecoderCounters decoderCounters)
    Called when an audio renderer is enabled.
    @@ -351,7 +351,7 @@

    Method Summary

    void onDrmSessionManagerError​(AnalyticsListener.EventTime eventTime, - Exception e) + Exception error)
    Called when a drm error occurs.
    @@ -366,7 +366,7 @@

    Method Summary

    void onDroppedVideoFrames​(AnalyticsListener.EventTime eventTime, - int count, + int droppedFrames, long elapsedMs)
    Called after video frames have been dropped.
    @@ -469,8 +469,8 @@

    Method Summary

    void -onPlayerError​(AnalyticsListener.EventTime eventTime, - ExoPlaybackException e) +onPlayerError​(AnalyticsListener.EventTime eventTime, + PlaybackException error)
    Called when a fatal player error occurred.
    @@ -530,14 +530,6 @@

    Method Summary

    void -onStaticMetadataChanged​(AnalyticsListener.EventTime eventTime, - List<Metadata> metadataList) - -
    Called when the static metadata changes.
    - - - -void onSurfaceSizeChanged​(AnalyticsListener.EventTime eventTime, int width, int height) @@ -545,7 +537,7 @@

    Method Summary

    Called when the output surface size changed.
    - + void onTimelineChanged​(AnalyticsListener.EventTime eventTime, int reason) @@ -553,16 +545,16 @@

    Method Summary

    Called when the timeline changed.
    - + void onTracksChanged​(AnalyticsListener.EventTime eventTime, - TrackGroupArray ignored, + TrackGroupArray trackGroups, TrackSelectionArray trackSelections)
    Called when the available or selected tracks for the renderers changed.
    - + void onUpstreamDiscarded​(AnalyticsListener.EventTime eventTime, MediaLoadData mediaLoadData) @@ -571,14 +563,14 @@

    Method Summary

    re-buffered in a different format. - + void onVideoDecoderInitialized​(AnalyticsListener.EventTime eventTime, String decoderName, long initializationDurationMs)   - + void onVideoDecoderReleased​(AnalyticsListener.EventTime eventTime, String decoderName) @@ -586,23 +578,23 @@

    Method Summary

    Called when a video renderer releases a decoder.
    - + void onVideoDisabled​(AnalyticsListener.EventTime eventTime, - DecoderCounters counters) + DecoderCounters decoderCounters)
    Called when a video renderer is disabled.
    - + void onVideoEnabled​(AnalyticsListener.EventTime eventTime, - DecoderCounters counters) + DecoderCounters decoderCounters)
    Called when a video renderer is enabled.
    - + void onVideoInputFormatChanged​(AnalyticsListener.EventTime eventTime, Format format, @@ -611,7 +603,7 @@

    Method Summary

    Called when the format of the media being consumed by a video renderer changes.
    - + void onVideoSizeChanged​(AnalyticsListener.EventTime eventTime, VideoSize videoSize) @@ -620,7 +612,7 @@

    Method Summary

    there's a change in the size or pixel aspect ratio of the video being rendered. - + void onVolumeChanged​(AnalyticsListener.EventTime eventTime, float volume) @@ -641,7 +633,7 @@

    Methods inherited from class java.lang.AnalyticsListener

    -onAudioCodecError, onAudioDecoderInitialized, onAudioInputFormatChanged, onAudioPositionAdvancing, onAudioSinkError, onDecoderDisabled, onDecoderEnabled, onDecoderInitialized, onDecoderInputFormatChanged, onDrmSessionAcquired, onEvents, onLoadingChanged, onMediaMetadataChanged, onPlayerReleased, onPlayerStateChanged, onPositionDiscontinuity, onSeekProcessed, onSeekStarted, onVideoCodecError, onVideoDecoderInitialized, onVideoFrameProcessingOffset, onVideoInputFormatChanged, onVideoSizeChanged +onAudioCodecError, onAudioDecoderInitialized, onAudioInputFormatChanged, onAudioPositionAdvancing, onAudioSinkError, onAvailableCommandsChanged, onDecoderDisabled, onDecoderEnabled, onDecoderInitialized, onDecoderInputFormatChanged, onDrmSessionAcquired, onEvents, onLoadingChanged, onMaxSeekToPreviousPositionChanged, onMediaMetadataChanged, onPlayerReleased, onPlayerStateChanged, onPlaylistMetadataChanged, onPositionDiscontinuity, onSeekBackIncrementChanged, onSeekForwardIncrementChanged, onSeekProcessed, onSeekStarted, onStaticMetadataChanged, onVideoCodecError, onVideoDecoderInitialized, onVideoFrameProcessingOffset, onVideoInputFormatChanged, onVideoSizeChanged @@ -927,22 +919,24 @@

    onMediaItemTransition

    - + @@ -953,7 +947,7 @@

    onPlayerError

  • onTracksChanged

    public void onTracksChanged​(AnalyticsListener.EventTime eventTime,
    -                            TrackGroupArray ignored,
    +                            TrackGroupArray trackGroups,
                                 TrackSelectionArray trackSelections)
    Description copied from interface: AnalyticsListener
    Called when the available or selected tracks for the renderers changed.
    @@ -962,38 +956,11 @@

    onTracksChanged

    onTracksChanged in interface AnalyticsListener
    Parameters:
    eventTime - The event time.
    -
    ignored - The available tracks. May be empty.
    +
    trackGroups - The available tracks. May be empty.
    trackSelections - The track selections for each renderer. May contain null elements.
  • - - - -
      -
    • -

      onStaticMetadataChanged

      -
      public void onStaticMetadataChanged​(AnalyticsListener.EventTime eventTime,
      -                                    List<Metadata> metadataList)
      -
      Description copied from interface: AnalyticsListener
      -
      Called when the static metadata changes. - -

      The provided metadataList is an immutable list of Metadata instances, where - the elements correspond to the current track selections (as returned by AnalyticsListener.onTracksChanged(EventTime, TrackGroupArray, TrackSelectionArray), or an empty list if there - are no track selections or the selected tracks contain no static metadata. - -

      The metadata is considered static in the sense that it comes from the tracks' declared - Formats, rather than being timed (or dynamic) metadata, which is represented within a metadata - track.

      -
      -
      Specified by:
      -
      onStaticMetadataChanged in interface AnalyticsListener
      -
      Parameters:
      -
      eventTime - The event time.
      -
      metadataList - The static metadata.
      -
      -
    • -
    @@ -1020,7 +987,7 @@

    onMetadata

  • onAudioEnabled

    public void onAudioEnabled​(AnalyticsListener.EventTime eventTime,
    -                           DecoderCounters counters)
    + DecoderCounters decoderCounters)
    Description copied from interface: AnalyticsListener
    Called when an audio renderer is enabled.
    @@ -1028,8 +995,8 @@

    onAudioEnabled

    onAudioEnabled in interface AnalyticsListener
    Parameters:
    eventTime - The event time.
    -
    counters - DecoderCounters that will be updated by the renderer for as long as it - remains enabled.
    +
    decoderCounters - DecoderCounters that will be updated by the renderer for as long + as it remains enabled.
  • @@ -1122,7 +1089,7 @@

    onAudioDecoderReleased

  • onAudioDisabled

    public void onAudioDisabled​(AnalyticsListener.EventTime eventTime,
    -                            DecoderCounters counters)
    + DecoderCounters decoderCounters)
    Description copied from interface: AnalyticsListener
    Called when an audio renderer is disabled.
    @@ -1130,7 +1097,7 @@

    onAudioDisabled

    onAudioDisabled in interface AnalyticsListener
    Parameters:
    eventTime - The event time.
    -
    counters - DecoderCounters that were updated by the renderer.
    +
    decoderCounters - DecoderCounters that were updated by the renderer.
  • @@ -1217,7 +1184,7 @@

    onVolumeChanged

  • onVideoEnabled

    public void onVideoEnabled​(AnalyticsListener.EventTime eventTime,
    -                           DecoderCounters counters)
    + DecoderCounters decoderCounters)
    Description copied from interface: AnalyticsListener
    Called when a video renderer is enabled.
    @@ -1225,8 +1192,8 @@

    onVideoEnabled

    onVideoEnabled in interface AnalyticsListener
    Parameters:
    eventTime - The event time.
    -
    counters - DecoderCounters that will be updated by the renderer for as long as it - remains enabled.
    +
    decoderCounters - DecoderCounters that will be updated by the renderer for as long + as it remains enabled.
  • @@ -1276,7 +1243,7 @@

    onVideoInputFormatChanged

  • onDroppedVideoFrames

    public void onDroppedVideoFrames​(AnalyticsListener.EventTime eventTime,
    -                                 int count,
    +                                 int droppedFrames,
                                      long elapsedMs)
    Description copied from interface: AnalyticsListener
    Called after video frames have been dropped.
    @@ -1285,7 +1252,7 @@

    onDroppedVideoFrames

    onDroppedVideoFrames in interface AnalyticsListener
    Parameters:
    eventTime - The event time.
    -
    count - The number of dropped frames since the last call to this method.
    +
    droppedFrames - The number of dropped frames since the last call to this method.
    elapsedMs - The duration in milliseconds over which the frames were dropped. This duration is timed from when the renderer was started or from when dropped frames were last reported (whichever was more recent), and not from when the first of the reported drops occurred.
    @@ -1318,7 +1285,7 @@

    onVideoDecoderReleased

  • onVideoDisabled

    public void onVideoDisabled​(AnalyticsListener.EventTime eventTime,
    -                            DecoderCounters counters)
    + DecoderCounters decoderCounters)
    Description copied from interface: AnalyticsListener
    Called when a video renderer is disabled.
    @@ -1326,7 +1293,7 @@

    onVideoDisabled

    onVideoDisabled in interface AnalyticsListener
    Parameters:
    eventTime - The event time.
    -
    counters - DecoderCounters that were updated by the renderer.
    +
    decoderCounters - DecoderCounters that were updated by the renderer.
  • @@ -1411,7 +1378,7 @@

    onLoadError

    This method being called does not indicate that playback has failed, or that it will fail. The player may be able to recover from the error. Hence applications should not implement this method to display a user visible error or initiate an application level retry. - Player.Listener.onPlayerError(com.google.android.exoplayer2.ExoPlaybackException) is the appropriate place to implement such behavior. This + Player.Listener.onPlayerError(com.google.android.exoplayer2.PlaybackException) is the appropriate place to implement such behavior. This method is called to provide the application with an opportunity to log the error if it wishes to do so.

    @@ -1580,14 +1547,14 @@

    onDrmSessionAcquired

  • onDrmSessionManagerError

    public void onDrmSessionManagerError​(AnalyticsListener.EventTime eventTime,
    -                                     Exception e)
    + Exception error)
    Description copied from interface: AnalyticsListener
    Called when a drm error occurs.

    This method being called does not indicate that playback has failed, or that it will fail. The player may be able to recover from the error. Hence applications should not implement this method to display a user visible error or initiate an application level retry. - Player.Listener.onPlayerError(com.google.android.exoplayer2.ExoPlaybackException) is the appropriate place to implement such behavior. This + Player.Listener.onPlayerError(com.google.android.exoplayer2.PlaybackException) is the appropriate place to implement such behavior. This method is called to provide the application with an opportunity to log the error if it wishes to do so.

    @@ -1595,7 +1562,7 @@

    onDrmSessionManagerError

    onDrmSessionManagerError in interface AnalyticsListener
    Parameters:
    eventTime - The event time.
    -
    e - The error.
    +
    error - The error.
  • diff --git a/docs/doc/reference/com/google/android/exoplayer2/util/ExoFlags.Builder.html b/docs/doc/reference/com/google/android/exoplayer2/util/FlagSet.Builder.html similarity index 68% rename from docs/doc/reference/com/google/android/exoplayer2/util/ExoFlags.Builder.html rename to docs/doc/reference/com/google/android/exoplayer2/util/FlagSet.Builder.html index 17bc263de28..a3e03554886 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/util/ExoFlags.Builder.html +++ b/docs/doc/reference/com/google/android/exoplayer2/util/FlagSet.Builder.html @@ -2,7 +2,7 @@ -ExoFlags.Builder (ExoPlayer library) +FlagSet.Builder (ExoPlayer library) @@ -19,13 +19,13 @@ + + + + + + + + + +
    + +
    + +
    +
    + +

    Class NetworkTypeObserver.Config

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.google.android.exoplayer2.util.NetworkTypeObserver.Config
      • +
      +
    • +
    +
    + +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          disable5GNsaDisambiguation

          +
          public static void disable5GNsaDisambiguation()
          +
          Disables logic to disambiguate 5G-NSA networks from 4G networks.
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +
    + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/util/NetworkTypeObserver.html b/docs/doc/reference/com/google/android/exoplayer2/util/NetworkTypeObserver.html index 2bdf551ec32..32f92591b7f 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/util/NetworkTypeObserver.html +++ b/docs/doc/reference/com/google/android/exoplayer2/util/NetworkTypeObserver.html @@ -158,6 +158,13 @@

    Nested Class Summary

    Description +static class  +NetworkTypeObserver.Config + +
    Configuration for NetworkTypeObserver.
    + + + static interface  NetworkTypeObserver.Listener diff --git a/docs/doc/reference/com/google/android/exoplayer2/util/ParsableByteArray.html b/docs/doc/reference/com/google/android/exoplayer2/util/ParsableByteArray.html index 9123bfcbc92..175bce0496f 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/util/ParsableByteArray.html +++ b/docs/doc/reference/com/google/android/exoplayer2/util/ParsableByteArray.html @@ -265,8 +265,8 @@

    Method Summary

    readBytes​(ParsableBitArray bitArray, int length) -
    Reads the next length bytes into bitArray, and resets the position of - bitArray to zero.
    +
    Reads the next length bytes into bitArray, and resets the position of + bitArray to zero.
    @@ -786,8 +786,8 @@

    skipBytes

    readBytes

    public void readBytes​(ParsableBitArray bitArray,
                           int length)
    -
    Reads the next length bytes into bitArray, and resets the position of - bitArray to zero.
    +
    Reads the next length bytes into bitArray, and resets the position of + bitArray to zero.
    Parameters:
    bitArray - The ParsableBitArray into which the bytes should be read.
    @@ -1021,8 +1021,8 @@

    readUnsignedFixedPoint1616

    readSynchSafeInt

    public int readSynchSafeInt()
    Reads a Synchsafe integer. -

    - Synchsafe integers keep the highest bit of every byte zeroed. A 32 bit synchsafe integer can + +

    Synchsafe integers keep the highest bit of every byte zeroed. A 32 bit synchsafe integer can store 28 bits of information.

    Returns:
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/util/TimestampAdjuster.html b/docs/doc/reference/com/google/android/exoplayer2/util/TimestampAdjuster.html index e93d2f0f624..0955ea38996 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/util/TimestampAdjuster.html +++ b/docs/doc/reference/com/google/android/exoplayer2/util/TimestampAdjuster.html @@ -131,8 +131,8 @@

    Class TimestampAdjuster


    public final class TimestampAdjuster
     extends Object
    -
    Offsets timestamps according to an initial sample timestamp offset. MPEG-2 TS timestamps scaling - and adjustment is supported, taking into account timestamp rollover.
    +
    Adjusts and offsets sample timestamps. MPEG-2 TS timestamps scaling and adjustment is supported, + taking into account timestamp rollover.
    @@ -155,12 +155,20 @@

    Field Summary

    static long -DO_NOT_OFFSET +MODE_NO_OFFSET
    A special firstSampleTimestampUs value indicating that presentation timestamps should not be offset.
    + +static long +MODE_SHARED + +
    A special firstSampleTimestampUs value indicating that the adjuster will be shared by + multiple threads.
    + + @@ -218,21 +226,22 @@

    Method Summary

    long getFirstSampleTimestampUs() -
    Returns the value of the first adjusted sample timestamp in microseconds, or DO_NOT_OFFSET if timestamps will not be offset.
    +
    Returns the value of the first adjusted sample timestamp in microseconds, or C.TIME_UNSET if timestamps will not be offset or if the adjuster is in shared mode.
    long getLastAdjustedTimestampUs() -
    Returns the last value obtained from adjustSampleTimestamp(long).
    +
    Returns the last adjusted timestamp, in microseconds.
    long getTimestampOffsetUs() -
    Returns the offset between the input of adjustSampleTimestamp(long) and its output.
    +
    Returns the offset between the input of adjustSampleTimestamp(long) and its output, or + C.TIME_UNSET if the offset has not yet been determined.
    @@ -246,13 +255,13 @@

    Method Summary

    void reset​(long firstSampleTimestampUs) -
    Resets the instance to its initial state.
    +
    Resets the instance.
    void sharedInitializeOrWait​(boolean canInitialize, - long startTimeUs) + long nextSampleTimestampUs)
    For shared timestamp adjusters, performs necessary initialization actions for a caller.
    @@ -296,18 +305,43 @@

    Methods inherited from class java.lang. + -
      +
      • -

        DO_NOT_OFFSET

        -
        public static final long DO_NOT_OFFSET
        +

        MODE_NO_OFFSET

        +
        public static final long MODE_NO_OFFSET
        A special firstSampleTimestampUs value indicating that presentation timestamps should - not be offset.
        + not be offset. In this mode: + +
        See Also:
        -
        Constant Field Values
        +
        Constant Field Values
        +
        +
      • +
      + + + + @@ -331,7 +365,7 @@

      TimestampAdjuster

      Parameters:
      firstSampleTimestampUs - The desired value of the first adjusted sample timestamp in - microseconds, or DO_NOT_OFFSET if timestamps should not be offset.
      + microseconds, or MODE_NO_OFFSET if timestamps should not be offset, or MODE_SHARED if the adjuster will be used in shared mode.
    @@ -352,32 +386,26 @@

    Method Detail

  • sharedInitializeOrWait

    public void sharedInitializeOrWait​(boolean canInitialize,
    -                                   long startTimeUs)
    +                                   long nextSampleTimestampUs)
                                 throws InterruptedException
    For shared timestamp adjusters, performs necessary initialization actions for a caller.
      -
    • If the adjuster does not yet have a target first sample - timestamp and if canInitialize is true, then initialization is started - by setting the target first sample timestamp to firstSampleTimestampUs. The call - returns, allowing the caller to proceed. Initialization completes when a caller adjusts - the first timestamp. -
    • If canInitialize is true and the adjuster already has a target first sample timestamp, then the call returns to allow the - caller to proceed only if firstSampleTimestampUs is equal to the target. This - ensures a caller that's previously started initialization can continue to proceed. It - also allows other callers with the same firstSampleTimestampUs to proceed, since - in this case it doesn't matter which caller adjusts the first timestamp to complete - initialization. -
    • If canInitialize is false or if firstSampleTimestampUs differs - from the target first sample timestamp, then the call - blocks until initialization completes. If initialization has already been completed the - call returns immediately. +
    • If the adjuster has already established a timestamp offset + then this method is a no-op. +
    • If canInitialize is true and the adjuster has not yet established a + timestamp offset, then the adjuster records the desired first sample timestamp for the + calling thread and returns to allow the caller to proceed. If the timestamp offset has + still not been established when the caller attempts to adjust its first timestamp, then + the recorded timestamp is used to set it. +
    • If canInitialize is false and the adjuster has not yet established a + timestamp offset, then the call blocks until the timestamp offset is set.
    Parameters:
    canInitialize - Whether the caller is able to initialize the adjuster, if needed.
    -
    startTimeUs - The desired first sample timestamp of the caller, in microseconds. Only used - if canInitialize is true.
    +
    nextSampleTimestampUs - The desired timestamp for the next sample loaded by the calling + thread, in microseconds. Only used if canInitialize is true.
    Throws:
    InterruptedException - If the thread is interrupted whilst blocked waiting for initialization to complete.
    @@ -391,7 +419,7 @@

    sharedInitializeOrWait

  • getFirstSampleTimestampUs

    public long getFirstSampleTimestampUs()
    -
    Returns the value of the first adjusted sample timestamp in microseconds, or DO_NOT_OFFSET if timestamps will not be offset.
    +
    Returns the value of the first adjusted sample timestamp in microseconds, or C.TIME_UNSET if timestamps will not be offset or if the adjuster is in shared mode.
  • @@ -401,7 +429,8 @@

    getFirstSampleTimestampUs

  • getLastAdjustedTimestampUs

    public long getLastAdjustedTimestampUs()
    -
    +
    Returns the last adjusted timestamp, in microseconds. If no timestamps have been adjusted yet + then the result of getFirstSampleTimestampUs() is returned.
  • @@ -411,14 +440,8 @@

    getLastAdjustedTimestampUs

  • getTimestampOffsetUs

    public long getTimestampOffsetUs()
    -
    Returns the offset between the input of adjustSampleTimestamp(long) and its output. If - DO_NOT_OFFSET was provided to the constructor, 0 is returned. If the timestamp - adjuster is yet not initialized, C.TIME_UNSET is returned.
    -
    -
    Returns:
    -
    The offset between adjustSampleTimestamp(long)'s input and output. C.TIME_UNSET if the adjuster is not yet initialized and 0 if timestamps should not be - offset.
    -
    +
    Returns the offset between the input of adjustSampleTimestamp(long) and its output, or + C.TIME_UNSET if the offset has not yet been determined.
  • @@ -428,11 +451,12 @@

    getTimestampOffsetUs

  • reset

    public void reset​(long firstSampleTimestampUs)
    -
    Resets the instance to its initial state.
    +
    Resets the instance.
    Parameters:
    firstSampleTimestampUs - The desired value of the first adjusted sample timestamp after - this reset, in microseconds, or DO_NOT_OFFSET if timestamps should not be offset.
    + this reset in microseconds, or MODE_NO_OFFSET if timestamps should not be offset, + or MODE_SHARED if the adjuster will be used in shared mode.
  • diff --git a/docs/doc/reference/com/google/android/exoplayer2/util/UriUtil.html b/docs/doc/reference/com/google/android/exoplayer2/util/UriUtil.html index 78a4e60fe9f..e128a0a513e 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/util/UriUtil.html +++ b/docs/doc/reference/com/google/android/exoplayer2/util/UriUtil.html @@ -25,7 +25,7 @@ catch(err) { } //--> -var data = {"i0":9,"i1":9,"i2":9}; +var data = {"i0":9,"i1":9,"i2":9,"i3":9}; var tabs = {65535:["t0","All Methods"],1:["t1","Static Methods"],8:["t4","Concrete Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -153,14 +153,21 @@

    Method Summary

    Description +static boolean +isAbsolute​(String uri) + +
    Returns true if the URI is starting with a scheme component, false otherwise.
    + + + static Uri removeQueryParameter​(Uri uri, String queryParameterName) -
    Removes query parameter from an Uri, if present.
    +
    Removes query parameter from a URI, if present.
    - + static String resolve​(String baseUri, String referenceUri) @@ -168,7 +175,7 @@

    Method Summary

    Performs relative resolution of a referenceUri with respect to a baseUri.
    - + static Uri resolveToUri​(String baseUri, String referenceUri) @@ -238,6 +245,17 @@

    resolve

  • + + + +
      +
    • +

      isAbsolute

      +
      public static boolean isAbsolute​(@Nullable
      +                                 String uri)
      +
      Returns true if the URI is starting with a scheme component, false otherwise.
      +
    • +
    @@ -246,13 +264,13 @@

    resolve

    removeQueryParameter

    public static Uri removeQueryParameter​(Uri uri,
                                            String queryParameterName)
    -
    Removes query parameter from an Uri, if present.
    +
    Removes query parameter from a URI, if present.
    Parameters:
    -
    uri - The uri.
    +
    uri - The URI.
    queryParameterName - The name of the query parameter.
    Returns:
    -
    The uri without the query parameter.
    +
    The URI without the query parameter.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/util/Util.html b/docs/doc/reference/com/google/android/exoplayer2/util/Util.html index a2fc34c240f..01e0e37fedf 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/util/Util.html +++ b/docs/doc/reference/com/google/android/exoplayer2/util/Util.html @@ -25,7 +25,7 @@ catch(err) { } //--> -var data = {"i0":9,"i1":9,"i2":9,"i3":9,"i4":9,"i5":9,"i6":9,"i7":9,"i8":9,"i9":9,"i10":9,"i11":9,"i12":9,"i13":9,"i14":9,"i15":9,"i16":9,"i17":9,"i18":9,"i19":9,"i20":9,"i21":9,"i22":9,"i23":9,"i24":9,"i25":9,"i26":9,"i27":9,"i28":9,"i29":9,"i30":9,"i31":9,"i32":9,"i33":9,"i34":9,"i35":9,"i36":9,"i37":9,"i38":9,"i39":9,"i40":9,"i41":9,"i42":9,"i43":9,"i44":9,"i45":9,"i46":9,"i47":9,"i48":9,"i49":9,"i50":9,"i51":9,"i52":9,"i53":9,"i54":9,"i55":9,"i56":9,"i57":9,"i58":9,"i59":9,"i60":9,"i61":9,"i62":9,"i63":9,"i64":9,"i65":9,"i66":9,"i67":9,"i68":9,"i69":9,"i70":9,"i71":9,"i72":9,"i73":9,"i74":9,"i75":9,"i76":9,"i77":9,"i78":9,"i79":9,"i80":9,"i81":9,"i82":9,"i83":9,"i84":9,"i85":9,"i86":9,"i87":9,"i88":9,"i89":9,"i90":9,"i91":9,"i92":9,"i93":9,"i94":9,"i95":9,"i96":9,"i97":9,"i98":9,"i99":9,"i100":9,"i101":9,"i102":9,"i103":9,"i104":9,"i105":9,"i106":9,"i107":9,"i108":9,"i109":9,"i110":9,"i111":9,"i112":9}; +var data = {"i0":9,"i1":9,"i2":9,"i3":9,"i4":9,"i5":9,"i6":9,"i7":9,"i8":9,"i9":9,"i10":9,"i11":9,"i12":9,"i13":9,"i14":9,"i15":9,"i16":9,"i17":9,"i18":9,"i19":9,"i20":9,"i21":9,"i22":9,"i23":9,"i24":9,"i25":9,"i26":9,"i27":9,"i28":9,"i29":9,"i30":9,"i31":9,"i32":9,"i33":9,"i34":9,"i35":9,"i36":9,"i37":9,"i38":9,"i39":9,"i40":9,"i41":9,"i42":9,"i43":9,"i44":9,"i45":9,"i46":9,"i47":9,"i48":9,"i49":9,"i50":9,"i51":9,"i52":9,"i53":9,"i54":9,"i55":9,"i56":9,"i57":9,"i58":9,"i59":9,"i60":9,"i61":9,"i62":9,"i63":9,"i64":9,"i65":9,"i66":9,"i67":9,"i68":9,"i69":9,"i70":9,"i71":9,"i72":9,"i73":9,"i74":9,"i75":9,"i76":9,"i77":9,"i78":9,"i79":9,"i80":9,"i81":9,"i82":9,"i83":9,"i84":9,"i85":9,"i86":9,"i87":9,"i88":9,"i89":9,"i90":9,"i91":9,"i92":9,"i93":9,"i94":9,"i95":9,"i96":9,"i97":9,"i98":9,"i99":9,"i100":9,"i101":9,"i102":9,"i103":9,"i104":9,"i105":9,"i106":9,"i107":9,"i108":9,"i109":9,"i110":9,"i111":9,"i112":9,"i113":9}; var tabs = {65535:["t0","All Methods"],1:["t1","Static Methods"],8:["t4","Concrete Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -637,20 +637,27 @@

    Method Summary

    static int +getErrorCodeFromPlatformDiagnosticsInfo​(String diagnosticsInfo) + +
    Attempts to parse an error code from a diagnostic string found in framework media exceptions.
    + + + +static int getIntegerCodeForString​(String string)
    Returns the integer equal to the big-endian concatenation of the characters in string as bytes.
    - + static String getLocaleLanguageTag​(Locale locale)
    Returns the language tag for a Locale.
    - + static long getMediaDurationForPlayoutDuration​(long playoutDuration, float speed) @@ -658,21 +665,21 @@

    Method Summary

    Returns the duration of media that will elapse in playoutDuration.
    - + static long getNowUnixTimeMs​(long elapsedRealtimeEpochOffsetMs)
    Returns the current time in milliseconds since the epoch.
    - + static int getPcmEncoding​(int bitDepth)
    Converts a sample bit depth to a corresponding PCM encoding constant.
    - + static Format getPcmFormat​(int pcmEncoding, int channels, @@ -681,7 +688,7 @@

    Method Summary

    Gets a PCM Format with the specified parameters.
    - + static int getPcmFrameSize​(int pcmEncoding, int channelCount) @@ -689,7 +696,7 @@

    Method Summary

    Returns the frame size for audio with channelCount channels in the specified encoding.
    - + static long getPlayoutDurationForMediaDuration​(long mediaDuration, float speed) @@ -697,14 +704,14 @@

    Method Summary

    Returns the playout duration of mediaDuration of media.
    - + static int getStreamTypeForAudioUsage​(int usage)
    Returns the C.StreamType corresponding to the specified C.AudioUsage.
    - + static String getStringForTime​(StringBuilder builder, Formatter formatter, @@ -713,7 +720,7 @@

    Method Summary

    Returns the specified millisecond time formatted as a string.
    - + static String[] getSystemLanguageCodes() @@ -721,14 +728,14 @@

    Method Summary

    ordered by preference. - + static String getTrackTypeString​(int trackType)
    Returns a string representation of a TRACK_TYPE_* constant defined in C.
    - + static String getUserAgent​(Context context, String applicationName) @@ -736,28 +743,28 @@

    Method Summary

    Returns a user agent string based on the given application name and the library version.
    - + static byte[] getUtf8Bytes​(String value)
    Returns a new byte array containing the code points of a String encoded using UTF-8.
    - + static byte[] gzip​(byte[] input)
    Compresses input using gzip and returns the result in a newly allocated byte array.
    - + static int inferContentType​(Uri uri)
    Makes a best guess to infer the C.ContentType from a Uri.
    - + static int inferContentType​(Uri uri, String overrideExtension) @@ -765,14 +772,14 @@

    Method Summary

    Makes a best guess to infer the C.ContentType from a Uri.
    - + static int inferContentType​(String fileName)
    Makes a best guess to infer the C.ContentType from a file name.
    - + static int inferContentTypeForUriAndMimeType​(Uri uri, String mimeType) @@ -780,7 +787,7 @@

    Method Summary

    Makes a best guess to infer the C.ContentType from a Uri and optional MIME type.
    - + static boolean inflate​(ParsableByteArray input, ParsableByteArray output, @@ -789,42 +796,42 @@

    Method Summary

    Uncompresses the data in input.
    - + static boolean isEncodingHighResolutionPcm​(int encoding)
    Returns whether encoding is high resolution (> 16-bit) PCM.
    - + static boolean isEncodingLinearPcm​(int encoding)
    Returns whether encoding is one of the linear PCM encodings.
    - + static boolean isLinebreak​(int c)
    Returns whether the given character is a carriage return ('\r') or a line feed ('\n').
    - + static boolean isLocalFileUri​(Uri uri)
    Returns true if the URI is a path to a local file or a reference to a local file.
    - + static boolean isTv​(Context context)
    Returns whether the app is running on a TV device.
    - + static int linearSearch​(int[] array, int value) @@ -832,7 +839,7 @@

    Method Summary

    Returns the index of the first occurrence of value in array, or C.INDEX_UNSET if value is not contained in array.
    - + static int linearSearch​(long[] array, long value) @@ -840,7 +847,7 @@

    Method Summary

    Returns the index of the first occurrence of value in array, or C.INDEX_UNSET if value is not contained in array.
    - + static boolean maybeRequestReadExternalStoragePermission​(Activity activity, Uri... uris) @@ -849,7 +856,7 @@

    Method Summary

    permission read the specified Uris, requesting the permission if necessary. - + static boolean maybeRequestReadExternalStoragePermission​(Activity activity, MediaItem... mediaItems) @@ -859,14 +866,14 @@

    Method Summary

    necessary. - + static long minValue​(SparseLongArray sparseLongArray)
    Returns the minimum value in the given SparseLongArray.
    - + static <T> void moveItems​(List<T> items, int fromIndex, @@ -876,21 +883,21 @@

    Method Summary

    Moves the elements starting at fromIndex to newFromIndex.
    - + static ExecutorService newSingleThreadExecutor​(String threadName)
    Instantiates a new single threaded executor whose thread has the specified name.
    - + static @PolyNull String normalizeLanguageCode​(@PolyNull String language)
    Returns a normalized IETF BCP 47 language tag for language.
    - + static <T> T[] nullSafeArrayAppend​(T[] original, T newElement) @@ -898,7 +905,7 @@

    Method Summary

    Creates a new array containing original with newElement appended.
    - + static <T> T[] nullSafeArrayConcatenation​(T[] first, T[] second) @@ -906,7 +913,7 @@

    Method Summary

    Creates a new array containing the concatenation of two non-null type arrays.
    - + static <T> T[] nullSafeArrayCopy​(T[] input, int length) @@ -914,7 +921,7 @@

    Method Summary

    Copies and optionally truncates an array.
    - + static <T> T[] nullSafeArrayCopyOfRange​(T[] input, int from, @@ -923,7 +930,7 @@

    Method Summary

    Copies a subset of an array.
    - + static <T> void nullSafeListToArray​(List<T> list, T[] array) @@ -931,7 +938,7 @@

    Method Summary

    Copies the contents of list into array.
    - + static long parseXsDateTime​(String value) @@ -939,14 +946,14 @@

    Method Summary

    epoch. - + static long parseXsDuration​(String value)
    Parses an xs:duration attribute value, returning the parsed duration in milliseconds.
    - + static boolean postOrRun​(Handler handler, Runnable runnable) @@ -954,7 +961,7 @@

    Method Summary

    Posts the Runnable if the calling thread differs with the Looper of the Handler.
    - + static boolean readBoolean​(Parcel parcel) @@ -962,7 +969,7 @@

    Method Summary

    and all other values mapping to true. - + static byte[] readExactly​(DataSource dataSource, int length) @@ -971,7 +978,7 @@

    Method Summary

    array containing the read data. - + static byte[] readToEnd​(DataSource dataSource) @@ -979,14 +986,14 @@

    Method Summary

    containing the read data. - + static void recursiveDelete​(File fileOrDirectory)
    Recursively deletes a directory and its content.
    - + static <T> void removeRange​(List<T> list, int fromIndex, @@ -995,7 +1002,7 @@

    Method Summary

    Removes an indexed range from a List.
    - + static long scaleLargeTimestamp​(long timestamp, long multiplier, @@ -1004,7 +1011,7 @@

    Method Summary

    Scales a large timestamp.
    - + static long[] scaleLargeTimestamps​(List<Long> timestamps, long multiplier, @@ -1013,7 +1020,7 @@

    Method Summary

    Applies scaleLargeTimestamp(long, long, long) to a list of unscaled timestamps.
    - + static void scaleLargeTimestampsInPlace​(long[] timestamps, long multiplier, @@ -1022,15 +1029,15 @@

    Method Summary

    Applies scaleLargeTimestamp(long, long, long) to an array of unscaled timestamps.
    - + static void sneakyThrow​(Throwable t) -
    A hacky method that always throws t even if t is a checked exception, - and is not declared to be thrown.
    +
    A hacky method that always throws t even if t is a checked exception, and is + not declared to be thrown.
    - + static String[] split​(String value, String regex) @@ -1038,7 +1045,7 @@

    Method Summary

    Splits a string using value.split(regex, -1).
    - + static String[] splitAtFirst​(String value, String regex) @@ -1046,14 +1053,14 @@

    Method Summary

    Splits the string at the first occurrence of the delimiter regex.
    - + static String[] splitCodecs​(String codecs)
    Splits a codecs sequence string, as defined in RFC 6381, into individual codec strings.
    - + static ComponentName startForegroundService​(Context context, Intent intent) @@ -1062,7 +1069,7 @@

    Method Summary

    Context.startService(Intent) otherwise. - + static long subtractWithOverflowDefault​(long x, long y, @@ -1071,7 +1078,7 @@

    Method Summary

    Returns the difference between two arguments, or a third argument if the result overflows.
    - + static boolean tableExists​(SQLiteDatabase database, String tableName) @@ -1079,21 +1086,21 @@

    Method Summary

    Returns whether the table exists in the database.
    - + static byte[] toByteArray​(InputStream inputStream)
    Converts the entirety of an InputStream to a byte array.
    - + static String toHexString​(byte[] bytes)
    Returns a string containing a lower-case hex representation of the bytes provided.
    - + static long toLong​(int mostSignificantBits, int leastSignificantBits) @@ -1101,14 +1108,14 @@

    Method Summary

    Return the long that is composed of the bits of the 2 specified integers.
    - + static long toUnsignedLong​(int x)
    Converts an integer to a long by unsigned conversion.
    - + static CharSequence truncateAscii​(CharSequence sequence, int maxLength) @@ -1116,14 +1123,14 @@

    Method Summary

    Truncates a sequence of ASCII characters to a maximum length.
    - + static String unescapeFileName​(String fileName)
    Unescapes an escaped file or directory name back to its original value.
    - + static void writeBoolean​(Parcel parcel, boolean value) @@ -2161,8 +2168,8 @@

    binarySearchFloor

    boolean stayInBounds)
    Returns the index of the largest element in array that is less than (or optionally equal to) a specified value. -

    - The search is performed using a binary search algorithm, so the array must be sorted. If the + +

    The search is performed using a binary search algorithm, so the array must be sorted. If the array contains multiple elements equal to value and inclusive is true, the index of the first one will be returned.

    @@ -2430,9 +2437,9 @@

    scaleLargeTimestamp

    long multiplier, long divisor)
    Scales a large timestamp. -

    - Logically, scaling consists of a multiplication followed by a division. The actual operations - performed are designed to minimize the probability of overflow.

    + +

    Logically, scaling consists of a multiplication followed by a division. The actual + operations performed are designed to minimize the probability of overflow.

    Parameters:
    timestamp - The timestamp to scale.
    @@ -3000,10 +3007,9 @@

    escapeFileName

    Escapes a string so that it's safe for use as a file or directory name on at least FAT32 filesystems. FAT32 is the most restrictive of all filesystems still commonly used today. -

    For simplicity, this only handles common characters known to be illegal on FAT32: - <, >, :, ", /, \, |, ?, and *. % is also escaped since it is used as the escape - character. Escaping is performed in a consistent way so that no collisions occur and - unescapeFileName(String) can be used to retrieve the original file name.

    +

    For simplicity, this only handles common characters known to be illegal on FAT32: <, + >, :, ", /, \, |, ?, and *. % is also escaped since it is used as the escape character. + Escaping is performed in a consistent way so that no collisions occur and unescapeFileName(String) can be used to retrieve the original file name.

    Parameters:
    fileName - File name to be escaped.
    @@ -3050,8 +3056,8 @@

    getDataUriForString

  • sneakyThrow

    public static void sneakyThrow​(Throwable t)
    -
    A hacky method that always throws t even if t is a checked exception, - and is not declared to be thrown.
    +
    A hacky method that always throws t even if t is a checked exception, and is + not declared to be thrown.
  • @@ -3344,7 +3350,7 @@

    moveItems

    -
      +
      • tableExists

        public static boolean tableExists​(SQLiteDatabase database,
        @@ -3352,6 +3358,25 @@ 

        tableExists

        Returns whether the table exists in the database.
      + + + +
        +
      • +

        getErrorCodeFromPlatformDiagnosticsInfo

        +
        public static int getErrorCodeFromPlatformDiagnosticsInfo​(@Nullable
        +                                                          String diagnosticsInfo)
        +
        Attempts to parse an error code from a diagnostic string found in framework media exceptions. + +

        For example: android.media.MediaCodec.error_1 or android.media.MediaDrm.error_neg_2.

        +
        +
        Parameters:
        +
        diagnosticsInfo - A string from which to parse the error code.
        +
        Returns:
        +
        The parser error code, or 0 if an error code could not be parsed.
        +
        +
      • +
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/util/package-summary.html b/docs/doc/reference/com/google/android/exoplayer2/util/package-summary.html index e096c9fe09c..7d38b8e92e7 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/util/package-summary.html +++ b/docs/doc/reference/com/google/android/exoplayer2/util/package-summary.html @@ -195,163 +195,175 @@

    Package com.google.android.exoplayer2.uti +BundleableUtils + +
    Utilities for Bundleable.
    + + + BundleUtil
    Utilities for Bundle.
    - + CodecSpecificDataUtil
    Provides utilities for handling various types of codec-specific data.
    - + ColorParser
    Parser for color expressions found in styling formats, e.g.
    - + ConditionVariable
    An interruptible condition variable.
    - + CopyOnWriteMultiset<E>
    An unordered collection of elements that allows duplicates, but also allows access to a set of unique elements.
    - + DebugTextViewHelper
    A helper class for periodically updating a TextView with debug information obtained from a SimpleExoPlayer.
    - + EGLSurfaceTexture
    Generates a SurfaceTexture using EGL/GLES functions.
    - + EventLogger
    Logs events from Player and other core components using Log.
    - -ExoFlags - -
    A set of integer flags.
    - - -ExoFlags.Builder +FileTypes -
    A builder for ExoFlags instances.
    +
    Defines common file type constants and helper methods.
    -FileTypes +FlacConstants -
    Defines common file type constants and helper methods.
    +
    Defines constants used by the FLAC extractor.
    -FlacConstants +FlagSet -
    Defines constants used by the FLAC extractor.
    +
    A set of integer flags.
    +FlagSet.Builder + +
    A builder for FlagSet instances.
    + + + GlUtil
    GL utilities.
    - + GlUtil.Attribute
    GL attribute, which can be attached to a buffer with GlUtil.Attribute.setBuffer(float[], int).
    - + GlUtil.Uniform
    GL uniform, which can be attached to a sampler using GlUtil.Uniform.setSamplerTexId(int, int).
    - + IntArrayQueue
    Array-based unbounded queue for int primitives with amortized O(1) add and remove.
    - + LibraryLoader
    Configurable loader for native libraries.
    - + ListenerSet<T>
    A set of listeners.
    - + Log
    Wrapper around Log which allows to set the log level.
    - + LongArray
    An append-only, auto-growing long[].
    - + MediaFormatUtil
    Helper class containing utility methods for managing MediaFormat instances.
    - + MimeTypes
    Defines common MIME types and helper methods.
    - + NalUnitUtil
    Utility methods for handling H.264/AVC and H.265/HEVC NAL units.
    - + NalUnitUtil.PpsData
    Holds data parsed from a picture parameter set NAL unit.
    - + NalUnitUtil.SpsData
    Holds data parsed from a sequence parameter set NAL unit.
    - + NetworkTypeObserver
    Observer for network type changes.
    + +NetworkTypeObserver.Config + +
    Configuration for NetworkTypeObserver.
    + + NotificationUtil @@ -436,7 +448,7 @@

    Package com.google.android.exoplayer2.uti TimestampAdjuster -
    Offsets timestamps according to an initial sample timestamp offset.
    +
    Adjusts and offsets sample timestamps.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/util/package-tree.html b/docs/doc/reference/com/google/android/exoplayer2/util/package-tree.html index 6aad6f1e74f..3c6628e03aa 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/util/package-tree.html +++ b/docs/doc/reference/com/google/android/exoplayer2/util/package-tree.html @@ -105,6 +105,7 @@

    Class Hierarchy

    @@ -28521,6 +29571,10 @@

    R

    S

    +
    sameAs(MediaMetadataCompat, MediaMetadataCompat) - Method in interface com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.MediaMetadataProvider
    +
    +
    Returns whether the old and the new metadata are considered the same.
    +
    sample(long, int, byte[]) - Static method in class com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem
    Creates an item representing a sample with the provided timestamp, flags and data.
    @@ -28916,6 +29970,22 @@

    S

    Schedules a seek action and waits until playback resumes after the seek.
    +
    seekBack() - Method in class com.google.android.exoplayer2.BasePlayer
    +
     
    +
    seekBack() - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    +
    seekBack() - Method in interface com.google.android.exoplayer2.Player
    +
    +
    Seeks back in the current window by Player.getSeekBackIncrement() milliseconds.
    +
    +
    seekForward() - Method in class com.google.android.exoplayer2.BasePlayer
    +
     
    +
    seekForward() - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    +
    seekForward() - Method in interface com.google.android.exoplayer2.Player
    +
    +
    Seeks forward in the current window by Player.getSeekForwardIncrement() milliseconds.
    +
    seekMap - Variable in class com.google.android.exoplayer2.extractor.BinarySearchSeeker
     
    seekMap - Variable in class com.google.android.exoplayer2.testutil.FakeExtractorOutput
    @@ -28976,6 +30046,8 @@

    S

    seekTo(int, long) - Method in class com.google.android.exoplayer2.ext.cast.CastPlayer
     
    +
    seekTo(int, long) - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    seekTo(int, long) - Method in interface com.google.android.exoplayer2.Player
    Seeks to a position specified in milliseconds in the specified window.
    @@ -28990,6 +30062,8 @@

    S

     
    seekTo(long) - Method in class com.google.android.exoplayer2.ext.media2.SessionPlayerConnector
     
    +
    seekTo(long) - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    seekTo(long) - Method in interface com.google.android.exoplayer2.Player
    Seeks to a position specified in milliseconds in the current window.
    @@ -29000,20 +30074,58 @@

    S

    seekToDefaultPosition() - Method in class com.google.android.exoplayer2.BasePlayer
     
    +
    seekToDefaultPosition() - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    seekToDefaultPosition() - Method in interface com.google.android.exoplayer2.Player
    Seeks to the default position associated with the current window.
    seekToDefaultPosition(int) - Method in class com.google.android.exoplayer2.BasePlayer
     
    +
    seekToDefaultPosition(int) - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    seekToDefaultPosition(int) - Method in interface com.google.android.exoplayer2.Player
    Seeks to the default position associated with the specified window.
    +
    seekToNext() - Method in class com.google.android.exoplayer2.BasePlayer
    +
     
    +
    seekToNext() - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    +
    seekToNext() - Method in interface com.google.android.exoplayer2.Player
    +
    +
    Seeks to a later position in the current or next window (if available).
    +
    +
    seekToNextWindow() - Method in class com.google.android.exoplayer2.BasePlayer
    +
     
    +
    seekToNextWindow() - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    +
    seekToNextWindow() - Method in interface com.google.android.exoplayer2.Player
    +
    +
    Seeks to the default position of the next window, which may depend on the current repeat mode + and whether shuffle mode is enabled.
    +
    seekToPosition(long) - Method in class com.google.android.exoplayer2.source.mediaparser.InputReaderAdapterV30
     
    seekToPosition(ExtractorInput, long, PositionHolder) - Method in class com.google.android.exoplayer2.extractor.BinarySearchSeeker
     
    +
    seekToPrevious() - Method in class com.google.android.exoplayer2.BasePlayer
    +
     
    +
    seekToPrevious() - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    +
    seekToPrevious() - Method in interface com.google.android.exoplayer2.Player
    +
    +
    Seeks to an earlier position in the current or previous window (if available).
    +
    +
    seekToPreviousWindow() - Method in class com.google.android.exoplayer2.BasePlayer
    +
     
    +
    seekToPreviousWindow() - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    +
    seekToPreviousWindow() - Method in interface com.google.android.exoplayer2.Player
    +
    +
    Seeks to the default position of the previous window, which may depend on the current repeat + mode and whether shuffle mode is enabled.
    +
    seekToTimeUs(Extractor, SeekMap, long, DataSource, FakeTrackOutput, Uri) - Static method in class com.google.android.exoplayer2.testutil.TestUtil
    Seeks to the given seek time of the stream from the given input, and keeps reading from the @@ -29129,6 +30241,12 @@

    S

    +
    selectBaseUrl(List<BaseUrl>) - Method in class com.google.android.exoplayer2.source.dash.BaseUrlExclusionList
    +
    +
    Selects the base URL to use from the given list.
    +
    +
    selectedBaseUrl - Variable in class com.google.android.exoplayer2.source.dash.DefaultDashChunkSource.RepresentationHolder
    +
     
    selectEmbeddedTrack(long, int) - Method in class com.google.android.exoplayer2.source.chunk.ChunkSampleStream
    Selects the embedded track, returning a new ChunkSampleStream.EmbeddedSampleStream from which the track's @@ -29355,6 +30473,18 @@

    S

    Creates a new instance.
    +
    ServerSideInsertedAdsMediaSource - Class in com.google.android.exoplayer2.source.ads
    +
    +
    A MediaSource for server-side inserted ad breaks.
    +
    +
    ServerSideInsertedAdsMediaSource(MediaSource) - Constructor for class com.google.android.exoplayer2.source.ads.ServerSideInsertedAdsMediaSource
    +
    +
    Creates the media source.
    +
    +
    ServerSideInsertedAdsUtil - Class in com.google.android.exoplayer2.source.ads
    +
    +
    A static utility class with methods to work with server-side inserted ads.
    +
    serviceDescription - Variable in class com.google.android.exoplayer2.source.dash.manifest.DashManifest
    The ServiceDescriptionElement, or null if not present.
    @@ -29367,6 +30497,10 @@

    S

    Creates a service description element.
    +
    serviceLocation - Variable in class com.google.android.exoplayer2.source.dash.manifest.BaseUrl
    +
    +
    The service location.
    +
    SessionAvailabilityListener - Interface in com.google.android.exoplayer2.ext.cast
    Listener of changes in the cast session availability.
    @@ -29440,11 +30574,11 @@

    S

    SessionPlayerConnector(Player) - Constructor for class com.google.android.exoplayer2.ext.media2.SessionPlayerConnector
    Creates an instance using DefaultMediaItemConverter to convert between ExoPlayer and - media2 MediaItems and DefaultControlDispatcher to dispatch player commands.
    + media2 MediaItems.
    SessionPlayerConnector(Player, MediaItemConverter) - Constructor for class com.google.android.exoplayer2.ext.media2.SessionPlayerConnector
    -
    Creates an instance using the provided ControlDispatcher to dispatch player commands.
    +
    Creates an instance.
    set(int, int[], int[], byte[], byte[], int, int, int) - Method in class com.google.android.exoplayer2.decoder.CryptoInfo
     
    @@ -29511,6 +30645,10 @@

    S

    Sets the MIME types to prioritize for linear ad media.
    +
    setAdPlaybackState(AdPlaybackState) - Method in class com.google.android.exoplayer2.source.ads.ServerSideInsertedAdsMediaSource
    +
    +
    Sets the AdPlaybackState published by this source.
    +
    setAdPreloadTimeoutMs(long) - Method in class com.google.android.exoplayer2.ext.ima.ImaAdsLoader.Builder
    Sets the duration in milliseconds for which the player must buffer while preloading an ad @@ -29659,7 +30797,13 @@

    S

    setArtworkData(byte[]) - Method in class com.google.android.exoplayer2.MediaMetadata.Builder
    -
    Sets the artwork data as a compressed byte array.
    + +
    +
    setArtworkData(byte[], Integer) - Method in class com.google.android.exoplayer2.MediaMetadata.Builder
    +
    +
    Sets the artwork data as a compressed byte array with an associated artworkDataType.
    setArtworkUri(Uri) - Method in class com.google.android.exoplayer2.MediaMetadata.Builder
    @@ -29778,8 +30922,8 @@

    S

     
    setBottomPaddingFraction(float) - Method in class com.google.android.exoplayer2.ui.SubtitleView
    -
    Sets the bottom padding fraction to apply when Cue.line is Cue.DIMEN_UNSET, - as a fraction of the view's remaining height after its top and bottom padding have been +
    Sets the bottom padding fraction to apply when Cue.line is Cue.DIMEN_UNSET, as + a fraction of the view's remaining height after its top and bottom padding have been subtracted.
    setBuffer(float[], int) - Method in class com.google.android.exoplayer2.util.GlUtil.Attribute
    @@ -29929,6 +31073,14 @@

    S

    Sets the slots to use for companion ads, if they are present in the loaded ad.
    +
    setCompilation(CharSequence) - Method in class com.google.android.exoplayer2.MediaMetadata.Builder
    +
    +
    Sets the compilation.
    +
    +
    setComposer(CharSequence) - Method in class com.google.android.exoplayer2.MediaMetadata.Builder
    +
    +
    Sets the composer.
    +
    setCompositeSequenceableLoaderFactory(CompositeSequenceableLoaderFactory) - Method in class com.google.android.exoplayer2.source.dash.DashMediaSource.Factory
    Sets the factory to create composite SequenceableLoaders for when this media source @@ -29944,6 +31096,10 @@

    S

    Sets the factory to create composite SequenceableLoaders for when this media source loads data from multiple streams (video, audio etc.).
    +
    setConductor(CharSequence) - Method in class com.google.android.exoplayer2.MediaMetadata.Builder
    +
    +
    Sets the conductor.
    +
    setConnectionTimeoutMs(int) - Method in class com.google.android.exoplayer2.ext.cronet.CronetDataSource.Factory
    Sets the connect timeout, in milliseconds.
    @@ -30014,35 +31170,69 @@

    S

    setControlDispatcher(ControlDispatcher) - Method in class com.google.android.exoplayer2.ext.leanback.LeanbackPlayerAdapter
    - +
    Deprecated. +
    Use a ForwardingPlayer and pass it to the constructor instead. You can also + customize some operations when configuring the player (for example by using + SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)).
    +
    setControlDispatcher(ControlDispatcher) - Method in class com.google.android.exoplayer2.ext.media2.SessionPlayerConnector
    - +
    Deprecated. +
    Use a ForwardingPlayer and pass it to the constructor instead. You can also + customize some operations when configuring the player (for example by using + SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)).
    +
    setControlDispatcher(ControlDispatcher) - Method in class com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
    - +
    Deprecated. +
    Use a ForwardingPlayer and pass it to MediaSessionConnector.setPlayer(Player) instead. + You can also customize some operations when configuring the player (for example by using + SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)).
    +
    setControlDispatcher(ControlDispatcher) - Method in class com.google.android.exoplayer2.ui.PlayerControlView
    - +
    Deprecated. +
    Use a ForwardingPlayer and pass it to PlayerControlView.setPlayer(Player) instead. + You can also customize some operations when configuring the player (for example by using + SimpleExoPlayer.Builder.setSeekBackIncrementMs(long)).
    +
    setControlDispatcher(ControlDispatcher) - Method in class com.google.android.exoplayer2.ui.PlayerNotificationManager
    - +
    Deprecated. +
    Use a ForwardingPlayer and pass it to PlayerNotificationManager.setPlayer(Player) instead. + You can also customize some operations when configuring the player (for example by using + SimpleExoPlayer.Builder.setSeekBackIncrementMs(long)), or configure whether the + rewind and fast forward actions should be used with {PlayerNotificationManager.setUseRewindAction(boolean)} + and PlayerNotificationManager.setUseFastForwardAction(boolean).
    +
    setControlDispatcher(ControlDispatcher) - Method in class com.google.android.exoplayer2.ui.PlayerView
    - +
    Deprecated. +
    Use a ForwardingPlayer and pass it to PlayerView.setPlayer(Player) instead. + You can also customize some operations when configuring the player (for example by using + SimpleExoPlayer.Builder.setSeekBackIncrementMs(long)).
    +
    setControlDispatcher(ControlDispatcher) - Method in class com.google.android.exoplayer2.ui.StyledPlayerControlView
    - +
    Deprecated. +
    Use a ForwardingPlayer and pass it to StyledPlayerControlView.setPlayer(Player) instead. + You can also customize some operations when configuring the player (for example by using + SimpleExoPlayer.Builder.setSeekBackIncrementMs(long)).
    +
    setControlDispatcher(ControlDispatcher) - Method in class com.google.android.exoplayer2.ui.StyledPlayerView
    - +
    Deprecated. +
    Use a ForwardingPlayer and pass it to StyledPlayerView.setPlayer(Player) instead. + You can also customize some operations when configuring the player (for example by using + SimpleExoPlayer.Builder.setSeekBackIncrementMs(long)).
    +
    setControllerAutoShow(boolean) - Method in class com.google.android.exoplayer2.ui.PlayerView
    @@ -30253,6 +31443,8 @@

    S

    This method is not supported and does nothing.
    +
    setDeviceMuted(boolean) - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    setDeviceMuted(boolean) - Method in interface com.google.android.exoplayer2.Player
    Sets the mute state of the device.
    @@ -30269,6 +31461,8 @@

    S

    This method is not supported and does nothing.
    +
    setDeviceVolume(int) - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    setDeviceVolume(int) - Method in interface com.google.android.exoplayer2.Player
    Sets the volume of the device.
    @@ -30278,11 +31472,13 @@

    S

    setDeviceVolume(int) - Method in class com.google.android.exoplayer2.testutil.StubExoPlayer
     
    setDisabledTextTrackSelectionFlags(int) - Method in class com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder
    -
     
    -
    setDisabledTextTrackSelectionFlags(int) - Method in class com.google.android.exoplayer2.trackselection.TrackSelectionParameters.Builder
    Sets a bitmask of selection flags that are disabled for text track selections.
    +
    setDiscNumber(Integer) - Method in class com.google.android.exoplayer2.MediaMetadata.Builder
    +
    +
    Sets the disc number.
    +
    setDisconnectedCallback(SessionCallbackBuilder.DisconnectedCallback) - Method in class com.google.android.exoplayer2.ext.media2.SessionCallbackBuilder
    Sets the SessionCallbackBuilder.DisconnectedCallback to handle cleaning up controller.
    @@ -30291,6 +31487,11 @@

    S

    Sets a discontinuity position to be returned from the next call to FakeMediaPeriod.readDiscontinuity().
    +
    setDispatchUnsupportedActionsEnabled(boolean) - Method in class com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
    +
    +
    Sets whether actions that are not advertised to the MediaSessionCompat will be + dispatched either way.
    +
    setDisplayTitle(CharSequence) - Method in class com.google.android.exoplayer2.MediaMetadata.Builder
    Sets the display title.
    @@ -30500,19 +31701,19 @@

    S

    -
    setErrorMessageProvider(ErrorMessageProvider<? super ExoPlaybackException>) - Method in class com.google.android.exoplayer2.ext.leanback.LeanbackPlayerAdapter
    +
    setErrorMessageProvider(ErrorMessageProvider<? super PlaybackException>) - Method in class com.google.android.exoplayer2.ext.leanback.LeanbackPlayerAdapter
    Sets the optional ErrorMessageProvider.
    -
    setErrorMessageProvider(ErrorMessageProvider<? super ExoPlaybackException>) - Method in class com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
    +
    setErrorMessageProvider(ErrorMessageProvider<? super PlaybackException>) - Method in class com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
    Sets the optional ErrorMessageProvider.
    -
    setErrorMessageProvider(ErrorMessageProvider<? super ExoPlaybackException>) - Method in class com.google.android.exoplayer2.ui.PlayerView
    +
    setErrorMessageProvider(ErrorMessageProvider<? super PlaybackException>) - Method in class com.google.android.exoplayer2.ui.PlayerView
    Sets the optional ErrorMessageProvider.
    -
    setErrorMessageProvider(ErrorMessageProvider<? super ExoPlaybackException>) - Method in class com.google.android.exoplayer2.ui.StyledPlayerView
    +
    setErrorMessageProvider(ErrorMessageProvider<? super PlaybackException>) - Method in class com.google.android.exoplayer2.ui.StyledPlayerView
    Sets the optional ErrorMessageProvider.
    @@ -30597,7 +31798,10 @@

    S

     
    setFallbackFactory(HttpDataSource.Factory) - Method in class com.google.android.exoplayer2.ext.cronet.CronetDataSource.Factory
    -
    Sets the fallback HttpDataSource.Factory that is used as a fallback if the CronetEngineWrapper fails to provide a CronetEngine.
    +
    Deprecated. +
    Do not use CronetDataSource or its factory in cases where a suitable + CronetEngine is not available. Use the fallback factory directly in such cases.
    +
    setFallbackMaxPlaybackSpeed(float) - Method in class com.google.android.exoplayer2.DefaultLivePlaybackSpeedControl.Builder
    @@ -30622,37 +31826,6 @@

    S

    Sets the fast forward increment in milliseconds.
    -
    setFastForwardIncrementMs(int) - Method in class com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
    -
    - -
    -
    setFastForwardIncrementMs(int) - Method in class com.google.android.exoplayer2.ui.PlayerControlView
    -
    - -
    -
    setFastForwardIncrementMs(int) - Method in class com.google.android.exoplayer2.ui.PlayerView
    -
    - -
    -
    setFastForwardIncrementMs(long) - Method in class com.google.android.exoplayer2.DefaultControlDispatcher
    -
    -
    Deprecated. -
    Create a new instance instead and pass the new instance to the UI component. This - makes sure the UI gets updated and is in sync with the new values.
    -
    -
    -
    setFastForwardIncrementMs(long) - Method in class com.google.android.exoplayer2.ui.PlayerNotificationManager
    -
    - -
    setFinalStreamEndPositionUs(long) - Method in class com.google.android.exoplayer2.text.TextRenderer
    Sets the position at which to stop rendering the current stream.
    @@ -30705,14 +31878,18 @@

    S

     
    setFontSize(float) - Method in class com.google.android.exoplayer2.text.webvtt.WebvttCssStyle
     
    -
    setFontSizeUnit(short) - Method in class com.google.android.exoplayer2.text.webvtt.WebvttCssStyle
    +
    setFontSizeUnit(int) - Method in class com.google.android.exoplayer2.text.webvtt.WebvttCssStyle
     
    setForceHighestSupportedBitrate(boolean) - Method in class com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder
    +
     
    +
    setForceHighestSupportedBitrate(boolean) - Method in class com.google.android.exoplayer2.trackselection.TrackSelectionParameters.Builder
    Sets whether to force selection of the highest bitrate audio and video tracks that comply with all other constraints.
    setForceLowestBitrate(boolean) - Method in class com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder
    +
     
    +
    setForceLowestBitrate(boolean) - Method in class com.google.android.exoplayer2.trackselection.TrackSelectionParameters.Builder
    Sets whether to force selection of the single lowest bitrate audio and video tracks that comply with all other constraints.
    @@ -30764,6 +31941,10 @@

    S

    Populates the holder with data from an MP3 Xing header, if valid and non-zero.
    +
    setGenre(CharSequence) - Method in class com.google.android.exoplayer2.MediaMetadata.Builder
    +
    +
    Sets the genre.
    +
    setGroup(String) - Method in class com.google.android.exoplayer2.ui.PlayerNotificationManager.Builder
    The key of the group the media notification should belong to.
    @@ -30883,6 +32064,16 @@

    S

    Sets whether the currently displayed video frame or media artwork is kept visible when the player is reset.
    +
    setKeepPostFor302Redirects(boolean) - Method in class com.google.android.exoplayer2.ext.cronet.CronetDataSource.Factory
    +
    +
    Sets whether we should keep the POST method and body when we have HTTP 302 redirects for a + POST request.
    +
    +
    setKeepPostFor302Redirects(boolean) - Method in class com.google.android.exoplayer2.upstream.DefaultHttpDataSource.Factory
    +
    +
    Sets whether we should keep the POST method and body when we have HTTP 302 redirects for a + POST request.
    +
    setKey(String) - Method in class com.google.android.exoplayer2.upstream.DataSpec.Builder
    Sets the DataSpec.key.
    @@ -31158,10 +32349,14 @@

    S

    Sets flags for MatroskaExtractor instances created by the factory.
    setMaxAudioBitrate(int) - Method in class com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder
    +
     
    +
    setMaxAudioBitrate(int) - Method in class com.google.android.exoplayer2.trackselection.TrackSelectionParameters.Builder
    Sets the maximum allowed audio bitrate.
    setMaxAudioChannelCount(int) - Method in class com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder
    +
     
    +
    setMaxAudioChannelCount(int) - Method in class com.google.android.exoplayer2.trackselection.TrackSelectionParameters.Builder
    Sets the maximum allowed audio channel count.
    @@ -31187,20 +32382,28 @@

    S

    Sets the maximum number of parallel downloads.
    setMaxVideoBitrate(int) - Method in class com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder
    +
     
    +
    setMaxVideoBitrate(int) - Method in class com.google.android.exoplayer2.trackselection.TrackSelectionParameters.Builder
    Sets the maximum allowed video bitrate.
    setMaxVideoFrameRate(int) - Method in class com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder
    +
     
    +
    setMaxVideoFrameRate(int) - Method in class com.google.android.exoplayer2.trackselection.TrackSelectionParameters.Builder
    Sets the maximum allowed video frame rate.
    setMaxVideoSize(int, int) - Method in class com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder
    +
     
    +
    setMaxVideoSize(int, int) - Method in class com.google.android.exoplayer2.trackselection.TrackSelectionParameters.Builder
    Sets the maximum allowed video width and height.
    setMaxVideoSizeSd() - Method in class com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder
    +
     
    +
    setMaxVideoSizeSd() - Method in class com.google.android.exoplayer2.trackselection.TrackSelectionParameters.Builder
    - +
    setMediaButtonEventHandler(MediaSessionConnector.MediaButtonEventHandler) - Method in class com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
    @@ -31210,6 +32413,10 @@

    S

    Sets a MediaCodecSelector for use by MediaCodec based renderers.
    +
    setMediaDescriptionAdapter(PlayerNotificationManager.MediaDescriptionAdapter) - Method in class com.google.android.exoplayer2.ui.PlayerNotificationManager.Builder
    +
    +
    The PlayerNotificationManager.MediaDescriptionAdapter to be queried for the notification contents.
    +
    setMediaId(String) - Method in class com.google.android.exoplayer2.MediaItem.Builder
    Sets the optional media ID which identifies the media item.
    @@ -31217,6 +32424,8 @@

    S

    setMediaItem(MediaItem) - Method in class com.google.android.exoplayer2.ext.media2.SessionPlayerConnector
    setMediaItem(MediaItem) - Method in class com.google.android.exoplayer2.BasePlayer
     
    +
    setMediaItem(MediaItem) - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    setMediaItem(MediaItem) - Method in interface com.google.android.exoplayer2.Player
    Clears the playlist, adds the specified MediaItem and resets the position to the @@ -31224,12 +32433,16 @@

    S

    setMediaItem(MediaItem, boolean) - Method in class com.google.android.exoplayer2.BasePlayer
     
    +
    setMediaItem(MediaItem, boolean) - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    setMediaItem(MediaItem, boolean) - Method in interface com.google.android.exoplayer2.Player
    Clears the playlist and adds the specified MediaItem.
    setMediaItem(MediaItem, long) - Method in class com.google.android.exoplayer2.BasePlayer
     
    +
    setMediaItem(MediaItem, long) - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    setMediaItem(MediaItem, long) - Method in interface com.google.android.exoplayer2.Player
    Clears the playlist and adds the specified MediaItem.
    @@ -31240,6 +32453,8 @@

    S

    setMediaItems(List<MediaItem>) - Method in class com.google.android.exoplayer2.BasePlayer
     
    +
    setMediaItems(List<MediaItem>) - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    setMediaItems(List<MediaItem>) - Method in interface com.google.android.exoplayer2.Player
    Clears the playlist, adds the specified MediaItems and resets the position to @@ -31247,6 +32462,8 @@

    S

    setMediaItems(List<MediaItem>, boolean) - Method in class com.google.android.exoplayer2.ext.cast.CastPlayer
     
    +
    setMediaItems(List<MediaItem>, boolean) - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    setMediaItems(List<MediaItem>, boolean) - Method in interface com.google.android.exoplayer2.Player
    Clears the playlist and adds the specified MediaItems.
    @@ -31257,6 +32474,8 @@

    S

     
    setMediaItems(List<MediaItem>, int, long) - Method in class com.google.android.exoplayer2.ext.cast.CastPlayer
     
    +
    setMediaItems(List<MediaItem>, int, long) - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    setMediaItems(List<MediaItem>, int, long) - Method in interface com.google.android.exoplayer2.Player
    Clears the playlist and adds the specified MediaItems.
    @@ -31376,6 +32595,11 @@

    S

    +
    setMetadataDeduplicationEnabled(boolean) - Method in class com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
    +
    +
    Sets whether MediaSessionConnector.MediaMetadataProvider.sameAs(MediaMetadataCompat, MediaMetadataCompat) + should be consulted before calling MediaSessionCompat.setMetadata(MediaMetadataCompat).
    +
    setMetadataType(int) - Method in class com.google.android.exoplayer2.source.hls.HlsMediaSource.Factory
    Sets the type of metadata to extract from the HLS source (defaults to HlsMediaSource.METADATA_TYPE_ID3).
    @@ -31404,14 +32628,20 @@

    S

    Sets the minimum interval between playback speed changes, in milliseconds.
    setMinVideoBitrate(int) - Method in class com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder
    +
     
    +
    setMinVideoBitrate(int) - Method in class com.google.android.exoplayer2.trackselection.TrackSelectionParameters.Builder
    Sets the minimum allowed video bitrate.
    setMinVideoFrameRate(int) - Method in class com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder
    +
     
    +
    setMinVideoFrameRate(int) - Method in class com.google.android.exoplayer2.trackselection.TrackSelectionParameters.Builder
    Sets the minimum allowed video frame rate.
    setMinVideoSize(int, int) - Method in class com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder
    +
     
    +
    setMinVideoSize(int, int) - Method in class com.google.android.exoplayer2.trackselection.TrackSelectionParameters.Builder
    Sets the minimum allowed video width and height.
    @@ -31669,6 +32899,8 @@

    S

     
    setPlaybackParameters(PlaybackParameters) - Method in class com.google.android.exoplayer2.ext.cast.CastPlayer
     
    +
    setPlaybackParameters(PlaybackParameters) - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    setPlaybackParameters(PlaybackParameters) - Method in interface com.google.android.exoplayer2.Player
    Attempts to set the playback parameters.
    @@ -31695,60 +32927,12 @@

    S

    -
    setPlaybackPreparer(PlaybackPreparer) - Method in class com.google.android.exoplayer2.ext.leanback.LeanbackPlayerAdapter
    -
    -
    Deprecated. -
    Use LeanbackPlayerAdapter.setControlDispatcher(ControlDispatcher) instead. The adapter calls - ControlDispatcher.dispatchPrepare(Player) instead of PlaybackPreparer.preparePlayback(). The DefaultControlDispatcher that the adapter - uses by default, calls Player.prepare(). If you wish to customize this behaviour, - you can provide a custom implementation of ControlDispatcher.dispatchPrepare(Player).
    -
    -
    -
    setPlaybackPreparer(PlaybackPreparer) - Method in class com.google.android.exoplayer2.ui.PlayerControlView
    -
    -
    Deprecated. -
    Use PlayerControlView.setControlDispatcher(ControlDispatcher) instead. The view calls ControlDispatcher.dispatchPrepare(Player) instead of PlaybackPreparer.preparePlayback(). The DefaultControlDispatcher that the view - uses by default, calls Player.prepare(). If you wish to customize this behaviour, - you can provide a custom implementation of ControlDispatcher.dispatchPrepare(Player).
    -
    -
    -
    setPlaybackPreparer(PlaybackPreparer) - Method in class com.google.android.exoplayer2.ui.PlayerNotificationManager
    -
    -
    Deprecated. -
    Use PlayerNotificationManager.setControlDispatcher(ControlDispatcher) instead. The manager calls - ControlDispatcher.dispatchPrepare(Player) instead of PlaybackPreparer.preparePlayback(). The DefaultControlDispatcher that this manager - uses by default, calls Player.prepare(). If you wish to intercept or customize this - behaviour, you can provide a custom implementation of ControlDispatcher.dispatchPrepare(Player) and pass it to PlayerNotificationManager.setControlDispatcher(ControlDispatcher).
    -
    -
    -
    setPlaybackPreparer(PlaybackPreparer) - Method in class com.google.android.exoplayer2.ui.PlayerView
    -
    -
    Deprecated. -
    Use PlayerView.setControlDispatcher(ControlDispatcher) instead. The view calls ControlDispatcher.dispatchPrepare(Player) instead of PlaybackPreparer.preparePlayback(). The DefaultControlDispatcher that the view - uses by default, calls Player.prepare(). If you wish to customize this behaviour, - you can provide a custom implementation of ControlDispatcher.dispatchPrepare(Player).
    -
    -
    -
    setPlaybackPreparer(PlaybackPreparer) - Method in class com.google.android.exoplayer2.ui.StyledPlayerControlView
    -
    -
    Deprecated. -
    Use StyledPlayerControlView.setControlDispatcher(ControlDispatcher) instead. The view calls ControlDispatcher.dispatchPrepare(Player) instead of PlaybackPreparer.preparePlayback(). The DefaultControlDispatcher that the view - uses by default, calls Player.prepare(). If you wish to customize this behaviour, - you can provide a custom implementation of ControlDispatcher.dispatchPrepare(Player).
    -
    -
    -
    setPlaybackPreparer(PlaybackPreparer) - Method in class com.google.android.exoplayer2.ui.StyledPlayerView
    -
    -
    Deprecated. -
    Use StyledPlayerView.setControlDispatcher(ControlDispatcher) instead. The view calls ControlDispatcher.dispatchPrepare(Player) instead of PlaybackPreparer.preparePlayback(). The DefaultControlDispatcher that the view - uses by default, calls Player.prepare(). If you wish to customize this behaviour, - you can provide a custom implementation of ControlDispatcher.dispatchPrepare(Player).
    -
    -
    setPlaybackSpeed(float) - Method in class com.google.android.exoplayer2.BasePlayer
     
    setPlaybackSpeed(float) - Method in class com.google.android.exoplayer2.ext.media2.SessionPlayerConnector
     
    +
    setPlaybackSpeed(float) - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    setPlaybackSpeed(float) - Method in interface com.google.android.exoplayer2.Player
    Changes the rate at which playback occurs.
    @@ -31813,6 +32997,20 @@

    S

    Sets an Player.Listener to be registered to listen to player events.
    setPlaylist(List<MediaItem>, MediaMetadata) - Method in class com.google.android.exoplayer2.ext.media2.SessionPlayerConnector
    +
    setPlaylistMetadata(MediaMetadata) - Method in class com.google.android.exoplayer2.ext.cast.CastPlayer
    +
    +
    This method is not supported and does nothing.
    +
    +
    setPlaylistMetadata(MediaMetadata) - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    +
    setPlaylistMetadata(MediaMetadata) - Method in interface com.google.android.exoplayer2.Player
    +
    +
    Sets the playlist MediaMetadata.
    +
    +
    setPlaylistMetadata(MediaMetadata) - Method in class com.google.android.exoplayer2.SimpleExoPlayer
    +
     
    +
    setPlaylistMetadata(MediaMetadata) - Method in class com.google.android.exoplayer2.testutil.StubExoPlayer
    +
     
    setPlaylistParserFactory(HlsPlaylistParserFactory) - Method in class com.google.android.exoplayer2.source.hls.HlsMediaSource.Factory
    Sets the factory from which playlist parsers will be obtained.
    @@ -31823,6 +33021,8 @@

    S

    setPlayWhenReady(boolean) - Method in class com.google.android.exoplayer2.ext.cast.CastPlayer
     
    +
    setPlayWhenReady(boolean) - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    setPlayWhenReady(boolean) - Method in interface com.google.android.exoplayer2.Player
    Sets whether playback should proceed when Player.getPlaybackState() == Player.STATE_READY.
    @@ -31899,10 +33099,14 @@

    S

    Sets the preferred languages for audio and forced text tracks.
    setPreferredAudioMimeType(String) - Method in class com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder
    +
     
    +
    setPreferredAudioMimeType(String) - Method in class com.google.android.exoplayer2.trackselection.TrackSelectionParameters.Builder
    Sets the preferred sample MIME type for audio tracks.
    setPreferredAudioMimeTypes(String...) - Method in class com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder
    +
     
    +
    setPreferredAudioMimeTypes(String...) - Method in class com.google.android.exoplayer2.trackselection.TrackSelectionParameters.Builder
    Sets the preferred sample MIME types for audio tracks.
    @@ -31938,10 +33142,14 @@

    S

    Sets the preferred C.RoleFlags for text tracks.
    setPreferredVideoMimeType(String) - Method in class com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder
    +
     
    +
    setPreferredVideoMimeType(String) - Method in class com.google.android.exoplayer2.trackselection.TrackSelectionParameters.Builder
    Sets the preferred sample MIME type for video tracks.
    setPreferredVideoMimeTypes(String...) - Method in class com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder
    +
     
    +
    setPreferredVideoMimeTypes(String...) - Method in class com.google.android.exoplayer2.trackselection.TrackSelectionParameters.Builder
    Sets the preferred sample MIME types for video tracks.
    @@ -32050,11 +33258,31 @@

    S

    Sets the read timeout, in milliseconds.
    +
    setRecordingDay(Integer) - Method in class com.google.android.exoplayer2.MediaMetadata.Builder
    +
    +
    Sets the day of the recording date.
    +
    +
    setRecordingMonth(Integer) - Method in class com.google.android.exoplayer2.MediaMetadata.Builder
    +
    +
    Sets the month of the recording date.
    +
    +
    setRecordingYear(Integer) - Method in class com.google.android.exoplayer2.MediaMetadata.Builder
    +
    +
    Sets the year of the recording date.
    +
    setRedirectedUri(ContentMetadataMutations, Uri) - Static method in class com.google.android.exoplayer2.upstream.cache.ContentMetadataMutations
    Adds a mutation to set the ContentMetadata.KEY_REDIRECTED_URI value, or to remove any existing entry if null is passed.
    +
    setReleaseDay(Integer) - Method in class com.google.android.exoplayer2.MediaMetadata.Builder
    +
    +
    Sets the day of the release date.
    +
    +
    setReleaseMonth(Integer) - Method in class com.google.android.exoplayer2.MediaMetadata.Builder
    +
    +
    Sets the month of the release date.
    +
    setReleaseTimeoutMs(long) - Method in class com.google.android.exoplayer2.ExoPlayer.Builder
    Deprecated.
    @@ -32064,6 +33292,10 @@

    S

    +
    setReleaseYear(Integer) - Method in class com.google.android.exoplayer2.MediaMetadata.Builder
    +
    +
    Sets the year of the release date.
    +
    setRemoveAudio(boolean) - Method in class com.google.android.exoplayer2.transformer.Transformer.Builder
    Sets whether to remove the audio from the output.
    @@ -32099,6 +33331,8 @@

    S

     
    setRepeatMode(int) - Method in class com.google.android.exoplayer2.ext.media2.SessionPlayerConnector
     
    +
    setRepeatMode(int) - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    setRepeatMode(int) - Method in interface com.google.android.exoplayer2.Player
    Sets the Player.RepeatMode to be used for playback.
    @@ -32129,6 +33363,11 @@

    S

    Sets which repeat toggle modes are enabled.
    +
    setRequestPriority(int) - Method in class com.google.android.exoplayer2.ext.cronet.CronetDataSource.Factory
    +
    +
    Sets the priority of requests made by CronetDataSource instances created by this + factory.
    +
    setRequestProperty(String, String) - Method in class com.google.android.exoplayer2.ext.cronet.CronetDataSource
     
    setRequestProperty(String, String) - Method in class com.google.android.exoplayer2.ext.okhttp.OkHttpDataSource
    @@ -32181,37 +33420,6 @@

    S

    Sets the rewind increment in milliseconds.
    -
    setRewindIncrementMs(int) - Method in class com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
    -
    - -
    -
    setRewindIncrementMs(int) - Method in class com.google.android.exoplayer2.ui.PlayerControlView
    -
    - -
    -
    setRewindIncrementMs(int) - Method in class com.google.android.exoplayer2.ui.PlayerView
    -
    - -
    -
    setRewindIncrementMs(long) - Method in class com.google.android.exoplayer2.DefaultControlDispatcher
    -
    -
    Deprecated. -
    Create a new instance instead and pass the new instance to the UI component. This - makes sure the UI gets updated and is in sync with the new values.
    -
    -
    -
    setRewindIncrementMs(long) - Method in class com.google.android.exoplayer2.ui.PlayerNotificationManager
    -
    - -
    setRoleFlags(int) - Method in class com.google.android.exoplayer2.Format.Builder
    @@ -32256,6 +33464,22 @@

    S

    Sets the color for the scrubber handle.
    +
    setSeekBackIncrementMs(long) - Method in class com.google.android.exoplayer2.SimpleExoPlayer.Builder
    +
    +
    Sets the BasePlayer.seekBack() increment.
    +
    +
    setSeekBackIncrementMs(long) - Method in class com.google.android.exoplayer2.testutil.TestExoPlayerBuilder
    +
    +
    Sets the seek back increment to be used by the player.
    +
    +
    setSeekForwardIncrementMs(long) - Method in class com.google.android.exoplayer2.SimpleExoPlayer.Builder
    +
    +
    Sets the BasePlayer.seekForward() increment.
    +
    +
    setSeekForwardIncrementMs(long) - Method in class com.google.android.exoplayer2.testutil.TestExoPlayerBuilder
    +
    +
    Sets the seek forward increment to be used by the player.
    +
    setSeekParameters(SeekParameters) - Method in class com.google.android.exoplayer2.ExoPlayer.Builder
    Deprecated.
    @@ -32466,6 +33690,8 @@

    S

     
    setShuffleModeEnabled(boolean) - Method in class com.google.android.exoplayer2.ext.cast.CastPlayer
     
    +
    setShuffleModeEnabled(boolean) - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    setShuffleModeEnabled(boolean) - Method in interface com.google.android.exoplayer2.Player
    Sets whether shuffling of windows is enabled.
    @@ -32790,6 +34016,10 @@

    S

    Sets the title.
    +
    setTotalDiscCount(Integer) - Method in class com.google.android.exoplayer2.MediaMetadata.Builder
    +
    +
    Sets the total number of discs.
    +
    setTotalTrackCount(Integer) - Method in class com.google.android.exoplayer2.MediaMetadata.Builder
    Sets the total number of tracks.
    @@ -32840,6 +34070,10 @@

    S

    Sets the TransferListener that will be used.
    +
    setTransferListener(TransferListener) - Method in class com.google.android.exoplayer2.ext.rtmp.RtmpDataSource.Factory
    +
    +
    Sets the TransferListener that will be used.
    +
    setTransferListener(TransferListener) - Method in class com.google.android.exoplayer2.upstream.DefaultHttpDataSource.Factory
    Sets the TransferListener that will be used.
    @@ -32959,6 +34193,14 @@

    S

    Sets whether this session manager should attach DrmSessions to the clear sections of the media content.
    +
    setUseFastForwardAction(boolean) - Method in class com.google.android.exoplayer2.ui.PlayerNotificationManager
    +
    +
    Sets whether the fast forward action should be used.
    +
    +
    setUseFastForwardActionInCompactView(boolean) - Method in class com.google.android.exoplayer2.ui.PlayerNotificationManager
    +
    +
    Sets whether the fast forward action should also be used in compact view.
    +
    setUseLazyPreparation(boolean) - Method in class com.google.android.exoplayer2.ExoPlayer.Builder
    Deprecated.
    @@ -32974,18 +34216,6 @@

    S

    Sets whether to use lazy preparation.
    -
    setUseNavigationActions(boolean) - Method in class com.google.android.exoplayer2.ui.PlayerNotificationManager
    -
    - -
    -
    setUseNavigationActionsInCompactView(boolean) - Method in class com.google.android.exoplayer2.ui.PlayerNotificationManager
    -
    - -
    setUseNextAction(boolean) - Method in class com.google.android.exoplayer2.ui.PlayerNotificationManager
    Sets whether the next action should be used.
    @@ -33033,6 +34263,14 @@

    S

    Sets the text size based on CaptioningManager.getFontScale() if CaptioningManager is available and enabled.
    +
    setUseRewindAction(boolean) - Method in class com.google.android.exoplayer2.ui.PlayerNotificationManager
    +
    +
    Sets whether the rewind action should be used.
    +
    +
    setUseRewindActionInCompactView(boolean) - Method in class com.google.android.exoplayer2.ui.PlayerNotificationManager
    +
    +
    Sets whether the rewind action should also be used in compact view.
    +
    setUserRating(Rating) - Method in class com.google.android.exoplayer2.MediaMetadata.Builder
    Sets the user Rating.
    @@ -33105,6 +34343,8 @@

    S

    This method is not supported and does nothing.
    +
    setVideoSurface(Surface) - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    setVideoSurface(Surface) - Method in interface com.google.android.exoplayer2.Player
    Sets the Surface onto which video will be rendered.
    @@ -33128,6 +34368,8 @@

    S

    This method is not supported and does nothing.
    +
    setVideoSurfaceHolder(SurfaceHolder) - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    setVideoSurfaceHolder(SurfaceHolder) - Method in interface com.google.android.exoplayer2.Player
    Sets the SurfaceHolder that holds the Surface onto which video will be @@ -33145,6 +34387,8 @@

    S

    This method is not supported and does nothing.
    +
    setVideoSurfaceView(SurfaceView) - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    setVideoSurfaceView(SurfaceView) - Method in interface com.google.android.exoplayer2.Player
    Sets the SurfaceView onto which video will be rendered.
    @@ -33161,6 +34405,8 @@

    S

    This method is not supported and does nothing.
    +
    setVideoTextureView(TextureView) - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    setVideoTextureView(TextureView) - Method in interface com.google.android.exoplayer2.Player
    Sets the TextureView onto which video will be rendered.
    @@ -33170,13 +34416,17 @@

    S

    setVideoTextureView(TextureView) - Method in class com.google.android.exoplayer2.testutil.StubExoPlayer
     
    setViewportSize(int, int, boolean) - Method in class com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder
    +
     
    +
    setViewportSize(int, int, boolean) - Method in class com.google.android.exoplayer2.trackselection.TrackSelectionParameters.Builder
    Sets the viewport size to constrain adaptive video selections so that only tracks suitable for the viewport are selected.
    setViewportSizeToPhysicalDisplaySize(Context, boolean) - Method in class com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder
    +
     
    +
    setViewportSizeToPhysicalDisplaySize(Context, boolean) - Method in class com.google.android.exoplayer2.trackselection.TrackSelectionParameters.Builder
    -
    setViewType(int) - Method in class com.google.android.exoplayer2.ui.SubtitleView
    @@ -33208,6 +34458,8 @@

    S

    This method is not supported and does nothing.
    +
    setVolume(float) - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    setVolume(float) - Method in interface com.google.android.exoplayer2.Player
    Sets the audio volume, with 0 being silence and 1 being unity gain (signal unchanged).
    @@ -33240,9 +34492,15 @@

    S

    Sets the fill color of the window.
    +
    setWriter(CharSequence) - Method in class com.google.android.exoplayer2.MediaMetadata.Builder
    +
    +
    Sets the writer.
    +
    setYear(Integer) - Method in class com.google.android.exoplayer2.MediaMetadata.Builder
    -
    Sets the year.
    +
    ShadowMediaCodecConfig - Class in com.google.android.exoplayer2.robolectric
    @@ -33313,6 +34571,10 @@

    S

     
    shouldInitCodec(MediaCodecInfo) - Method in class com.google.android.exoplayer2.video.MediaCodecVideoRenderer
     
    +
    shouldPlayAdGroup() - Method in class com.google.android.exoplayer2.source.ads.AdPlaybackState.AdGroup
    +
    +
    Returns whether the ad group has at least one ad that should be played.
    +
    shouldProcessBuffer(long, long) - Method in class com.google.android.exoplayer2.testutil.FakeAudioRenderer
     
    shouldProcessBuffer(long, long) - Method in class com.google.android.exoplayer2.testutil.FakeRenderer
    @@ -33587,7 +34849,7 @@

    S

     
    SingleSegmentBase(RangedUri, long, long, long, long) - Constructor for class com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase
     
    -
    SingleSegmentRepresentation(long, Format, String, SegmentBase.SingleSegmentBase, List<Descriptor>, String, long) - Constructor for class com.google.android.exoplayer2.source.dash.manifest.Representation.SingleSegmentRepresentation
    +
    SingleSegmentRepresentation(long, Format, List<BaseUrl>, SegmentBase.SingleSegmentBase, List<Descriptor>, String, long) - Constructor for class com.google.android.exoplayer2.source.dash.manifest.Representation.SingleSegmentRepresentation
     
    SINK_FORMAT_SUPPORTED_DIRECTLY - Static variable in interface com.google.android.exoplayer2.audio.AudioSink
    @@ -33622,7 +34884,7 @@

    S

    Returns the number of events in the set.
    -
    size() - Method in class com.google.android.exoplayer2.util.ExoFlags
    +
    size() - Method in class com.google.android.exoplayer2.util.FlagSet
    Returns the number of flags in this set.
    @@ -33630,6 +34892,10 @@

    S

    Returns the number of items in the queue.
    +
    size() - Method in class com.google.android.exoplayer2.util.ListenerSet
    +
    +
    Returns the number of added listeners.
    +
    size() - Method in class com.google.android.exoplayer2.util.LongArray
    Returns the current size of the array.
    @@ -33802,8 +35068,8 @@

    S

    sneakyThrow(Throwable) - Static method in class com.google.android.exoplayer2.util.Util
    -
    A hacky method that always throws t even if t is a checked exception, - and is not declared to be thrown.
    +
    A hacky method that always throws t even if t is a checked exception, and is + not declared to be thrown.
    sniff(ExtractorInput) - Method in class com.google.android.exoplayer2.ext.flac.FlacExtractor
     
    @@ -33875,26 +35141,6 @@

    S

    Information about the original source of the media presentation.
    -
    SOURCE_GMS - Static variable in class com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper
    -
    -
    Cronet implementation from GMSCore.
    -
    -
    SOURCE_NATIVE - Static variable in class com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper
    -
    -
    Natively bundled Cronet implementation.
    -
    -
    SOURCE_UNAVAILABLE - Static variable in class com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper
    -
    -
    No Cronet implementation available.
    -
    -
    SOURCE_UNKNOWN - Static variable in class com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper
    -
    -
    Other (unknown) Cronet implementation.
    -
    -
    SOURCE_USER_PROVIDED - Static variable in class com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper
    -
    -
    User-provided Cronet engine.
    -
    sourceId(int) - Method in class com.google.android.exoplayer2.source.SampleQueue
    Sets a source identifier for subsequent samples.
    @@ -34068,18 +35314,6 @@

    S

    A downloader for SmoothStreaming streams.
    -
    SsDownloader(Uri, List<StreamKey>, CacheDataSource.Factory) - Constructor for class com.google.android.exoplayer2.source.smoothstreaming.offline.SsDownloader
    -
    - -
    -
    SsDownloader(Uri, List<StreamKey>, CacheDataSource.Factory, Executor) - Constructor for class com.google.android.exoplayer2.source.smoothstreaming.offline.SsDownloader
    -
    - -
    SsDownloader(MediaItem, CacheDataSource.Factory) - Constructor for class com.google.android.exoplayer2.source.smoothstreaming.offline.SsDownloader
    Creates an instance.
    @@ -34290,8 +35524,8 @@

    S

    startTimeUs - Variable in class com.google.android.exoplayer2.source.chunk.Chunk
    -
    The start time of the media contained by the chunk, or C.TIME_UNSET if the data - being loaded does not contain media samples.
    +
    The start time of the media contained by the chunk, or C.TIME_UNSET if the data being + loaded does not contain media samples.
    startTimeUs - Variable in class com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist
    @@ -34414,8 +35648,8 @@

    S

    STEREO_MODE_STEREO_MESH - Static variable in class com.google.android.exoplayer2.C
    -
    Indicates a stereo layout where the left and right eyes have separate meshes, - used with 360/3D/VR videos.
    +
    Indicates a stereo layout where the left and right eyes have separate meshes, used with + 360/3D/VR videos.
    STEREO_MODE_TOP_BOTTOM - Static variable in class com.google.android.exoplayer2.C
    @@ -34429,6 +35663,8 @@

    S

     
    stop() - Method in class com.google.android.exoplayer2.BaseRenderer
     
    +
    stop() - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    stop() - Method in class com.google.android.exoplayer2.NoSampleRenderer
     
    stop() - Method in interface com.google.android.exoplayer2.Player
    @@ -34463,6 +35699,8 @@

    S

    stop(boolean) - Method in class com.google.android.exoplayer2.ext.cast.CastPlayer
     
    +
    stop(boolean) - Method in class com.google.android.exoplayer2.ForwardingPlayer
    +
     
    stop(boolean) - Method in interface com.google.android.exoplayer2.Player
    Deprecated. @@ -34655,13 +35893,11 @@

    S

    subsampleOffsetUs - Variable in class com.google.android.exoplayer2.metadata.MetadataInputBuffer
    -
    An offset that must be added to the metadata's timestamps after it's been decoded, or - Format.OFFSET_SAMPLE_RELATIVE if DecoderInputBuffer.timeUs should be added.
    +
    An offset that must be added to the metadata's timestamps after it's been decoded, or Format.OFFSET_SAMPLE_RELATIVE if DecoderInputBuffer.timeUs should be added.
    subsampleOffsetUs - Variable in class com.google.android.exoplayer2.text.SubtitleInputBuffer
    -
    An offset that must be added to the subtitle's event times after it's been decoded, or - Format.OFFSET_SAMPLE_RELATIVE if DecoderInputBuffer.timeUs should be added.
    +
    An offset that must be added to the subtitle's event times after it's been decoded, or Format.OFFSET_SAMPLE_RELATIVE if DecoderInputBuffer.timeUs should be added.
    subset(Uri...) - Method in class com.google.android.exoplayer2.testutil.CacheAsserts.RequestSet
     
    @@ -35151,12 +36387,16 @@

    T

    TIMELINE_CHANGE_REASON_SOURCE_UPDATE - Static variable in interface com.google.android.exoplayer2.Player
    -
    Timeline changed as a result of a dynamic update introduced by the played media.
    +
    Timeline changed as a result of a source update (e.g.
    Timeline.Period - Class in com.google.android.exoplayer2
    Holds information about a period in a Timeline.
    +
    Timeline.RemotableTimeline - Class in com.google.android.exoplayer2
    +
    +
    A concrete class of Timeline to restore a Timeline instance from a Bundle sent by another process via IBinder.
    +
    Timeline.Window - Class in com.google.android.exoplayer2
    Holds information about a window in a Timeline.
    @@ -35188,8 +36428,7 @@

    T

    TimelineQueueEditor.QueueDataAdapter - Interface in com.google.android.exoplayer2.ext.mediasession
    Adapter to get MediaDescriptionCompat of items in the queue and to notify the - application about changes in the queue to sync the data structure backing the - MediaSessionConnector.
    + application about changes in the queue to sync the data structure backing the MediaSessionConnector.
    TimelineQueueNavigator - Class in com.google.android.exoplayer2.ext.mediasession
    @@ -35266,8 +36505,7 @@

    T

     
    timeShiftBufferDepthMs - Variable in class com.google.android.exoplayer2.source.dash.manifest.DashManifest
    -
    The timeShiftBufferDepth value in milliseconds, or C.TIME_UNSET if not - present.
    +
    The timeShiftBufferDepth value in milliseconds, or C.TIME_UNSET if not present.
    TimeSignalCommand - Class in com.google.android.exoplayer2.metadata.scte35
    @@ -35279,7 +36517,7 @@

    T

    TimestampAdjuster - Class in com.google.android.exoplayer2.util
    -
    Offsets timestamps according to an initial sample timestamp offset.
    +
    Adjusts and offsets sample timestamps.
    TimestampAdjuster(long) - Constructor for class com.google.android.exoplayer2.util.TimestampAdjuster
     
    @@ -35289,7 +36527,7 @@

    T

    TimestampAdjusterProvider() - Constructor for class com.google.android.exoplayer2.source.hls.TimestampAdjusterProvider
     
    -
    timestampMs - Variable in exception com.google.android.exoplayer2.ExoPlaybackException
    +
    timestampMs - Variable in exception com.google.android.exoplayer2.PlaybackException
    The value of SystemClock.elapsedRealtime() when this exception was created.
    @@ -35315,6 +36553,11 @@

    T

    The time of the seek point, in microseconds.
    +
    timeUs - Variable in class com.google.android.exoplayer2.source.ads.AdPlaybackState.AdGroup
    +
    +
    The time of the ad group in the Timeline.Period, in + microseconds, or C.TIME_END_OF_SOURCE to indicate a postroll ad.
    +
    timeUsToTargetTime(long) - Method in class com.google.android.exoplayer2.extractor.BinarySearchSeeker.BinarySearchSeekMap
     
    timeUsToTargetTime(long) - Method in class com.google.android.exoplayer2.extractor.BinarySearchSeeker.DefaultSeekTimestampConverter
    @@ -35369,8 +36612,12 @@

    T

     
    toBundle() - Method in class com.google.android.exoplayer2.PercentageRating
     
    +
    toBundle() - Method in exception com.google.android.exoplayer2.PlaybackException
    +
     
    toBundle() - Method in class com.google.android.exoplayer2.PlaybackParameters
     
    +
    toBundle() - Method in class com.google.android.exoplayer2.Player.Commands
    +
     
    toBundle() - Method in class com.google.android.exoplayer2.Player.PositionInfo
    Returns a Bundle representing the information stored in this object.
    @@ -35383,6 +36630,8 @@

    T

    toBundle() - Method in class com.google.android.exoplayer2.StarRating
     
    +
    toBundle() - Method in class com.google.android.exoplayer2.text.Cue
    +
     
    toBundle() - Method in class com.google.android.exoplayer2.ThumbRating
     
    toBundle() - Method in class com.google.android.exoplayer2.Timeline.Period
    @@ -35399,6 +36648,17 @@

    T

    toBundle() - Method in class com.google.android.exoplayer2.video.VideoSize
     
    +
    toBundle(boolean) - Method in class com.google.android.exoplayer2.Timeline
    +
    toBundleArrayList(List<T>) - Static method in class com.google.android.exoplayer2.util.BundleableUtils
    +
    +
    Converts a list of Bundleable to an ArrayList of Bundle so that the + returned list can be put to Bundle using Bundle.putParcelableArrayList(java.lang.String, java.util.ArrayList<? extends android.os.Parcelable>) + conveniently.
    +
    +
    toBundleList(List<T>) - Static method in class com.google.android.exoplayer2.util.BundleableUtils
    +
    +
    Converts a list of Bundleable to a list Bundle.
    +
    toByteArray(InputStream) - Static method in class com.google.android.exoplayer2.util.Util
    Converts the entirety of an InputStream to a byte array.
    @@ -35445,6 +36705,10 @@

    T

    Converts a MediaItem to a MediaQueueItem.
    +
    toNullableBundle(Bundleable) - Static method in class com.google.android.exoplayer2.util.BundleableUtils
    +
    +
    Converts a Bundleable to a Bundle.
    +
    toString() - Method in class com.google.android.exoplayer2.audio.AudioCapabilities
     
    toString() - Method in class com.google.android.exoplayer2.audio.AudioProcessor.AudioFormat
    @@ -35557,6 +36821,10 @@

    T

    Total buffered duration from AnalyticsListener.EventTime.currentPlaybackPositionMs at the time of the event, in milliseconds.
    +
    totalDiscCount - Variable in class com.google.android.exoplayer2.MediaMetadata
    +
    +
    Optional total number of discs.
    +
    totalDroppedFrames - Variable in class com.google.android.exoplayer2.analytics.PlaybackStats
    The total number of dropped video frames.
    @@ -35814,6 +37082,8 @@

    T

    Constraint parameters for track selection.
    +
    TrackSelectionParameters(TrackSelectionParameters.Builder) - Constructor for class com.google.android.exoplayer2.trackselection.TrackSelectionParameters
    +
     
    TrackSelectionParameters.Builder - Class in com.google.android.exoplayer2.trackselection
    @@ -35934,8 +37204,7 @@

    T

    trim() - Method in interface com.google.android.exoplayer2.upstream.Allocator
    -
    Hints to the allocator that it should make a best effort to release any excess - Allocations.
    +
    Hints to the allocator that it should make a best effort to release any excess Allocations.
    trim() - Method in class com.google.android.exoplayer2.upstream.DefaultAllocator
     
    @@ -36097,7 +37366,7 @@

    T

    type - Variable in class com.google.android.exoplayer2.source.chunk.Chunk
    -
    The type of the chunk.
    +
    The data type of the chunk.
    type - Variable in class com.google.android.exoplayer2.source.dash.manifest.AdaptationSet
    @@ -36113,6 +37382,10 @@

    T

    type - Variable in exception com.google.android.exoplayer2.upstream.HttpDataSource.HttpDataSourceException
     
    +
    type - Variable in class com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.FallbackSelection
    +
    +
    The type of fallback.
    +
    type - Variable in class com.google.android.exoplayer2.upstream.ParsingLoadable
    The type of the data.
    @@ -36134,7 +37407,9 @@

    T

    Type for when all ad groups failed to load.
    TYPE_CLOSE - Static variable in exception com.google.android.exoplayer2.upstream.HttpDataSource.HttpDataSourceException
    -
     
    +
    +
    The error occurred in closing a HttpDataSource.
    +
    TYPE_CUSTOM_BASE - Static variable in interface com.google.android.exoplayer2.trackselection.TrackSelection
    The first value that can be used for application specific track selection types.
    @@ -36164,7 +37439,9 @@

    T

    The search didn't find any timestamps.
    TYPE_OPEN - Static variable in exception com.google.android.exoplayer2.upstream.HttpDataSource.HttpDataSourceException
    -
     
    +
    +
    The error occurred reading data from a HttpDataSource.
    +
    TYPE_OTHER - Static variable in class com.google.android.exoplayer2.C
    Value returned by Util.inferContentType(String) for files other than DASH, HLS or @@ -36183,14 +37460,16 @@

    T

    The search found only timestamps smaller than the target timestamp.
    TYPE_READ - Static variable in exception com.google.android.exoplayer2.upstream.HttpDataSource.HttpDataSourceException
    -
     
    +
    +
    The error occurred in opening a HttpDataSource.
    +
    TYPE_REMOTE - Static variable in exception com.google.android.exoplayer2.ExoPlaybackException
    The error occurred in a remote component.
    TYPE_RENDERER - Static variable in exception com.google.android.exoplayer2.ExoPlaybackException
    -
    The error occurred in a Renderer.
    +
    The error occurred in a Renderer.
    TYPE_RTSP - Static variable in class com.google.android.exoplayer2.C
    @@ -36198,7 +37477,7 @@

    T

    TYPE_SOURCE - Static variable in exception com.google.android.exoplayer2.ExoPlaybackException
    -
    The error occurred loading data from a MediaSource.
    +
    The error occurred loading data from a MediaSource.
    TYPE_SS - Static variable in class com.google.android.exoplayer2.C
    @@ -36262,8 +37541,10 @@

    U

    Thrown when an error is encountered when trying to read from a UdpDataSource.
    -
    UdpDataSourceException(IOException) - Constructor for exception com.google.android.exoplayer2.upstream.UdpDataSource.UdpDataSourceException
    -
     
    +
    UdpDataSourceException(Throwable, int) - Constructor for exception com.google.android.exoplayer2.upstream.UdpDataSource.UdpDataSourceException
    +
    +
    Creates a UdpDataSourceException.
    +
    uid - Variable in class com.google.android.exoplayer2.Timeline.Period
    A unique identifier for the period.
    @@ -36309,8 +37590,8 @@

    U

    unescapeStream(byte[], int) - Static method in class com.google.android.exoplayer2.util.NalUnitUtil
    -
    Unescapes data up to the specified limit, replacing occurrences of [0, 0, 3] with - [0, 0].
    +
    Unescapes data up to the specified limit, replacing occurrences of [0, 0, 3] with [0, + 0].
    UnexpectedDiscontinuityException(long, long) - Constructor for exception com.google.android.exoplayer2.audio.AudioSink.UnexpectedDiscontinuityException
    @@ -36587,6 +37868,10 @@

    U

    url - Variable in class com.google.android.exoplayer2.metadata.id3.UrlLinkFrame
     
    +
    url - Variable in class com.google.android.exoplayer2.source.dash.manifest.BaseUrl
    +
    +
    The URL.
    +
    url - Variable in class com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.Rendition
    The rendition's url, or null if the tag does not have a URI attribute.
    @@ -36733,8 +38018,7 @@

    U

     
    UUID_NIL - Static variable in class com.google.android.exoplayer2.C
    -
    The Nil UUID as defined by - RFC4122.
    +
    The Nil UUID as defined by RFC4122.
    @@ -37066,15 +38350,15 @@

    V

    -
    viewportHeight - Variable in class com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters
    +
    viewportHeight - Variable in class com.google.android.exoplayer2.trackselection.TrackSelectionParameters
    Viewport height in pixels.
    -
    viewportOrientationMayChange - Variable in class com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters
    +
    viewportOrientationMayChange - Variable in class com.google.android.exoplayer2.trackselection.TrackSelectionParameters
    Whether the viewport orientation may change during playback.
    -
    viewportWidth - Variable in class com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters
    +
    viewportWidth - Variable in class com.google.android.exoplayer2.trackselection.TrackSelectionParameters
    Viewport width in pixels.
    @@ -37128,17 +38412,6 @@

    V

    Configures and queries the underlying native library.
    -
    VpxOutputBuffer - Class in com.google.android.exoplayer2.ext.vp9
    -
    -
    Deprecated. - -
    -
    -
    VpxOutputBuffer(OutputBuffer.Owner<VideoDecoderOutputBuffer>) - Constructor for class com.google.android.exoplayer2.ext.vp9.VpxOutputBuffer
    -
    -
    Deprecated.
    -
    Creates VpxOutputBuffer.
    -
    @@ -37305,6 +38578,10 @@

    W

    Utility methods for parsing WebVTT data.
    +
    weight - Variable in class com.google.android.exoplayer2.source.dash.manifest.BaseUrl
    +
    +
    The weight.
    +
    WIDEVINE_UUID - Static variable in class com.google.android.exoplayer2.C
    UUID for the Widevine DRM scheme.
    @@ -37410,6 +38687,11 @@

    W

    Returns a copy this data spec with additional HTTP request headers.
    +
    withAdDurationsUs(int, long...) - Method in class com.google.android.exoplayer2.source.ads.AdPlaybackState
    +
    +
    Returns an instance with the specified ad durations, in microseconds, in the specified ad + group.
    +
    withAdDurationsUs(long[]) - Method in class com.google.android.exoplayer2.source.ads.AdPlaybackState.AdGroup
    Returns a new instance with the specified ad durations, in microseconds.
    @@ -37418,6 +38700,10 @@

    W

    Returns an instance with the specified ad durations, in microseconds.
    +
    withAdGroupTimeUs(int, long) - Method in class com.google.android.exoplayer2.source.ads.AdPlaybackState
    +
    +
    Returns an instance with the specified ad group time.
    +
    withAdLoadError(int, int) - Method in class com.google.android.exoplayer2.source.ads.AdPlaybackState
    Returns an instance with the specified ad marked as having a load error.
    @@ -37456,6 +38742,15 @@

    W

    Returns an instance with the specified content duration, in microseconds.
    +
    withContentResumeOffsetUs(int, long) - Method in class com.google.android.exoplayer2.source.ads.AdPlaybackState
    +
    +
    Returns an instance with the specified AdPlaybackState.AdGroup.contentResumeOffsetUs, in microseconds, + for the specified ad group.
    +
    +
    withContentResumeOffsetUs(long) - Method in class com.google.android.exoplayer2.source.ads.AdPlaybackState.AdGroup
    +
    +
    Returns an instance with the specified AdPlaybackState.AdGroup.contentResumeOffsetUs.
    +
    withFamily(String) - Method in interface com.google.android.exoplayer2.testutil.truth.SpannedSubject.Typefaced
    Checks that at least one of the matched spans has the expected fontFamily.
    @@ -37464,6 +38759,15 @@

    W

    Checks that one of the matched spans has the expected flags.
    +
    withIsServerSideInserted(boolean) - Method in class com.google.android.exoplayer2.source.ads.AdPlaybackState.AdGroup
    +
    +
    Returns an instance with the specified value for AdPlaybackState.AdGroup.isServerSideInserted.
    +
    +
    withIsServerSideInserted(int, boolean) - Method in class com.google.android.exoplayer2.source.ads.AdPlaybackState
    +
    +
    Returns an instance with the specified value for AdPlaybackState.AdGroup.isServerSideInserted in the + specified ad group.
    +
    withManifestFormatInfo(Format) - Method in class com.google.android.exoplayer2.Format
     
    withMarkAndPosition(int, int, int) - Method in interface com.google.android.exoplayer2.testutil.truth.SpannedSubject.EmphasizedText
    @@ -37471,6 +38775,10 @@

    W

    Checks that at least one of the matched spans has the expected mark and position.
    +
    withNewAdGroup(int, long) - Method in class com.google.android.exoplayer2.source.ads.AdPlaybackState
    +
    +
    Returns an instance with a new ad group.
    +
    withParameters(int, MediaSource.MediaPeriodId) - Method in class com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher
    Creates a view of the event dispatcher with the provided window index and media period id.
    @@ -37484,6 +38792,11 @@

    W

    Returns an instance with the specified ad marked as played.
    +
    withRemovedAdGroupCount(int) - Method in class com.google.android.exoplayer2.source.ads.AdPlaybackState
    +
    +
    Returns an instance with the specified number of removed ad + groups.
    +
    withRequestHeaders(Map<String, String>) - Method in class com.google.android.exoplayer2.upstream.DataSpec
    Returns a copy of this data spec with the specified HTTP request headers.
    @@ -37509,6 +38822,10 @@

    W

    Checks that at least one of the matched spans has the expected text.
    +
    withTimeUs(long) - Method in class com.google.android.exoplayer2.source.ads.AdPlaybackState.AdGroup
    +
    +
    Returns a new instance with the AdPlaybackState.AdGroup.timeUs set to the specified value.
    +
    withUri(Uri) - Method in class com.google.android.exoplayer2.upstream.DataSpec
    Returns a copy of this data spec with the specified Uri.
    @@ -37563,6 +38880,10 @@

    W

    Creates an instance.
    +
    writer - Variable in class com.google.android.exoplayer2.MediaMetadata
    +
    +
    Optional writer.
    +
    writeToBuffer(byte[], int, int) - Method in class com.google.android.exoplayer2.source.rtsp.RtpPacket
    Writes the data in an RTP packet to a target buffer.
    @@ -37671,7 +38992,9 @@

    Y

    year - Variable in class com.google.android.exoplayer2.MediaMetadata
    -
    Optional year.
    +
    Deprecated. + +
    yuvPlanes - Variable in class com.google.android.exoplayer2.video.VideoDecoderOutputBuffer
    diff --git a/docs/doc/reference/member-search-index.js b/docs/doc/reference/member-search-index.js index 47a8fbed674..41bac2c724e 100644 --- a/docs/doc/reference/member-search-index.js +++ b/docs/doc/reference/member-search-index.js @@ -1 +1 @@ -memberSearchIndex = [{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AAC_ELD_MAX_RATE_BYTES_PER_SECOND"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AAC_HE_AUDIO_SAMPLE_COUNT"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AAC_HE_V1_MAX_RATE_BYTES_PER_SECOND"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AAC_HE_V2_MAX_RATE_BYTES_PER_SECOND"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AAC_LC_AUDIO_SAMPLE_COUNT"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AAC_LC_MAX_RATE_BYTES_PER_SECOND"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AAC_LD_AUDIO_SAMPLE_COUNT"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AAC_XHE_AUDIO_SAMPLE_COUNT"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AAC_XHE_MAX_RATE_BYTES_PER_SECOND"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"abandonedBeforeReadyCount"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"absoluteStreamPosition"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"AbstractConcatenatedTimeline(boolean, ShuffleOrder)","url":"%3Cinit%3E(boolean,com.google.android.exoplayer2.source.ShuffleOrder)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"AC3"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"AC3_MAX_RATE_BYTES_PER_SECOND"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Extractor","l":"Ac3Extractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Reader","l":"Ac3Reader()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Reader","l":"Ac3Reader(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"AC4"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util","l":"AC40_SYNCWORD"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util","l":"AC41_SYNCWORD"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Extractor","l":"Ac4Extractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Reader","l":"Ac4Reader()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Reader","l":"Ac4Reader(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"Consumer","l":"accept(T)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.AllowedCommandProvider","l":"acceptConnection(MediaSession, MediaSession.ControllerInfo)","url":"acceptConnection(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.DefaultAllowedCommandProvider","l":"acceptConnection(MediaSession, MediaSession.ControllerInfo)","url":"acceptConnection(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"accessibilityChannel"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"AdaptationSet","l":"accessibilityDescriptors"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"acquire()"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"acquire()"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"acquire()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"acquire()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"acquire(DrmSessionEventListener.EventDispatcher)","url":"acquire(com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2.drm","c":"ErrorStateDrmSession","l":"acquire(DrmSessionEventListener.EventDispatcher)","url":"acquire(com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.AppManagedProvider","l":"acquireExoMediaDrm(UUID)","url":"acquireExoMediaDrm(java.util.UUID)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.Provider","l":"acquireExoMediaDrm(UUID)","url":"acquireExoMediaDrm(java.util.UUID)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"acquireSession(Looper, DrmSessionEventListener.EventDispatcher, Format)","url":"acquireSession(android.os.Looper,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionManager","l":"acquireSession(Looper, DrmSessionEventListener.EventDispatcher, Format)","url":"acquireSession(android.os.Looper,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData.Segment","l":"action"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"ACTION_ADD_DOWNLOAD"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"ACTION_FAST_FORWARD"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"ACTION_INIT"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"ACTION_NEXT"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"ACTION_PAUSE"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"ACTION_PAUSE_DOWNLOADS"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"ACTION_PLAY"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"ACTION_PREVIOUS"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"ACTION_REMOVE_ALL_DOWNLOADS"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"ACTION_REMOVE_DOWNLOAD"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"ACTION_RESUME_DOWNLOADS"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"ACTION_REWIND"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"ACTION_SET_PLAYBACK_SPEED"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"ACTION_SET_REQUIREMENTS"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"ACTION_SET_STOP_REASON"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"ACTION_STOP"},{"p":"com.google.android.exoplayer2.testutil","c":"Action","l":"Action(String, String)","url":"%3Cinit%3E(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.PlaybackPreparer","l":"ACTIONS"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.QueueNavigator","l":"ACTIONS"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.UnexpectedDiscontinuityException","l":"actualPresentationTimeUs"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"AD_STATE_AVAILABLE"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"AD_STATE_ERROR"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"AD_STATE_PLAYED"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"AD_STATE_SKIPPED"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"AD_STATE_UNAVAILABLE"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection.AdaptationCheckpoint","l":"AdaptationCheckpoint(long, long)","url":"%3Cinit%3E(long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"AdaptationSet","l":"AdaptationSet(int, int, List, List, List, List)","url":"%3Cinit%3E(int,int,java.util.List,java.util.List,java.util.List,java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Period","l":"adaptationSets"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"adaptive"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"ADAPTIVE_NOT_SEAMLESS"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"ADAPTIVE_NOT_SUPPORTED"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"ADAPTIVE_SEAMLESS"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"ADAPTIVE_SUPPORT_MASK"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"AdaptiveTrackSelection(TrackGroup, int[], BandwidthMeter)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroup,int[],com.google.android.exoplayer2.upstream.BandwidthMeter)"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"AdaptiveTrackSelection(TrackGroup, int[], int, BandwidthMeter, long, long, long, float, float, List, Clock)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroup,int[],int,com.google.android.exoplayer2.upstream.BandwidthMeter,long,long,long,float,float,java.util.List,com.google.android.exoplayer2.util.Clock)"},{"p":"com.google.android.exoplayer2.testutil","c":"Dumper","l":"add(Dumper.Dumpable)","url":"add(com.google.android.exoplayer2.testutil.Dumper.Dumpable)"},{"p":"com.google.android.exoplayer2.util","c":"CopyOnWriteMultiset","l":"add(E)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor.QueueDataAdapter","l":"add(int, MediaDescriptionCompat)","url":"add(int,android.support.v4.media.MediaDescriptionCompat)"},{"p":"com.google.android.exoplayer2","c":"Player.Commands.Builder","l":"add(int)"},{"p":"com.google.android.exoplayer2.util","c":"ExoFlags.Builder","l":"add(int)"},{"p":"com.google.android.exoplayer2.util","c":"IntArrayQueue","l":"add(int)"},{"p":"com.google.android.exoplayer2.util","c":"PriorityTaskManager","l":"add(int)"},{"p":"com.google.android.exoplayer2.util","c":"TimedValueQueue","l":"add(long, V)","url":"add(long,V)"},{"p":"com.google.android.exoplayer2.util","c":"LongArray","l":"add(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"Dumper","l":"add(String, byte[])","url":"add(java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"Dumper","l":"add(String, Object)","url":"add(java.lang.String,java.lang.Object)"},{"p":"com.google.android.exoplayer2.util","c":"ListenerSet","l":"add(T)"},{"p":"com.google.android.exoplayer2.util","c":"ExoFlags.Builder","l":"addAll(ExoFlags)","url":"addAll(com.google.android.exoplayer2.util.ExoFlags)"},{"p":"com.google.android.exoplayer2","c":"Player.Commands.Builder","l":"addAll(int...)"},{"p":"com.google.android.exoplayer2.util","c":"ExoFlags.Builder","l":"addAll(int...)"},{"p":"com.google.android.exoplayer2","c":"Player.Commands.Builder","l":"addAll(Player.Commands)","url":"addAll(com.google.android.exoplayer2.Player.Commands)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addAnalyticsListener(AnalyticsListener)","url":"addAnalyticsListener(com.google.android.exoplayer2.analytics.AnalyticsListener)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"addAudioLanguagesToSelection(String...)","url":"addAudioLanguagesToSelection(java.lang.String...)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioComponent","l":"addAudioListener(AudioListener)","url":"addAudioListener(com.google.android.exoplayer2.audio.AudioListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addAudioListener(AudioListener)","url":"addAudioListener(com.google.android.exoplayer2.audio.AudioListener)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"addAudioOffloadListener(ExoPlayer.AudioOffloadListener)","url":"addAudioOffloadListener(com.google.android.exoplayer2.ExoPlayer.AudioOffloadListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addAudioOffloadListener(ExoPlayer.AudioOffloadListener)","url":"addAudioOffloadListener(com.google.android.exoplayer2.ExoPlayer.AudioOffloadListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"addAudioOffloadListener(ExoPlayer.AudioOffloadListener)","url":"addAudioOffloadListener(com.google.android.exoplayer2.ExoPlayer.AudioOffloadListener)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.DeviceComponent","l":"addDeviceListener(DeviceListener)","url":"addDeviceListener(com.google.android.exoplayer2.device.DeviceListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addDeviceListener(DeviceListener)","url":"addDeviceListener(com.google.android.exoplayer2.device.DeviceListener)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"addDownload(DownloadRequest, int)","url":"addDownload(com.google.android.exoplayer2.offline.DownloadRequest,int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"addDownload(DownloadRequest)","url":"addDownload(com.google.android.exoplayer2.offline.DownloadRequest)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"addDrmEventListener(Handler, DrmSessionEventListener)","url":"addDrmEventListener(android.os.Handler,com.google.android.exoplayer2.drm.DrmSessionEventListener)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"addDrmEventListener(Handler, DrmSessionEventListener)","url":"addDrmEventListener(android.os.Handler,com.google.android.exoplayer2.drm.DrmSessionEventListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"BandwidthMeter","l":"addEventListener(Handler, BandwidthMeter.EventListener)","url":"addEventListener(android.os.Handler,com.google.android.exoplayer2.upstream.BandwidthMeter.EventListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"addEventListener(Handler, BandwidthMeter.EventListener)","url":"addEventListener(android.os.Handler,com.google.android.exoplayer2.upstream.BandwidthMeter.EventListener)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener.EventDispatcher","l":"addEventListener(Handler, DrmSessionEventListener)","url":"addEventListener(android.os.Handler,com.google.android.exoplayer2.drm.DrmSessionEventListener)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"addEventListener(Handler, MediaSourceEventListener)","url":"addEventListener(android.os.Handler,com.google.android.exoplayer2.source.MediaSourceEventListener)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"addEventListener(Handler, MediaSourceEventListener)","url":"addEventListener(android.os.Handler,com.google.android.exoplayer2.source.MediaSourceEventListener)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"addEventListener(Handler, MediaSourceEventListener)","url":"addEventListener(android.os.Handler,com.google.android.exoplayer2.source.MediaSourceEventListener)"},{"p":"com.google.android.exoplayer2.decoder","c":"Buffer","l":"addFlag(int)"},{"p":"com.google.android.exoplayer2","c":"Player.Commands.Builder","l":"addIf(int, boolean)","url":"addIf(int,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"ExoFlags.Builder","l":"addIf(int, boolean)","url":"addIf(int,boolean)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"addItems(int, MediaQueueItem...)","url":"addItems(int,com.google.android.gms.cast.MediaQueueItem...)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"addItems(MediaQueueItem...)","url":"addItems(com.google.android.gms.cast.MediaQueueItem...)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"additionalFailureInfo"},{"p":"com.google.android.exoplayer2.testutil","c":"AdditionalFailureInfo","l":"AdditionalFailureInfo()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"addListener(AnalyticsListener)","url":"addListener(com.google.android.exoplayer2.analytics.AnalyticsListener)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"addListener(DownloadManager.Listener)","url":"addListener(com.google.android.exoplayer2.offline.DownloadManager.Listener)"},{"p":"com.google.android.exoplayer2.upstream","c":"BandwidthMeter.EventListener.EventDispatcher","l":"addListener(Handler, BandwidthMeter.EventListener)","url":"addListener(android.os.Handler,com.google.android.exoplayer2.upstream.BandwidthMeter.EventListener)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"addListener(HlsPlaylistTracker.PlaylistEventListener)","url":"addListener(com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker.PlaylistEventListener)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"addListener(HlsPlaylistTracker.PlaylistEventListener)","url":"addListener(com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker.PlaylistEventListener)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"addListener(Player.EventListener)","url":"addListener(com.google.android.exoplayer2.Player.EventListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addListener(Player.EventListener)","url":"addListener(com.google.android.exoplayer2.Player.EventListener)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"addListener(Player.EventListener)","url":"addListener(com.google.android.exoplayer2.Player.EventListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"addListener(Player.EventListener)","url":"addListener(com.google.android.exoplayer2.Player.EventListener)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"addListener(Player.Listener)","url":"addListener(com.google.android.exoplayer2.Player.Listener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addListener(Player.Listener)","url":"addListener(com.google.android.exoplayer2.Player.Listener)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"addListener(Player.Listener)","url":"addListener(com.google.android.exoplayer2.Player.Listener)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"addListener(Player.Listener)","url":"addListener(com.google.android.exoplayer2.Player.Listener)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"addListener(String, Cache.Listener)","url":"addListener(java.lang.String,com.google.android.exoplayer2.upstream.cache.Cache.Listener)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"addListener(String, Cache.Listener)","url":"addListener(java.lang.String,com.google.android.exoplayer2.upstream.cache.Cache.Listener)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"addListener(TimeBar.OnScrubListener)","url":"addListener(com.google.android.exoplayer2.ui.TimeBar.OnScrubListener)"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar","l":"addListener(TimeBar.OnScrubListener)","url":"addListener(com.google.android.exoplayer2.ui.TimeBar.OnScrubListener)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"addMediaItem(int, MediaItem)","url":"addMediaItem(int,com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"addMediaItem(int, MediaItem)","url":"addMediaItem(int,com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"addMediaItem(MediaItem)","url":"addMediaItem(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"addMediaItem(MediaItem)","url":"addMediaItem(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"addMediaItems(int, List)","url":"addMediaItems(int,java.util.List)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addMediaItems(int, List)","url":"addMediaItems(int,java.util.List)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"addMediaItems(int, List)","url":"addMediaItems(int,java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"addMediaItems(int, List)","url":"addMediaItems(int,java.util.List)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"addMediaItems(List)","url":"addMediaItems(java.util.List)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"addMediaItems(List)","url":"addMediaItems(java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.AddMediaItems","l":"AddMediaItems(String, MediaSource...)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"addMediaSource(int, MediaSource, Handler, Runnable)","url":"addMediaSource(int,com.google.android.exoplayer2.source.MediaSource,android.os.Handler,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"addMediaSource(int, MediaSource)","url":"addMediaSource(int,com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addMediaSource(int, MediaSource)","url":"addMediaSource(int,com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"addMediaSource(int, MediaSource)","url":"addMediaSource(int,com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"addMediaSource(int, MediaSource)","url":"addMediaSource(int,com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"addMediaSource(MediaSource, Handler, Runnable)","url":"addMediaSource(com.google.android.exoplayer2.source.MediaSource,android.os.Handler,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"addMediaSource(MediaSource)","url":"addMediaSource(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addMediaSource(MediaSource)","url":"addMediaSource(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"addMediaSource(MediaSource)","url":"addMediaSource(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"addMediaSource(MediaSource)","url":"addMediaSource(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"addMediaSources(Collection, Handler, Runnable)","url":"addMediaSources(java.util.Collection,android.os.Handler,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"addMediaSources(Collection)","url":"addMediaSources(java.util.Collection)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"addMediaSources(int, Collection, Handler, Runnable)","url":"addMediaSources(int,java.util.Collection,android.os.Handler,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"addMediaSources(int, Collection)","url":"addMediaSources(int,java.util.Collection)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"addMediaSources(int, List)","url":"addMediaSources(int,java.util.List)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addMediaSources(int, List)","url":"addMediaSources(int,java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"addMediaSources(int, List)","url":"addMediaSources(int,java.util.List)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"addMediaSources(List)","url":"addMediaSources(java.util.List)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addMediaSources(List)","url":"addMediaSources(java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"addMediaSources(List)","url":"addMediaSources(java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"addMediaSources(MediaSource...)","url":"addMediaSources(com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.MetadataComponent","l":"addMetadataOutput(MetadataOutput)","url":"addMetadataOutput(com.google.android.exoplayer2.metadata.MetadataOutput)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addMetadataOutput(MetadataOutput)","url":"addMetadataOutput(com.google.android.exoplayer2.metadata.MetadataOutput)"},{"p":"com.google.android.exoplayer2.text.span","c":"SpanUtil","l":"addOrReplaceSpan(Spannable, Object, int, int, int)","url":"addOrReplaceSpan(android.text.Spannable,java.lang.Object,int,int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock","l":"addPendingHandlerMessage(FakeClock.HandlerMessage)","url":"addPendingHandlerMessage(com.google.android.exoplayer2.testutil.FakeClock.HandlerMessage)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"addPlaylistItem(int, MediaItem)","url":"addPlaylistItem(int,androidx.media2.common.MediaItem)"},{"p":"com.google.android.exoplayer2.util","c":"SlidingPercentile","l":"addSample(int, float)","url":"addSample(int,float)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"addTextLanguagesToSelection(boolean, String...)","url":"addTextLanguagesToSelection(boolean,java.lang.String...)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.TextComponent","l":"addTextOutput(TextOutput)","url":"addTextOutput(com.google.android.exoplayer2.text.TextOutput)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addTextOutput(TextOutput)","url":"addTextOutput(com.google.android.exoplayer2.text.TextOutput)"},{"p":"com.google.android.exoplayer2.testutil","c":"Dumper","l":"addTime(String, long)","url":"addTime(java.lang.String,long)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"addTrackSelection(int, DefaultTrackSelector.Parameters)","url":"addTrackSelection(int,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"addTrackSelectionForSingleRenderer(int, int, DefaultTrackSelector.Parameters, List)","url":"addTrackSelectionForSingleRenderer(int,int,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters,java.util.List)"},{"p":"com.google.android.exoplayer2.upstream","c":"BaseDataSource","l":"addTransferListener(TransferListener)","url":"addTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSource","l":"addTransferListener(TransferListener)","url":"addTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSource","l":"addTransferListener(TransferListener)","url":"addTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"DummyDataSource","l":"addTransferListener(TransferListener)","url":"addTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"PriorityDataSource","l":"addTransferListener(TransferListener)","url":"addTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"ResolvingDataSource","l":"addTransferListener(TransferListener)","url":"addTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"StatsDataSource","l":"addTransferListener(TransferListener)","url":"addTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"TeeDataSource","l":"addTransferListener(TransferListener)","url":"addTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"addTransferListener(TransferListener)","url":"addTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesCipherDataSource","l":"addTransferListener(TransferListener)","url":"addTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"addVideoFrameProcessingOffset(long)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"addVideoListener(VideoListener)","url":"addVideoListener(com.google.android.exoplayer2.video.VideoListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addVideoListener(VideoListener)","url":"addVideoListener(com.google.android.exoplayer2.video.VideoListener)"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView","l":"addVideoSurfaceListener(SphericalGLSurfaceView.VideoSurfaceListener)","url":"addVideoSurfaceListener(com.google.android.exoplayer2.video.spherical.SphericalGLSurfaceView.VideoSurfaceListener)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"addVisibilityListener(PlayerControlView.VisibilityListener)","url":"addVisibilityListener(com.google.android.exoplayer2.ui.PlayerControlView.VisibilityListener)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"addVisibilityListener(StyledPlayerControlView.VisibilityListener)","url":"addVisibilityListener(com.google.android.exoplayer2.ui.StyledPlayerControlView.VisibilityListener)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"addWithOverflowDefault(long, long, long)","url":"addWithOverflowDefault(long,long,long)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"AdGroup()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"adGroupCount"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"adGroupIndex"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"adGroupIndex"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"adGroups"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"adGroupTimesUs"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"adIndexInAdGroup"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"adIndexInAdGroup"},{"p":"com.google.android.exoplayer2.video","c":"VideoFrameReleaseHelper","l":"adjustReleaseTime(long)"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"adjustSampleTimestamp(long)"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"adjustTsTimestamp(long)"},{"p":"com.google.android.exoplayer2.ui","c":"AdOverlayInfo","l":"AdOverlayInfo(View, int, String)","url":"%3Cinit%3E(android.view.View,int,java.lang.String)"},{"p":"com.google.android.exoplayer2.ui","c":"AdOverlayInfo","l":"AdOverlayInfo(View, int)","url":"%3Cinit%3E(android.view.View,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"adPlaybackCount"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"adPlaybackState"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"AdPlaybackState(Object, long...)","url":"%3Cinit%3E(java.lang.Object,long...)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"adResumePositionUs"},{"p":"com.google.android.exoplayer2","c":"MediaItem.PlaybackProperties","l":"adsConfiguration"},{"p":"com.google.android.exoplayer2","c":"MediaItem.AdsConfiguration","l":"adsId"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"adsId"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource","l":"AdsMediaSource(MediaSource, DataSpec, Object, MediaSourceFactory, AdsLoader, AdViewProvider)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaSource,com.google.android.exoplayer2.upstream.DataSpec,java.lang.Object,com.google.android.exoplayer2.source.MediaSourceFactory,com.google.android.exoplayer2.source.ads.AdsLoader,com.google.android.exoplayer2.ui.AdViewProvider)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.AdsConfiguration","l":"adTagUri"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"ADTS"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsExtractor","l":"AdtsExtractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsExtractor","l":"AdtsExtractor(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsReader","l":"AdtsReader(boolean, String)","url":"%3Cinit%3E(boolean,java.lang.String)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsReader","l":"AdtsReader(boolean)","url":"%3Cinit%3E(boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"advancePeekPosition(int, boolean)","url":"advancePeekPosition(int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"advancePeekPosition(int, boolean)","url":"advancePeekPosition(int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"advancePeekPosition(int, boolean)","url":"advancePeekPosition(int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"advancePeekPosition(int, boolean)","url":"advancePeekPosition(int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"advancePeekPosition(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"advancePeekPosition(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"advancePeekPosition(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"advancePeekPosition(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock","l":"advanceTime(long)"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesCipherDataSink","l":"AesCipherDataSink(byte[], DataSink, byte[])","url":"%3Cinit%3E(byte[],com.google.android.exoplayer2.upstream.DataSink,byte[])"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesCipherDataSink","l":"AesCipherDataSink(byte[], DataSink)","url":"%3Cinit%3E(byte[],com.google.android.exoplayer2.upstream.DataSink)"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesCipherDataSource","l":"AesCipherDataSource(byte[], DataSource)","url":"%3Cinit%3E(byte[],com.google.android.exoplayer2.upstream.DataSource)"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesFlushingCipher","l":"AesFlushingCipher(int, byte[], long, long)","url":"%3Cinit%3E(int,byte[],long,long)"},{"p":"com.google.android.exoplayer2.robolectric","c":"ShadowMediaCodecConfig","l":"after()"},{"p":"com.google.android.exoplayer2.testutil","c":"HttpDataSourceTestEnv","l":"after()"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"albumArtist"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"albumTitle"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"alignVideoSizeV21(int, int)","url":"alignVideoSizeV21(int,int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"ALL_PLAYBACK_ACTIONS"},{"p":"com.google.android.exoplayer2.upstream","c":"Allocator","l":"allocate()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultAllocator","l":"allocate()"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection.AdaptationCheckpoint","l":"allocatedBandwidth"},{"p":"com.google.android.exoplayer2.upstream","c":"Allocation","l":"Allocation(byte[], int)","url":"%3Cinit%3E(byte[],int)"},{"p":"com.google.android.exoplayer2","c":"C","l":"ALLOW_CAPTURE_BY_ALL"},{"p":"com.google.android.exoplayer2","c":"C","l":"ALLOW_CAPTURE_BY_NONE"},{"p":"com.google.android.exoplayer2","c":"C","l":"ALLOW_CAPTURE_BY_SYSTEM"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"allowAudioMixedChannelCountAdaptiveness"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"allowAudioMixedMimeTypeAdaptiveness"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"allowAudioMixedSampleRateAdaptiveness"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes","l":"allowedCapturePolicy"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm.LicenseServer","l":"allowingSchemeDatas(List...)","url":"allowingSchemeDatas(java.util.List...)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"allowMultipleAdaptiveSelections"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"allowVideoMixedMimeTypeAdaptiveness"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"allowVideoNonSeamlessAdaptiveness"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"allSamplesAreSyncSamples(String, String)","url":"allSamplesAreSyncSamples(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"AMR"},{"p":"com.google.android.exoplayer2.extractor.amr","c":"AmrExtractor","l":"AmrExtractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.amr","c":"AmrExtractor","l":"AmrExtractor(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"AnalyticsCollector(Clock)","url":"%3Cinit%3E(com.google.android.exoplayer2.util.Clock)"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"ANCHOR_TYPE_END"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"ANCHOR_TYPE_MIDDLE"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"ANCHOR_TYPE_START"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject.AndSpanFlags","l":"andFlags(int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ApicFrame","l":"ApicFrame(String, String, int, byte[])","url":"%3Cinit%3E(java.lang.String,java.lang.String,int,byte[])"},{"p":"com.google.android.exoplayer2.ext.cast","c":"DefaultCastOptionsProvider","l":"APP_ID_DEFAULT_RECEIVER_WITH_DRM"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"append(List)","url":"append(java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData","l":"appendReadAction(Runnable)","url":"appendReadAction(java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData","l":"appendReadData(byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData","l":"appendReadData(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData","l":"appendReadError(IOException)","url":"appendReadError(java.io.IOException)"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","c":"AppInfoTable","l":"AppInfoTable(int, String)","url":"%3Cinit%3E(int,java.lang.String)"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","c":"AppInfoTableDecoder","l":"AppInfoTableDecoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_AIT"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_CAMERA_MOTION"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_CEA608"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_CEA708"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_DVBSUBS"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_EMSG"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_EXIF"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_ICY"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_ID3"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","c":"AppInfoTableDecoder","l":"APPLICATION_INFORMATION_TABLE_ID"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_M3U8"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_MATROSKA"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_MP4"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_MP4CEA608"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_MP4VTT"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_MPD"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_PGS"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_RAWCC"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_RTSP"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_SCTE35"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_SS"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_SUBRIP"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_TTML"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_TX3G"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_VOBSUB"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_WEBM"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"apply(Action)","url":"apply(com.google.android.exoplayer2.testutil.Action)"},{"p":"com.google.android.exoplayer2.testutil","c":"AdditionalFailureInfo","l":"apply(Statement, Description)","url":"apply(org.junit.runners.model.Statement,org.junit.runner.Description)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"applyContentMetadataMutations(String, ContentMetadataMutations)","url":"applyContentMetadataMutations(java.lang.String,com.google.android.exoplayer2.upstream.cache.ContentMetadataMutations)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"applyContentMetadataMutations(String, ContentMetadataMutations)","url":"applyContentMetadataMutations(java.lang.String,com.google.android.exoplayer2.upstream.cache.ContentMetadataMutations)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink.AudioProcessorChain","l":"applyPlaybackParameters(PlaybackParameters)","url":"applyPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink.DefaultAudioProcessorChain","l":"applyPlaybackParameters(PlaybackParameters)","url":"applyPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink.AudioProcessorChain","l":"applySkipSilenceEnabled(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink.DefaultAudioProcessorChain","l":"applySkipSilenceEnabled(boolean)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.AppManagedProvider","l":"AppManagedProvider(ExoMediaDrm)","url":"%3Cinit%3E(com.google.android.exoplayer2.drm.ExoMediaDrm)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"areEqual(Object, Object)","url":"areEqual(java.lang.Object,java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"artist"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"artworkData"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"artworkUri"},{"p":"com.google.android.exoplayer2","c":"C","l":"ASCII_NAME"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil","l":"ASPECT_RATIO_IDC_VALUES"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout","l":"AspectRatioFrameLayout(Context, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout","l":"AspectRatioFrameLayout(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertAdGroupCounts(Timeline, int...)","url":"assertAdGroupCounts(com.google.android.exoplayer2.Timeline,int...)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts","l":"assertAllBehaviors(ExtractorAsserts.ExtractorFactory, String, String)","url":"assertAllBehaviors(com.google.android.exoplayer2.testutil.ExtractorAsserts.ExtractorFactory,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts","l":"assertAllBehaviors(ExtractorAsserts.ExtractorFactory, String)","url":"assertAllBehaviors(com.google.android.exoplayer2.testutil.ExtractorAsserts.ExtractorFactory,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts","l":"assertBehavior(ExtractorAsserts.ExtractorFactory, String, ExtractorAsserts.AssertionConfig, ExtractorAsserts.SimulationConfig)","url":"assertBehavior(com.google.android.exoplayer2.testutil.ExtractorAsserts.ExtractorFactory,java.lang.String,com.google.android.exoplayer2.testutil.ExtractorAsserts.AssertionConfig,com.google.android.exoplayer2.testutil.ExtractorAsserts.SimulationConfig)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts","l":"assertBehavior(ExtractorAsserts.ExtractorFactory, String, ExtractorAsserts.SimulationConfig)","url":"assertBehavior(com.google.android.exoplayer2.testutil.ExtractorAsserts.ExtractorFactory,java.lang.String,com.google.android.exoplayer2.testutil.ExtractorAsserts.SimulationConfig)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"assertBitmapsAreSimilar(Bitmap, Bitmap, double)","url":"assertBitmapsAreSimilar(android.graphics.Bitmap,android.graphics.Bitmap,double)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"assertBufferInfosEqual(MediaCodec.BufferInfo, MediaCodec.BufferInfo)","url":"assertBufferInfosEqual(android.media.MediaCodec.BufferInfo,android.media.MediaCodec.BufferInfo)"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts","l":"assertCachedData(Cache, CacheAsserts.RequestSet)","url":"assertCachedData(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.testutil.CacheAsserts.RequestSet)"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts","l":"assertCachedData(Cache, FakeDataSet)","url":"assertCachedData(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.testutil.FakeDataSet)"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts","l":"assertCacheEmpty(Cache)","url":"assertCacheEmpty(com.google.android.exoplayer2.upstream.cache.Cache)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"assertCompletedManifestLoads(Integer...)","url":"assertCompletedManifestLoads(java.lang.Integer...)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"assertCompletedMediaPeriodLoads(MediaSource.MediaPeriodId...)","url":"assertCompletedMediaPeriodLoads(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId...)"},{"p":"com.google.android.exoplayer2.testutil","c":"DecoderCountersUtil","l":"assertConsecutiveDroppedBufferLimit(String, DecoderCounters, int)","url":"assertConsecutiveDroppedBufferLimit(java.lang.String,com.google.android.exoplayer2.decoder.DecoderCounters,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts","l":"assertDataCached(Cache, DataSpec, byte[])","url":"assertDataCached(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.DataSpec,byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"assertDataSourceContent(DataSource, DataSpec, byte[], boolean)","url":"assertDataSourceContent(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,byte[],boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"DecoderCountersUtil","l":"assertDroppedBufferLimit(String, DecoderCounters, int)","url":"assertDroppedBufferLimit(java.lang.String,com.google.android.exoplayer2.decoder.DecoderCounters,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertEmpty(Timeline)","url":"assertEmpty(com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertEqualNextWindowIndices(Timeline, Timeline, int, boolean)","url":"assertEqualNextWindowIndices(com.google.android.exoplayer2.Timeline,com.google.android.exoplayer2.Timeline,int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertEqualPreviousWindowIndices(Timeline, Timeline, int, boolean)","url":"assertEqualPreviousWindowIndices(com.google.android.exoplayer2.Timeline,com.google.android.exoplayer2.Timeline,int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertEqualsExceptIdsAndManifest(Timeline, Timeline)","url":"assertEqualsExceptIdsAndManifest(com.google.android.exoplayer2.Timeline,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.testutil","c":"DefaultRenderersFactoryAsserts","l":"assertExtensionRendererCreated(Class, int)","url":"assertExtensionRendererCreated(java.lang.Class,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaPeriodAsserts","l":"assertGetStreamKeysAndManifestFilterIntegration(MediaPeriodAsserts.FilterableManifestMediaPeriodFactory, T, int, String)","url":"assertGetStreamKeysAndManifestFilterIntegration(com.google.android.exoplayer2.testutil.MediaPeriodAsserts.FilterableManifestMediaPeriodFactory,T,int,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaPeriodAsserts","l":"assertGetStreamKeysAndManifestFilterIntegration(MediaPeriodAsserts.FilterableManifestMediaPeriodFactory, T)","url":"assertGetStreamKeysAndManifestFilterIntegration(com.google.android.exoplayer2.testutil.MediaPeriodAsserts.FilterableManifestMediaPeriodFactory,T)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayerLibraryInfo","l":"ASSERTIONS_ENABLED"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"assertMediaItemsTransitionedSame(MediaItem...)","url":"assertMediaItemsTransitionedSame(com.google.android.exoplayer2.MediaItem...)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"assertMediaItemsTransitionReasonsEqual(Integer...)","url":"assertMediaItemsTransitionReasonsEqual(java.lang.Integer...)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"assertMediaPeriodCreated(MediaSource.MediaPeriodId)","url":"assertMediaPeriodCreated(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertNextWindowIndices(Timeline, int, boolean, int...)","url":"assertNextWindowIndices(com.google.android.exoplayer2.Timeline,int,boolean,int...)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"assertNoPositionDiscontinuities()"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"assertNoTimelineChange()"},{"p":"com.google.android.exoplayer2.testutil","c":"DumpFileAsserts","l":"assertOutput(Context, Dumper.Dumpable, String, String)","url":"assertOutput(android.content.Context,com.google.android.exoplayer2.testutil.Dumper.Dumpable,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"DumpFileAsserts","l":"assertOutput(Context, Dumper.Dumpable, String)","url":"assertOutput(android.content.Context,com.google.android.exoplayer2.testutil.Dumper.Dumpable,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"DumpFileAsserts","l":"assertOutput(Context, String, String, String)","url":"assertOutput(android.content.Context,java.lang.String,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"DumpFileAsserts","l":"assertOutput(Context, String, String)","url":"assertOutput(android.content.Context,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"assertPassed(DecoderCounters, DecoderCounters)","url":"assertPassed(com.google.android.exoplayer2.decoder.DecoderCounters,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertPeriodCounts(Timeline, int...)","url":"assertPeriodCounts(com.google.android.exoplayer2.Timeline,int...)"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertPeriodDurations(Timeline, long...)","url":"assertPeriodDurations(com.google.android.exoplayer2.Timeline,long...)"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertPeriodEqualsExceptIds(Timeline.Period, Timeline.Period)","url":"assertPeriodEqualsExceptIds(com.google.android.exoplayer2.Timeline.Period,com.google.android.exoplayer2.Timeline.Period)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"assertPlaybackStatesEqual(Integer...)","url":"assertPlaybackStatesEqual(java.lang.Integer...)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"assertPlayedPeriodIndices(Integer...)","url":"assertPlayedPeriodIndices(java.lang.Integer...)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"assertPositionDiscontinuityReasonsEqual(Integer...)","url":"assertPositionDiscontinuityReasonsEqual(java.lang.Integer...)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"assertPrepareAndReleaseAllPeriods()"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertPreviousWindowIndices(Timeline, int, boolean, int...)","url":"assertPreviousWindowIndices(com.google.android.exoplayer2.Timeline,int,boolean,int...)"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts","l":"assertReadData(DataSource, DataSpec, byte[])","url":"assertReadData(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"assertReleased()"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestDownloadManagerListener","l":"assertRemoved(String)","url":"assertRemoved(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"assertSample(int, byte[], long, int, TrackOutput.CryptoData)","url":"assertSample(int,byte[],long,int,com.google.android.exoplayer2.extractor.TrackOutput.CryptoData)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"assertSampleCount(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"DecoderCountersUtil","l":"assertSkippedOutputBufferCount(String, DecoderCounters, int)","url":"assertSkippedOutputBufferCount(java.lang.String,com.google.android.exoplayer2.decoder.DecoderCounters,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts","l":"assertSniff(Extractor, FakeExtractorInput, boolean)","url":"assertSniff(com.google.android.exoplayer2.extractor.Extractor,com.google.android.exoplayer2.testutil.FakeExtractorInput,boolean)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestDownloadManagerListener","l":"assertState(String, int)","url":"assertState(java.lang.String,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"assertThat(Spanned)","url":"assertThat(android.text.Spanned)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"assertTimelineChange()"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"assertTimelineChangeBlocking()"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"assertTimelineChangeReasonsEqual(Integer...)","url":"assertTimelineChangeReasonsEqual(java.lang.Integer...)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"assertTimelinesSame(Timeline...)","url":"assertTimelinesSame(com.google.android.exoplayer2.Timeline...)"},{"p":"com.google.android.exoplayer2.testutil","c":"DecoderCountersUtil","l":"assertTotalBufferCount(String, DecoderCounters, int, int)","url":"assertTotalBufferCount(java.lang.String,com.google.android.exoplayer2.decoder.DecoderCounters,int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaPeriodAsserts","l":"assertTrackGroups(MediaPeriod, TrackGroupArray)","url":"assertTrackGroups(com.google.android.exoplayer2.source.MediaPeriod,com.google.android.exoplayer2.source.TrackGroupArray)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"assertTrackGroupsEqual(TrackGroupArray)","url":"assertTrackGroupsEqual(com.google.android.exoplayer2.source.TrackGroupArray)"},{"p":"com.google.android.exoplayer2.testutil","c":"DecoderCountersUtil","l":"assertVideoFrameProcessingOffsetSampleCount(String, DecoderCounters, int, int)","url":"assertVideoFrameProcessingOffsetSampleCount(java.lang.String,com.google.android.exoplayer2.decoder.DecoderCounters,int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertWindowEqualsExceptUidAndManifest(Timeline.Window, Timeline.Window)","url":"assertWindowEqualsExceptUidAndManifest(com.google.android.exoplayer2.Timeline.Window,com.google.android.exoplayer2.Timeline.Window)"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertWindowIsDynamic(Timeline, boolean...)","url":"assertWindowIsDynamic(com.google.android.exoplayer2.Timeline,boolean...)"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertWindowTags(Timeline, Object...)","url":"assertWindowTags(com.google.android.exoplayer2.Timeline,java.lang.Object...)"},{"p":"com.google.android.exoplayer2.upstream","c":"AssetDataSource","l":"AssetDataSource(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.upstream","c":"AssetDataSource.AssetDataSourceException","l":"AssetDataSourceException(IOException)","url":"%3Cinit%3E(java.io.IOException)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Period","l":"assetIdentifier"},{"p":"com.google.android.exoplayer2.util","c":"AtomicFile","l":"AtomicFile(File)","url":"%3Cinit%3E(java.io.File)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"RangedUri","l":"attemptMerge(RangedUri, String)","url":"attemptMerge(com.google.android.exoplayer2.source.dash.manifest.RangedUri,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil.Attribute","l":"Attribute(int, int)","url":"%3Cinit%3E(int,int)"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_AAC"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_AC3"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_AC4"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_ALAC"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_ALAW"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_AMR"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_AMR_NB"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_AMR_WB"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_DTS"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_DTS_EXPRESS"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_DTS_HD"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_E_AC3"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_E_AC3_JOC"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_FLAC"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"AUDIO_FORMAT"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_MATROSKA"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_MLAW"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_MP4"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_MPEG"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_MPEG_L1"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_MPEG_L2"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_MPEGH_MHA1"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_MPEGH_MHM1"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_MSGSM"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AUDIO_OBJECT_TYPE_AAC_ELD"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AUDIO_OBJECT_TYPE_AAC_ER_BSAC"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AUDIO_OBJECT_TYPE_AAC_LC"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AUDIO_OBJECT_TYPE_AAC_PS"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AUDIO_OBJECT_TYPE_AAC_SBR"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AUDIO_OBJECT_TYPE_AAC_XHE"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_OGG"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_OPUS"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_RAW"},{"p":"com.google.android.exoplayer2","c":"C","l":"AUDIO_SESSION_ID_UNSET"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"AUDIO_STREAM"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"AUDIO_STREAM_MASK"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_TRUEHD"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_UNKNOWN"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_VORBIS"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_WAV"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_WEBM"},{"p":"com.google.android.exoplayer2.audio","c":"AudioCapabilities","l":"AudioCapabilities(int[], int)","url":"%3Cinit%3E(int[],int)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioCapabilitiesReceiver","l":"AudioCapabilitiesReceiver(Context, AudioCapabilitiesReceiver.Listener)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.audio.AudioCapabilitiesReceiver.Listener)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener.EventDispatcher","l":"audioCodecError(Exception)","url":"audioCodecError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2","c":"C","l":"AUDIOFOCUS_GAIN"},{"p":"com.google.android.exoplayer2","c":"C","l":"AUDIOFOCUS_GAIN_TRANSIENT"},{"p":"com.google.android.exoplayer2","c":"C","l":"AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE"},{"p":"com.google.android.exoplayer2","c":"C","l":"AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK"},{"p":"com.google.android.exoplayer2","c":"C","l":"AUDIOFOCUS_NONE"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor.AudioFormat","l":"AudioFormat(int, int, int)","url":"%3Cinit%3E(int,int,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"audioFormatHistory"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry.VariantInfo","l":"audioGroupId"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Variant","l":"audioGroupId"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"audios"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener.EventDispatcher","l":"audioSinkError(Exception)","url":"audioSinkError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.AudioTrackScore","l":"AudioTrackScore(Format, DefaultTrackSelector.Parameters, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters,int)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.InitializationException","l":"audioTrackState"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"autoReturn"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.Event","l":"autoReturn"},{"p":"com.google.android.exoplayer2.audio","c":"AuxEffectInfo","l":"AuxEffectInfo(int, float)","url":"%3Cinit%3E(int,float)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"availabilityStartTimeMs"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"availNum"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.Event","l":"availNum"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"availsExpected"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.Event","l":"availsExpected"},{"p":"com.google.android.exoplayer2","c":"Format","l":"averageBitrate"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry.VariantInfo","l":"averageBitrate"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"backgroundColor"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"backgroundJoiningCount"},{"p":"com.google.android.exoplayer2.upstream","c":"BandwidthMeter.EventListener.EventDispatcher","l":"bandwidthSample(int, long, long)","url":"bandwidthSample(int,long,long)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"BAR_GRAVITY_BOTTOM"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"BAR_GRAVITY_CENTER"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"BASE_TYPE_APPLICATION"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"BASE_TYPE_AUDIO"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"BASE_TYPE_IMAGE"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"BASE_TYPE_TEXT"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"BASE_TYPE_VIDEO"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"BaseAudioProcessor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"BaseDataSource","l":"BaseDataSource(boolean)","url":"%3Cinit%3E(boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.BaseFactory","l":"BaseFactory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunk","l":"BaseMediaChunk(DataSource, DataSpec, Format, int, Object, long, long, long, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,com.google.android.exoplayer2.Format,int,java.lang.Object,long,long,long,long,long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunkIterator","l":"BaseMediaChunkIterator(long, long)","url":"%3Cinit%3E(long,long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunkOutput","l":"BaseMediaChunkOutput(int[], SampleQueue[])","url":"%3Cinit%3E(int[],com.google.android.exoplayer2.source.SampleQueue[])"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"BaseMediaSource()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"BasePlayer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"BaseRenderer(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"BaseTrackSelection(TrackGroup, int...)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroup,int...)"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"BaseTrackSelection(TrackGroup, int[], int)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroup,int[],int)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylist","l":"baseUri"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser.RepresentationInfo","l":"baseUrl"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"baseUrl"},{"p":"com.google.android.exoplayer2.robolectric","c":"ShadowMediaCodecConfig","l":"before()"},{"p":"com.google.android.exoplayer2.testutil","c":"HttpDataSourceTestEnv","l":"before()"},{"p":"com.google.android.exoplayer2.util","c":"TraceUtil","l":"beginSection(String)","url":"beginSection(java.lang.String)"},{"p":"com.google.android.exoplayer2.source","c":"BehindLiveWindowException","l":"BehindLiveWindowException()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.analytics","c":"DefaultPlaybackSessionManager","l":"belongsToSession(AnalyticsListener.EventTime, String)","url":"belongsToSession(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackSessionManager","l":"belongsToSession(AnalyticsListener.EventTime, String)","url":"belongsToSession(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"binaryElement(int, int, ExtractorInput)","url":"binaryElement(int,int,com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"binaryElement(int, int, ExtractorInput)","url":"binaryElement(int,int,com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"BinaryFrame","l":"BinaryFrame(String, byte[])","url":"%3Cinit%3E(java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"binarySearchCeil(int[], int, boolean, boolean)","url":"binarySearchCeil(int[],int,boolean,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"binarySearchCeil(List>, T, boolean, boolean)","url":"binarySearchCeil(java.util.List,T,boolean,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"binarySearchCeil(long[], long, boolean, boolean)","url":"binarySearchCeil(long[],long,boolean,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"binarySearchFloor(int[], int, boolean, boolean)","url":"binarySearchFloor(int[],int,boolean,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"binarySearchFloor(List>, T, boolean, boolean)","url":"binarySearchFloor(java.util.List,T,boolean,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"binarySearchFloor(long[], long, boolean, boolean)","url":"binarySearchFloor(long[],long,boolean,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"binarySearchFloor(LongArray, long, boolean, boolean)","url":"binarySearchFloor(com.google.android.exoplayer2.util.LongArray,long,boolean,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"BinarySearchSeeker(BinarySearchSeeker.SeekTimestampConverter, BinarySearchSeeker.TimestampSeeker, long, long, long, long, long, long, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.BinarySearchSeeker.SeekTimestampConverter,com.google.android.exoplayer2.extractor.BinarySearchSeeker.TimestampSeeker,long,long,long,long,long,long,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.BinarySearchSeekMap","l":"BinarySearchSeekMap(BinarySearchSeeker.SeekTimestampConverter, long, long, long, long, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.BinarySearchSeeker.SeekTimestampConverter,long,long,long,long,long,long)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil.Attribute","l":"bind()"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil.Uniform","l":"bind()"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"bitmap"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"bitmapHeight"},{"p":"com.google.android.exoplayer2","c":"Format","l":"bitrate"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil.Header","l":"bitrate"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"bitrate"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.VorbisIdHeader","l":"bitrateMaximum"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.VorbisIdHeader","l":"bitrateMinimum"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.VorbisIdHeader","l":"bitrateNominal"},{"p":"com.google.android.exoplayer2","c":"C","l":"BITS_PER_BYTE"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisBitArray","l":"bitsLeft()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"bitsLeft()"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"bitsPerSample"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"bitsPerSampleLookupKey"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util.SyncFrameInfo","l":"bitstreamVersion"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"blacklist(int, long)","url":"blacklist(int,long)"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"blacklist(int, long)","url":"blacklist(int,long)"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"blacklist(int, long)","url":"blacklist(int,long)"},{"p":"com.google.android.exoplayer2.util","c":"ConditionVariable","l":"block()"},{"p":"com.google.android.exoplayer2.util","c":"ConditionVariable","l":"block(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.Mode","l":"blockFlag"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.VorbisIdHeader","l":"blockSize0"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.VorbisIdHeader","l":"blockSize1"},{"p":"com.google.android.exoplayer2.util","c":"ConditionVariable","l":"blockUninterruptible()"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"blockUntilActionScheduleFinished(long)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"blockUntilDelivered()"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"blockUntilDelivered(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"blockUntilEnded(long)"},{"p":"com.google.android.exoplayer2.util","c":"RunnableFutureTask","l":"blockUntilFinished()"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestDownloadManagerListener","l":"blockUntilIdle()"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestDownloadManagerListener","l":"blockUntilIdleAndThrowAnyFailure()"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestDownloadManagerListener","l":"blockUntilInitialized()"},{"p":"com.google.android.exoplayer2.util","c":"RunnableFutureTask","l":"blockUntilStarted()"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"blockUntilStopped(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity.HostedTest","l":"blockUntilStopped(long)"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.PpsData","l":"bottomFieldPicOrderInFramePresentFlag"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"breakDurationUs"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.Event","l":"breakDurationUs"},{"p":"com.google.android.exoplayer2","c":"C","l":"BUFFER_FLAG_DECODE_ONLY"},{"p":"com.google.android.exoplayer2","c":"C","l":"BUFFER_FLAG_ENCRYPTED"},{"p":"com.google.android.exoplayer2","c":"C","l":"BUFFER_FLAG_END_OF_STREAM"},{"p":"com.google.android.exoplayer2","c":"C","l":"BUFFER_FLAG_HAS_SUPPLEMENTAL_DATA"},{"p":"com.google.android.exoplayer2","c":"C","l":"BUFFER_FLAG_KEY_FRAME"},{"p":"com.google.android.exoplayer2","c":"C","l":"BUFFER_FLAG_LAST_SAMPLE"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"BUFFER_REPLACEMENT_MODE_DIRECT"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"BUFFER_REPLACEMENT_MODE_DISABLED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"BUFFER_REPLACEMENT_MODE_NORMAL"},{"p":"com.google.android.exoplayer2.decoder","c":"Buffer","l":"Buffer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl.Builder","l":"build()"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl.Builder","l":"build()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"build()"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"build()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"build()"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"build()"},{"p":"com.google.android.exoplayer2","c":"Player.Commands.Builder","l":"build()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"build()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.TestResource.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"build()"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts.AssertionConfig.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"build()"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"build()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder","l":"build()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.util","c":"ExoFlags.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager.Builder","l":"build(MediaDrmCallback)","url":"build(com.google.android.exoplayer2.drm.MediaDrmCallback)"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"buildAacLcAudioSpecificConfig(int, int)","url":"buildAacLcAudioSpecificConfig(int,int)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildAdaptationSet(int, int, List, List, List, List)","url":"buildAdaptationSet(int,int,java.util.List,java.util.List,java.util.List,java.util.List)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"buildAddDownloadIntent(Context, Class, DownloadRequest, boolean)","url":"buildAddDownloadIntent(android.content.Context,java.lang.Class,com.google.android.exoplayer2.offline.DownloadRequest,boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"buildAddDownloadIntent(Context, Class, DownloadRequest, int, boolean)","url":"buildAddDownloadIntent(android.content.Context,java.lang.Class,com.google.android.exoplayer2.offline.DownloadRequest,int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"buildAssetUri(String)","url":"buildAssetUri(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"buildAudioRenderers(Context, int, MediaCodecSelector, boolean, AudioSink, Handler, AudioRendererEventListener, ArrayList)","url":"buildAudioRenderers(android.content.Context,int,com.google.android.exoplayer2.mediacodec.MediaCodecSelector,boolean,com.google.android.exoplayer2.audio.AudioSink,android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,java.util.ArrayList)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"buildAudioSink(Context, boolean, boolean, boolean)","url":"buildAudioSink(android.content.Context,boolean,boolean,boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"buildAudioSpecificConfig(int, int, int)","url":"buildAudioSpecificConfig(int,int,int)"},{"p":"com.google.android.exoplayer2.util","c":"CodecSpecificDataUtil","l":"buildAvcCodecString(int, int, int)","url":"buildAvcCodecString(int,int,int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheKeyFactory","l":"buildCacheKey(DataSpec)","url":"buildCacheKey(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"buildCameraMotionRenderers(Context, int, ArrayList)","url":"buildCameraMotionRenderers(android.content.Context,int,java.util.ArrayList)"},{"p":"com.google.android.exoplayer2.util","c":"CodecSpecificDataUtil","l":"buildCea708InitializationData(boolean)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashUtil","l":"buildDataSpec(Representation, RangedUri, int)","url":"buildDataSpec(com.google.android.exoplayer2.source.dash.manifest.Representation,com.google.android.exoplayer2.source.dash.manifest.RangedUri,int)"},{"p":"com.google.android.exoplayer2.ui","c":"DownloadNotificationHelper","l":"buildDownloadCompletedNotification(Context, int, PendingIntent, String)","url":"buildDownloadCompletedNotification(android.content.Context,int,android.app.PendingIntent,java.lang.String)"},{"p":"com.google.android.exoplayer2.ui","c":"DownloadNotificationHelper","l":"buildDownloadFailedNotification(Context, int, PendingIntent, String)","url":"buildDownloadFailedNotification(android.content.Context,int,android.app.PendingIntent,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"buildDrmSessionManager()"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"Player.Commands.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.TestResource.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts.AssertionConfig.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.util","c":"ExoFlags.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"Builder(Context, ExtractorsFactory)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.extractor.ExtractorsFactory)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"Builder(Context, int, String, PlayerNotificationManager.MediaDescriptionAdapter)","url":"%3Cinit%3E(android.content.Context,int,java.lang.String,com.google.android.exoplayer2.ui.PlayerNotificationManager.MediaDescriptionAdapter)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"Builder(Context, Renderer...)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.Renderer...)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"Builder(Context, RenderersFactory, ExtractorsFactory)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.RenderersFactory,com.google.android.exoplayer2.extractor.ExtractorsFactory)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"Builder(Context, RenderersFactory, TrackSelector, MediaSourceFactory, LoadControl, BandwidthMeter, AnalyticsCollector)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.RenderersFactory,com.google.android.exoplayer2.trackselection.TrackSelector,com.google.android.exoplayer2.source.MediaSourceFactory,com.google.android.exoplayer2.LoadControl,com.google.android.exoplayer2.upstream.BandwidthMeter,com.google.android.exoplayer2.analytics.AnalyticsCollector)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"Builder(Context, RenderersFactory)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.RenderersFactory)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"Builder(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"Builder(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"Builder(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"Builder(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter.Builder","l":"Builder(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"Builder(Renderer[], TrackSelector, MediaSourceFactory, LoadControl, BandwidthMeter)","url":"%3Cinit%3E(com.google.android.exoplayer2.Renderer[],com.google.android.exoplayer2.trackselection.TrackSelector,com.google.android.exoplayer2.source.MediaSourceFactory,com.google.android.exoplayer2.LoadControl,com.google.android.exoplayer2.upstream.BandwidthMeter)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest.Builder","l":"Builder(String, Uri)","url":"%3Cinit%3E(java.lang.String,android.net.Uri)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"Builder(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildEvent(String, String, long, long, byte[])","url":"buildEvent(java.lang.String,java.lang.String,long,long,byte[])"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildEventStream(String, String, long, long[], EventMessage[])","url":"buildEventStream(java.lang.String,java.lang.String,long,long[],com.google.android.exoplayer2.metadata.emsg.EventMessage[])"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"buildExoPlayer(HostActivity, Surface, MappingTrackSelector)","url":"buildExoPlayer(com.google.android.exoplayer2.testutil.HostActivity,android.view.Surface,com.google.android.exoplayer2.trackselection.MappingTrackSelector)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildFormat(String, String, int, int, float, int, int, int, String, List, List, String, List, List)","url":"buildFormat(java.lang.String,java.lang.String,int,int,float,int,int,int,java.lang.String,java.util.List,java.util.List,java.lang.String,java.util.List,java.util.List)"},{"p":"com.google.android.exoplayer2.util","c":"CodecSpecificDataUtil","l":"buildHevcCodecStringFromSps(ParsableNalUnitBitArray)","url":"buildHevcCodecStringFromSps(com.google.android.exoplayer2.util.ParsableNalUnitBitArray)"},{"p":"com.google.android.exoplayer2.audio","c":"OpusUtil","l":"buildInitializationData(byte[])"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildMediaPresentationDescription(long, long, long, boolean, long, long, long, long, ProgramInformation, UtcTimingElement, ServiceDescriptionElement, Uri, List)","url":"buildMediaPresentationDescription(long,long,long,boolean,long,long,long,long,com.google.android.exoplayer2.source.dash.manifest.ProgramInformation,com.google.android.exoplayer2.source.dash.manifest.UtcTimingElement,com.google.android.exoplayer2.source.dash.manifest.ServiceDescriptionElement,android.net.Uri,java.util.List)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"buildMetadataRenderers(Context, MetadataOutput, Looper, int, ArrayList)","url":"buildMetadataRenderers(android.content.Context,com.google.android.exoplayer2.metadata.MetadataOutput,android.os.Looper,int,java.util.ArrayList)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"buildMiscellaneousRenderers(Context, Handler, int, ArrayList)","url":"buildMiscellaneousRenderers(android.content.Context,android.os.Handler,int,java.util.ArrayList)"},{"p":"com.google.android.exoplayer2.util","c":"CodecSpecificDataUtil","l":"buildNalUnit(byte[], int, int)","url":"buildNalUnit(byte[],int,int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"buildPauseDownloadsIntent(Context, Class, boolean)","url":"buildPauseDownloadsIntent(android.content.Context,java.lang.Class,boolean)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildPeriod(String, long, List, List, Descriptor)","url":"buildPeriod(java.lang.String,long,java.util.List,java.util.List,com.google.android.exoplayer2.source.dash.manifest.Descriptor)"},{"p":"com.google.android.exoplayer2.ui","c":"DownloadNotificationHelper","l":"buildProgressNotification(Context, int, PendingIntent, String, List)","url":"buildProgressNotification(android.content.Context,int,android.app.PendingIntent,java.lang.String,java.util.List)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"PsshAtomUtil","l":"buildPsshAtom(UUID, byte[])","url":"buildPsshAtom(java.util.UUID,byte[])"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"PsshAtomUtil","l":"buildPsshAtom(UUID, UUID[], byte[])","url":"buildPsshAtom(java.util.UUID,java.util.UUID[],byte[])"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildRangedUri(String, long, long)","url":"buildRangedUri(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpUtil","l":"buildRangeRequestHeader(long, long)","url":"buildRangeRequestHeader(long,long)"},{"p":"com.google.android.exoplayer2.upstream","c":"RawResourceDataSource","l":"buildRawResourceUri(int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"buildRemoveAllDownloadsIntent(Context, Class, boolean)","url":"buildRemoveAllDownloadsIntent(android.content.Context,java.lang.Class,boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"buildRemoveDownloadIntent(Context, Class, String, boolean)","url":"buildRemoveDownloadIntent(android.content.Context,java.lang.Class,java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildRepresentation(DashManifestParser.RepresentationInfo, String, String, ArrayList, ArrayList)","url":"buildRepresentation(com.google.android.exoplayer2.source.dash.manifest.DashManifestParser.RepresentationInfo,java.lang.String,java.lang.String,java.util.ArrayList,java.util.ArrayList)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"buildRequestBuilder(DataSpec)","url":"buildRequestBuilder(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"buildRequestUri(int, int)","url":"buildRequestUri(int,int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"buildResumeDownloadsIntent(Context, Class, boolean)","url":"buildResumeDownloadsIntent(android.content.Context,java.lang.Class,boolean)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildSegmentList(RangedUri, long, long, long, long, List, long, List, long, long)","url":"buildSegmentList(com.google.android.exoplayer2.source.dash.manifest.RangedUri,long,long,long,long,java.util.List,long,java.util.List,long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildSegmentTemplate(RangedUri, long, long, long, long, long, List, long, UrlTemplate, UrlTemplate, long, long)","url":"buildSegmentTemplate(com.google.android.exoplayer2.source.dash.manifest.RangedUri,long,long,long,long,long,java.util.List,long,com.google.android.exoplayer2.source.dash.manifest.UrlTemplate,com.google.android.exoplayer2.source.dash.manifest.UrlTemplate,long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildSegmentTimelineElement(long, long)","url":"buildSegmentTimelineElement(long,long)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"buildSetRequirementsIntent(Context, Class, Requirements, boolean)","url":"buildSetRequirementsIntent(android.content.Context,java.lang.Class,com.google.android.exoplayer2.scheduler.Requirements,boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"buildSetStopReasonIntent(Context, Class, String, int, boolean)","url":"buildSetStopReasonIntent(android.content.Context,java.lang.Class,java.lang.String,int,boolean)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildSingleSegmentBase(RangedUri, long, long, long, long)","url":"buildSingleSegmentBase(com.google.android.exoplayer2.source.dash.manifest.RangedUri,long,long,long,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"buildSource(HostActivity, DrmSessionManager, FrameLayout)","url":"buildSource(com.google.android.exoplayer2.testutil.HostActivity,com.google.android.exoplayer2.drm.DrmSessionManager,android.widget.FrameLayout)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"buildTestData(int, int)","url":"buildTestData(int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"buildTestData(int, Random)","url":"buildTestData(int,java.util.Random)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"buildTestData(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"buildTestString(int, Random)","url":"buildTestString(int,java.util.Random)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"buildTextRenderers(Context, TextOutput, Looper, int, ArrayList)","url":"buildTextRenderers(android.content.Context,com.google.android.exoplayer2.text.TextOutput,android.os.Looper,int,java.util.ArrayList)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"buildTrackSelector(HostActivity)","url":"buildTrackSelector(com.google.android.exoplayer2.testutil.HostActivity)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"buildUpon()"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"buildUpon()"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"buildUpon()"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource","l":"buildUpon()"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"buildUpon()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"buildUpon()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"buildUpon()"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer","l":"buildUpon()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"buildUpon()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"buildUponParameters()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"UrlTemplate","l":"buildUri(String, long, int, long)","url":"buildUri(java.lang.String,long,int,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildUtcTimingElement(String, String)","url":"buildUtcTimingElement(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"buildVideoRenderers(Context, int, MediaCodecSelector, boolean, Handler, VideoRendererEventListener, long, ArrayList)","url":"buildVideoRenderers(android.content.Context,int,com.google.android.exoplayer2.mediacodec.MediaCodecSelector,boolean,android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener,long,java.util.ArrayList)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BundledChunkExtractor","l":"BundledChunkExtractor(Extractor, int, Format)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.Extractor,int,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.source","c":"BundledExtractorsAdapter","l":"BundledExtractorsAdapter(ExtractorsFactory)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.ExtractorsFactory)"},{"p":"com.google.android.exoplayer2.source.hls","c":"BundledHlsMediaChunkExtractor","l":"BundledHlsMediaChunkExtractor(Extractor, Format, TimestampAdjuster)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.Extractor,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.util.TimestampAdjuster)"},{"p":"com.google.android.exoplayer2","c":"BundleListRetriever","l":"BundleListRetriever(List)","url":"%3Cinit%3E(java.util.List)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData.Segment","l":"BY_START_THEN_END_THEN_DIVISOR"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"byteAlign()"},{"p":"com.google.android.exoplayer2.upstream","c":"ByteArrayDataSink","l":"ByteArrayDataSink()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"ByteArrayDataSource","l":"ByteArrayDataSource(byte[])","url":"%3Cinit%3E(byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData.Segment","l":"byteOffset"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.SegmentBase","l":"byteRangeLength"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.SegmentBase","l":"byteRangeOffset"},{"p":"com.google.android.exoplayer2","c":"C","l":"BYTES_PER_FLOAT"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"MlltFrame","l":"bytesBetweenReference"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"MlltFrame","l":"bytesDeviations"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadProgress","l":"bytesDownloaded"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"bytesLeft()"},{"p":"com.google.android.exoplayer2.drm","c":"MediaDrmCallbackException","l":"bytesLoaded"},{"p":"com.google.android.exoplayer2.source","c":"LoadEventInfo","l":"bytesLoaded"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"bytesLoaded()"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"bytesLoaded()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor.AudioFormat","l":"bytesPerFrame"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData.Segment","l":"bytesRead"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceInputStream","l":"bytesRead()"},{"p":"com.google.android.exoplayer2.upstream","c":"BaseDataSource","l":"bytesTransferred(int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"CACHE_IGNORED_REASON_ERROR"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"CACHE_IGNORED_REASON_UNSET_LENGTH"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheWriter","l":"cache()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CachedRegionTracker","l":"CACHED_TO_END"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink","l":"CacheDataSink(Cache, long, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,long,int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink","l":"CacheDataSink(Cache, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink.CacheDataSinkException","l":"CacheDataSinkException(IOException)","url":"%3Cinit%3E(java.io.IOException)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSinkFactory","l":"CacheDataSinkFactory(Cache, long, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,long,int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSinkFactory","l":"CacheDataSinkFactory(Cache, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"CacheDataSource(Cache, DataSource, DataSource, DataSink, int, CacheDataSource.EventListener, CacheKeyFactory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSink,int,com.google.android.exoplayer2.upstream.cache.CacheDataSource.EventListener,com.google.android.exoplayer2.upstream.cache.CacheKeyFactory)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"CacheDataSource(Cache, DataSource, DataSource, DataSink, int, CacheDataSource.EventListener)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSink,int,com.google.android.exoplayer2.upstream.cache.CacheDataSource.EventListener)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"CacheDataSource(Cache, DataSource, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.DataSource,int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"CacheDataSource(Cache, DataSource)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.DataSource)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSourceFactory","l":"CacheDataSourceFactory(Cache, DataSource.Factory, DataSource.Factory, DataSink.Factory, int, CacheDataSource.EventListener, CacheKeyFactory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.upstream.DataSink.Factory,int,com.google.android.exoplayer2.upstream.cache.CacheDataSource.EventListener,com.google.android.exoplayer2.upstream.cache.CacheKeyFactory)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSourceFactory","l":"CacheDataSourceFactory(Cache, DataSource.Factory, DataSource.Factory, DataSink.Factory, int, CacheDataSource.EventListener)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.upstream.DataSink.Factory,int,com.google.android.exoplayer2.upstream.cache.CacheDataSource.EventListener)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSourceFactory","l":"CacheDataSourceFactory(Cache, DataSource.Factory, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.DataSource.Factory,int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSourceFactory","l":"CacheDataSourceFactory(Cache, DataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CachedRegionTracker","l":"CachedRegionTracker(Cache, String, ChunkIndex)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,java.lang.String,com.google.android.exoplayer2.extractor.ChunkIndex)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache.CacheException","l":"CacheException(String, Throwable)","url":"%3Cinit%3E(java.lang.String,java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache.CacheException","l":"CacheException(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache.CacheException","l":"CacheException(Throwable)","url":"%3Cinit%3E(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheSpan","l":"CacheSpan(String, long, long, long, File)","url":"%3Cinit%3E(java.lang.String,long,long,long,java.io.File)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheSpan","l":"CacheSpan(String, long, long)","url":"%3Cinit%3E(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheWriter","l":"CacheWriter(CacheDataSource, DataSpec, byte[], CacheWriter.ProgressListener)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.CacheDataSource,com.google.android.exoplayer2.upstream.DataSpec,byte[],com.google.android.exoplayer2.upstream.cache.CacheWriter.ProgressListener)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.SeekOperationParams","l":"calculateNextSearchBytePosition(long, long, long, long, long, long)","url":"calculateNextSearchBytePosition(long,long,long,long,long,long)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"calculateTargetBufferBytes(Renderer[], ExoTrackSelection[])","url":"calculateTargetBufferBytes(com.google.android.exoplayer2.Renderer[],com.google.android.exoplayer2.trackselection.ExoTrackSelection[])"},{"p":"com.google.android.exoplayer2.video.spherical","c":"CameraMotionRenderer","l":"CameraMotionRenderer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.ServerControl","l":"canBlockReload"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"cancel()"},{"p":"com.google.android.exoplayer2.ext.workmanager","c":"WorkManagerScheduler","l":"cancel()"},{"p":"com.google.android.exoplayer2.offline","c":"Downloader","l":"cancel()"},{"p":"com.google.android.exoplayer2.offline","c":"ProgressiveDownloader","l":"cancel()"},{"p":"com.google.android.exoplayer2.offline","c":"SegmentDownloader","l":"cancel()"},{"p":"com.google.android.exoplayer2.scheduler","c":"PlatformScheduler","l":"cancel()"},{"p":"com.google.android.exoplayer2.scheduler","c":"Scheduler","l":"cancel()"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer","l":"cancel()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheWriter","l":"cancel()"},{"p":"com.google.android.exoplayer2.util","c":"RunnableFutureTask","l":"cancel(boolean)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ContainerMediaChunk","l":"cancelLoad()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"DataChunk","l":"cancelLoad()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"InitializationChunk","l":"cancelLoad()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"SingleSampleMediaChunk","l":"cancelLoad()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaChunk","l":"cancelLoad()"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader.Loadable","l":"cancelLoad()"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"cancelLoad()"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"cancelLoading()"},{"p":"com.google.android.exoplayer2.util","c":"RunnableFutureTask","l":"cancelWork()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableNalUnitBitArray","l":"canReadBits(int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableNalUnitBitArray","l":"canReadExpGolombCodedNum()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"canReplace(DrmInitData.SchemeData)","url":"canReplace(com.google.android.exoplayer2.drm.DrmInitData.SchemeData)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"canReuseCodec(Format, Format)","url":"canReuseCodec(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"canReuseCodec(MediaCodecInfo, Format, Format)","url":"canReuseCodec(com.google.android.exoplayer2.mediacodec.MediaCodecInfo,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"canReuseCodec(MediaCodecInfo, Format, Format)","url":"canReuseCodec(com.google.android.exoplayer2.mediacodec.MediaCodecInfo,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"canReuseCodec(MediaCodecInfo, Format, Format)","url":"canReuseCodec(com.google.android.exoplayer2.mediacodec.MediaCodecInfo,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"canReuseDecoder(String, Format, Format)","url":"canReuseDecoder(java.lang.String,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Libgav1VideoRenderer","l":"canReuseDecoder(String, Format, Format)","url":"canReuseDecoder(java.lang.String,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"LibvpxVideoRenderer","l":"canReuseDecoder(String, Format, Format)","url":"canReuseDecoder(java.lang.String,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"canReuseDecoder(String, Format, Format)","url":"canReuseDecoder(java.lang.String,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"canSelectFormat(Format, int, long)","url":"canSelectFormat(com.google.android.exoplayer2.Format,int,long)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.ServerControl","l":"canSkipDateRanges"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"capabilities"},{"p":"com.google.android.exoplayer2.util","c":"IntArrayQueue","l":"capacity()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"capacity()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry.VariantInfo","l":"captionGroupId"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Variant","l":"captionGroupId"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"CaptionStyleCompat(int, int, int, int, int, Typeface)","url":"%3Cinit%3E(int,int,int,int,int,android.graphics.Typeface)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SmtaMetadataEntry","l":"captureFrameRate"},{"p":"com.google.android.exoplayer2.testutil","c":"CapturingAudioSink","l":"CapturingAudioSink(AudioSink)","url":"%3Cinit%3E(com.google.android.exoplayer2.audio.AudioSink)"},{"p":"com.google.android.exoplayer2.testutil","c":"CapturingRenderersFactory","l":"CapturingRenderersFactory(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"castNonNull(T)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"castNonNullTypeArray(T[])"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"CastPlayer(CastContext, MediaItemConverter)","url":"%3Cinit%3E(com.google.android.gms.cast.framework.CastContext,com.google.android.exoplayer2.ext.cast.MediaItemConverter)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"CastPlayer(CastContext)","url":"%3Cinit%3E(com.google.android.gms.cast.framework.CastContext)"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea608Decoder","l":"Cea608Decoder(String, int, long)","url":"%3Cinit%3E(java.lang.String,int,long)"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea708Decoder","l":"Cea708Decoder(int, List)","url":"%3Cinit%3E(int,java.util.List)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"ceilDivide(int, int)","url":"ceilDivide(int,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"ceilDivide(long, long)","url":"ceilDivide(long,long)"},{"p":"com.google.android.exoplayer2","c":"C","l":"CENC_TYPE_cbc1"},{"p":"com.google.android.exoplayer2","c":"C","l":"CENC_TYPE_cbcs"},{"p":"com.google.android.exoplayer2","c":"C","l":"CENC_TYPE_cenc"},{"p":"com.google.android.exoplayer2","c":"C","l":"CENC_TYPE_cens"},{"p":"com.google.android.exoplayer2","c":"Format","l":"channelCount"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil.Config","l":"channelCount"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util.SyncFrameInfo","l":"channelCount"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util.SyncFrameInfo","l":"channelCount"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor.AudioFormat","l":"channelCount"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusDecoder","l":"channelCount"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil.Header","l":"channels"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"channels"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.VorbisIdHeader","l":"channels"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"ChapterFrame(String, int, int, long, long, Id3Frame[])","url":"%3Cinit%3E(java.lang.String,int,int,long,long,com.google.android.exoplayer2.metadata.id3.Id3Frame[])"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"chapterId"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterTocFrame","l":"ChapterTocFrame(String, boolean, boolean, String[], Id3Frame[])","url":"%3Cinit%3E(java.lang.String,boolean,boolean,java.lang.String[],com.google.android.exoplayer2.metadata.id3.Id3Frame[])"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacMetadataReader","l":"checkAndPeekStreamMarker(ExtractorInput)","url":"checkAndPeekStreamMarker(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacFrameReader","l":"checkAndReadFrameHeader(ParsableByteArray, FlacStreamMetadata, int, FlacFrameReader.SampleNumberHolder)","url":"checkAndReadFrameHeader(com.google.android.exoplayer2.util.ParsableByteArray,com.google.android.exoplayer2.extractor.FlacStreamMetadata,int,com.google.android.exoplayer2.extractor.FlacFrameReader.SampleNumberHolder)"},{"p":"com.google.android.exoplayer2.util","c":"Assertions","l":"checkArgument(boolean, Object)","url":"checkArgument(boolean,java.lang.Object)"},{"p":"com.google.android.exoplayer2.util","c":"Assertions","l":"checkArgument(boolean)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"checkCleartextTrafficPermitted(MediaItem...)","url":"checkCleartextTrafficPermitted(com.google.android.exoplayer2.MediaItem...)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacFrameReader","l":"checkFrameHeaderFromPeek(ExtractorInput, FlacStreamMetadata, int, FlacFrameReader.SampleNumberHolder)","url":"checkFrameHeaderFromPeek(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.FlacStreamMetadata,int,com.google.android.exoplayer2.extractor.FlacFrameReader.SampleNumberHolder)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil","l":"checkGlError()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunkIterator","l":"checkInBounds()"},{"p":"com.google.android.exoplayer2.util","c":"Assertions","l":"checkIndex(int, int, int)","url":"checkIndex(int,int,int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"checkInitialization()"},{"p":"com.google.android.exoplayer2.util","c":"Assertions","l":"checkMainThread()"},{"p":"com.google.android.exoplayer2.util","c":"Assertions","l":"checkNotEmpty(String, Object)","url":"checkNotEmpty(java.lang.String,java.lang.Object)"},{"p":"com.google.android.exoplayer2.util","c":"Assertions","l":"checkNotEmpty(String)","url":"checkNotEmpty(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"Assertions","l":"checkNotNull(T, Object)","url":"checkNotNull(T,java.lang.Object)"},{"p":"com.google.android.exoplayer2.util","c":"Assertions","l":"checkNotNull(T)"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"checkRequirements(Context)","url":"checkRequirements(android.content.Context)"},{"p":"com.google.android.exoplayer2.util","c":"Assertions","l":"checkState(boolean, Object)","url":"checkState(boolean,java.lang.Object)"},{"p":"com.google.android.exoplayer2.util","c":"Assertions","l":"checkState(boolean)"},{"p":"com.google.android.exoplayer2.util","c":"Assertions","l":"checkStateNotNull(T, Object)","url":"checkStateNotNull(T,java.lang.Object)"},{"p":"com.google.android.exoplayer2.util","c":"Assertions","l":"checkStateNotNull(T)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterTocFrame","l":"children"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkHolder","l":"chunk"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"Chunk(DataSource, DataSpec, int, Format, int, Object, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,int,com.google.android.exoplayer2.Format,int,java.lang.Object,long,long)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"chunkCount"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkHolder","l":"ChunkHolder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaChunk","l":"chunkIndex"},{"p":"com.google.android.exoplayer2.extractor","c":"ChunkIndex","l":"ChunkIndex(int[], long[], long[], long[])","url":"%3Cinit%3E(int[],long[],long[],long[])"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"ChunkSampleStream(int, int[], Format[], T, SequenceableLoader.Callback>, Allocator, long, DrmSessionManager, DrmSessionEventListener.EventDispatcher, LoadErrorHandlingPolicy, MediaSourceEventListener.EventDispatcher)","url":"%3Cinit%3E(int,int[],com.google.android.exoplayer2.Format[],T,com.google.android.exoplayer2.source.SequenceableLoader.Callback,com.google.android.exoplayer2.upstream.Allocator,long,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher,com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy,com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2","c":"FormatHolder","l":"clear()"},{"p":"com.google.android.exoplayer2.decoder","c":"Buffer","l":"clear()"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"clear()"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleOutputBuffer","l":"clear()"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"clear()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkHolder","l":"clear()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"clear()"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleOutputBuffer","l":"clear()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.RequestProperties","l":"clear()"},{"p":"com.google.android.exoplayer2.util","c":"IntArrayQueue","l":"clear()"},{"p":"com.google.android.exoplayer2.util","c":"TimedValueQueue","l":"clear()"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"clear(Handler, Runnable)","url":"clear(android.os.Handler,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.drm","c":"HttpMediaDrmCallback","l":"clearAllKeyRequestProperties()"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"clearAllRequestProperties()"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"clearAllRequestProperties()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"clearAllRequestProperties()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource","l":"clearAllRequestProperties()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.RequestProperties","l":"clearAndSet(Map)","url":"clearAndSet(java.util.Map)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioComponent","l":"clearAuxEffectInfo()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"clearAuxEffectInfo()"},{"p":"com.google.android.exoplayer2.decoder","c":"CryptoInfo","l":"clearBlocks"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput.CryptoData","l":"clearBlocks"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"clearCameraMotionListener(CameraMotionListener)","url":"clearCameraMotionListener(com.google.android.exoplayer2.video.spherical.CameraMotionListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"clearCameraMotionListener(CameraMotionListener)","url":"clearCameraMotionListener(com.google.android.exoplayer2.video.spherical.CameraMotionListener)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecUtil","l":"clearDecoderInfoCache()"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"clearFatalError()"},{"p":"com.google.android.exoplayer2.decoder","c":"Buffer","l":"clearFlag(int)"},{"p":"com.google.android.exoplayer2","c":"C","l":"CLEARKEY_UUID"},{"p":"com.google.android.exoplayer2.drm","c":"HttpMediaDrmCallback","l":"clearKeyRequestProperty(String)","url":"clearKeyRequestProperty(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"clearMediaItems()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"clearMediaItems()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"clearMediaItems()"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.ClearMediaItems","l":"ClearMediaItems(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil","l":"clearPrefixFlags(boolean[])"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"clearRequestProperty(String)","url":"clearRequestProperty(java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"clearRequestProperty(String)","url":"clearRequestProperty(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"clearRequestProperty(String)","url":"clearRequestProperty(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource","l":"clearRequestProperty(String)","url":"clearRequestProperty(java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"clearSelectionOverride(int, TrackGroupArray)","url":"clearSelectionOverride(int,com.google.android.exoplayer2.source.TrackGroupArray)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"clearSelectionOverrides()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"clearSelectionOverrides(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.CleartextNotPermittedException","l":"CleartextNotPermittedException(IOException, DataSpec)","url":"%3Cinit%3E(java.io.IOException,com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorOutput","l":"clearTrackOutputs()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"clearTrackSelections(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"clearVideoFrameMetadataListener(VideoFrameMetadataListener)","url":"clearVideoFrameMetadataListener(com.google.android.exoplayer2.video.VideoFrameMetadataListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"clearVideoFrameMetadataListener(VideoFrameMetadataListener)","url":"clearVideoFrameMetadataListener(com.google.android.exoplayer2.video.VideoFrameMetadataListener)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"clearVideoSizeConstraints()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"clearVideoSurface()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"clearVideoSurface()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"clearVideoSurface()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"clearVideoSurface()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"clearVideoSurface()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"clearVideoSurface()"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.ClearVideoSurface","l":"ClearVideoSurface(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"clearVideoSurface(Surface)","url":"clearVideoSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"clearVideoSurface(Surface)","url":"clearVideoSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"clearVideoSurface(Surface)","url":"clearVideoSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"clearVideoSurface(Surface)","url":"clearVideoSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"clearVideoSurface(Surface)","url":"clearVideoSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"clearVideoSurfaceHolder(SurfaceHolder)","url":"clearVideoSurfaceHolder(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"clearVideoSurfaceHolder(SurfaceHolder)","url":"clearVideoSurfaceHolder(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"clearVideoSurfaceHolder(SurfaceHolder)","url":"clearVideoSurfaceHolder(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"clearVideoSurfaceHolder(SurfaceHolder)","url":"clearVideoSurfaceHolder(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"clearVideoSurfaceHolder(SurfaceHolder)","url":"clearVideoSurfaceHolder(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"clearVideoSurfaceView(SurfaceView)","url":"clearVideoSurfaceView(android.view.SurfaceView)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"clearVideoSurfaceView(SurfaceView)","url":"clearVideoSurfaceView(android.view.SurfaceView)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"clearVideoSurfaceView(SurfaceView)","url":"clearVideoSurfaceView(android.view.SurfaceView)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"clearVideoSurfaceView(SurfaceView)","url":"clearVideoSurfaceView(android.view.SurfaceView)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"clearVideoSurfaceView(SurfaceView)","url":"clearVideoSurfaceView(android.view.SurfaceView)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"clearVideoTextureView(TextureView)","url":"clearVideoTextureView(android.view.TextureView)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"clearVideoTextureView(TextureView)","url":"clearVideoTextureView(android.view.TextureView)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"clearVideoTextureView(TextureView)","url":"clearVideoTextureView(android.view.TextureView)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"clearVideoTextureView(TextureView)","url":"clearVideoTextureView(android.view.TextureView)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"clearVideoTextureView(TextureView)","url":"clearVideoTextureView(android.view.TextureView)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"clearViewportSizeConstraints()"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"clearWindowColor()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunk","l":"clippedEndTimeUs"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunk","l":"clippedStartTimeUs"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"ClippingMediaPeriod(MediaPeriod, boolean, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaPeriod,boolean,long,long)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource","l":"ClippingMediaSource(MediaSource, long, long, boolean, boolean, boolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaSource,long,long,boolean,boolean,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource","l":"ClippingMediaSource(MediaSource, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaSource,long,long)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource","l":"ClippingMediaSource(MediaSource, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaSource,long)"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"clippingProperties"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPayloadFormat","l":"clockRate"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder","l":"cloneAndClear()"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.DefaultShuffleOrder","l":"cloneAndClear()"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.UnshuffledShuffleOrder","l":"cloneAndClear()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeShuffleOrder","l":"cloneAndClear()"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder","l":"cloneAndInsert(int, int)","url":"cloneAndInsert(int,int)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.DefaultShuffleOrder","l":"cloneAndInsert(int, int)","url":"cloneAndInsert(int,int)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.UnshuffledShuffleOrder","l":"cloneAndInsert(int, int)","url":"cloneAndInsert(int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeShuffleOrder","l":"cloneAndInsert(int, int)","url":"cloneAndInsert(int,int)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder","l":"cloneAndRemove(int, int)","url":"cloneAndRemove(int,int)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.DefaultShuffleOrder","l":"cloneAndRemove(int, int)","url":"cloneAndRemove(int,int)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.UnshuffledShuffleOrder","l":"cloneAndRemove(int, int)","url":"cloneAndRemove(int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeShuffleOrder","l":"cloneAndRemove(int, int)","url":"cloneAndRemove(int,int)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"close()"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.ext.rtmp","c":"RtmpDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"close()"},{"p":"com.google.android.exoplayer2.testutil","c":"FailOnCloseDataSink","l":"close()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"AssetDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"ByteArrayDataSink","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"ByteArrayDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"ContentDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSchemeDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSink","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceInputStream","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"DummyDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"PriorityDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"RawResourceDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"ResolvingDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"StatsDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"TeeDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"UdpDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink","l":"close()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesCipherDataSink","l":"close()"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesCipherDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.util","c":"ConditionVariable","l":"close()"},{"p":"com.google.android.exoplayer2.util","c":"ReusableBufferedOutputStream","l":"close()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"closedCaptions"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"closeQuietly(Closeable)","url":"closeQuietly(java.io.Closeable)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"closeQuietly(DataSource)","url":"closeQuietly(com.google.android.exoplayer2.upstream.DataSource)"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"closeSession(byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"closeSession(byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"closeSession(byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"closeSession(byte[])"},{"p":"com.google.android.exoplayer2","c":"SeekParameters","l":"CLOSEST_SYNC"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"CODEC_OPERATING_RATE_UNSET"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter.Configuration","l":"codecInfo"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecDecoderException","l":"codecInfo"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer.DecoderInitializationException","l":"codecInfo"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer.CodecMaxValues","l":"CodecMaxValues(int, int, int)","url":"%3Cinit%3E(int,int,int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"codecMimeType"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"codecNeedsSetOutputSurfaceWorkaround(String)","url":"codecNeedsSetOutputSurfaceWorkaround(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"codecs"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil.Config","l":"codecs"},{"p":"com.google.android.exoplayer2.video","c":"AvcConfig","l":"codecs"},{"p":"com.google.android.exoplayer2.video","c":"DolbyVisionConfig","l":"codecs"},{"p":"com.google.android.exoplayer2.video","c":"HevcConfig","l":"codecs"},{"p":"com.google.android.exoplayer2","c":"C","l":"COLOR_RANGE_FULL"},{"p":"com.google.android.exoplayer2","c":"C","l":"COLOR_RANGE_LIMITED"},{"p":"com.google.android.exoplayer2","c":"C","l":"COLOR_SPACE_BT2020"},{"p":"com.google.android.exoplayer2","c":"C","l":"COLOR_SPACE_BT601"},{"p":"com.google.android.exoplayer2","c":"C","l":"COLOR_SPACE_BT709"},{"p":"com.google.android.exoplayer2","c":"C","l":"COLOR_TRANSFER_HLG"},{"p":"com.google.android.exoplayer2","c":"C","l":"COLOR_TRANSFER_SDR"},{"p":"com.google.android.exoplayer2","c":"C","l":"COLOR_TRANSFER_ST2084"},{"p":"com.google.android.exoplayer2","c":"Format","l":"colorInfo"},{"p":"com.google.android.exoplayer2.video","c":"ColorInfo","l":"ColorInfo(int, int, int, byte[])","url":"%3Cinit%3E(int,int,int,byte[])"},{"p":"com.google.android.exoplayer2.video","c":"ColorInfo","l":"colorRange"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"colors"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"colorspace"},{"p":"com.google.android.exoplayer2.video","c":"ColorInfo","l":"colorSpace"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"COLORSPACE_BT2020"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"COLORSPACE_BT601"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"COLORSPACE_BT709"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"COLORSPACE_UNKNOWN"},{"p":"com.google.android.exoplayer2.video","c":"ColorInfo","l":"colorTransfer"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_ADJUST_DEVICE_VOLUME"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_CHANGE_MEDIA_ITEMS"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_GET_AUDIO_ATTRIBUTES"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_GET_CURRENT_MEDIA_ITEM"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_GET_DEVICE_VOLUME"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_GET_MEDIA_ITEMS"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_GET_MEDIA_ITEMS_METADATA"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_GET_TEXT"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_GET_VOLUME"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor","l":"COMMAND_MOVE_QUEUE_ITEM"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_PLAY_PAUSE"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_PREPARE_STOP"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SEEK_TO_DEFAULT_POSITION"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SEEK_TO_MEDIA_ITEM"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SEEK_TO_NEXT_MEDIA_ITEM"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SET_DEVICE_VOLUME"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SET_REPEAT_MODE"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SET_SHUFFLE_MODE"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SET_SPEED_AND_PITCH"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SET_VIDEO_SURFACE"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SET_VOLUME"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"PrivateCommand","l":"commandBytes"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"CommentFrame","l":"CommentFrame(String, String, String)","url":"%3Cinit%3E(java.lang.String,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.CommentHeader","l":"CommentHeader(String, String[], int)","url":"%3Cinit%3E(java.lang.String,java.lang.String[],int)"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.CommentHeader","l":"comments"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"commitFile(File, long)","url":"commitFile(java.io.File,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"commitFile(File, long)","url":"commitFile(java.io.File,long)"},{"p":"com.google.android.exoplayer2","c":"C","l":"COMMON_PSSH_UUID"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"compare(DrmInitData.SchemeData, DrmInitData.SchemeData)","url":"compare(com.google.android.exoplayer2.drm.DrmInitData.SchemeData,com.google.android.exoplayer2.drm.DrmInitData.SchemeData)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"compareLong(long, long)","url":"compareLong(long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheSpan","l":"compareTo(CacheSpan)","url":"compareTo(com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.AudioTrackScore","l":"compareTo(DefaultTrackSelector.AudioTrackScore)","url":"compareTo(com.google.android.exoplayer2.trackselection.DefaultTrackSelector.AudioTrackScore)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.OtherTrackScore","l":"compareTo(DefaultTrackSelector.OtherTrackScore)","url":"compareTo(com.google.android.exoplayer2.trackselection.DefaultTrackSelector.OtherTrackScore)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.TextTrackScore","l":"compareTo(DefaultTrackSelector.TextTrackScore)","url":"compareTo(com.google.android.exoplayer2.trackselection.DefaultTrackSelector.TextTrackScore)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.VideoTrackScore","l":"compareTo(DefaultTrackSelector.VideoTrackScore)","url":"compareTo(com.google.android.exoplayer2.trackselection.DefaultTrackSelector.VideoTrackScore)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock.HandlerMessage","l":"compareTo(FakeClock.HandlerMessage)","url":"compareTo(com.google.android.exoplayer2.testutil.FakeClock.HandlerMessage)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.SegmentBase","l":"compareTo(Long)","url":"compareTo(java.lang.Long)"},{"p":"com.google.android.exoplayer2.offline","c":"SegmentDownloader.Segment","l":"compareTo(SegmentDownloader.Segment)","url":"compareTo(com.google.android.exoplayer2.offline.SegmentDownloader.Segment)"},{"p":"com.google.android.exoplayer2.offline","c":"StreamKey","l":"compareTo(StreamKey)","url":"compareTo(com.google.android.exoplayer2.offline.StreamKey)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"UrlTemplate","l":"compile(String)","url":"compile(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil","l":"compileProgram(String, String)","url":"compileProgram(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil","l":"compileProgram(String[], String[])","url":"compileProgram(java.lang.String[],java.lang.String[])"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"componentSpliceList"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.Event","l":"componentSpliceList"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand.ComponentSplice","l":"componentSplicePlaybackPositionUs"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand.ComponentSplice","l":"componentSplicePts"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand.ComponentSplice","l":"componentTag"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.ComponentSplice","l":"componentTag"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"CompositeMediaSource()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source","c":"CompositeSequenceableLoader","l":"CompositeSequenceableLoader(SequenceableLoader[])","url":"%3Cinit%3E(com.google.android.exoplayer2.source.SequenceableLoader[])"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"ConcatenatingMediaSource(boolean, boolean, ShuffleOrder, MediaSource...)","url":"%3Cinit%3E(boolean,boolean,com.google.android.exoplayer2.source.ShuffleOrder,com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"ConcatenatingMediaSource(boolean, MediaSource...)","url":"%3Cinit%3E(boolean,com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"ConcatenatingMediaSource(boolean, ShuffleOrder, MediaSource...)","url":"%3Cinit%3E(boolean,com.google.android.exoplayer2.source.ShuffleOrder,com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"ConcatenatingMediaSource(MediaSource...)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.util","c":"ConditionVariable","l":"ConditionVariable()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.util","c":"ConditionVariable","l":"ConditionVariable(Clock)","url":"%3Cinit%3E(com.google.android.exoplayer2.util.Clock)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts","l":"configs()"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts","l":"configsNoSniffing()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter.Configuration","l":"Configuration(MediaCodecInfo, MediaFormat, Format, Surface, MediaCrypto, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.mediacodec.MediaCodecInfo,android.media.MediaFormat,com.google.android.exoplayer2.Format,android.view.Surface,android.media.MediaCrypto,int)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.ConfigurationException","l":"ConfigurationException(String, Format)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.ConfigurationException","l":"ConfigurationException(Throwable, Format)","url":"%3Cinit%3E(java.lang.Throwable,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor","l":"configure(AudioProcessor.AudioFormat)","url":"configure(com.google.android.exoplayer2.audio.AudioProcessor.AudioFormat)"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"configure(AudioProcessor.AudioFormat)","url":"configure(com.google.android.exoplayer2.audio.AudioProcessor.AudioFormat)"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"configure(AudioProcessor.AudioFormat)","url":"configure(com.google.android.exoplayer2.audio.AudioProcessor.AudioFormat)"},{"p":"com.google.android.exoplayer2.ext.gvr","c":"GvrAudioProcessor","l":"configure(AudioProcessor.AudioFormat)","url":"configure(com.google.android.exoplayer2.audio.AudioProcessor.AudioFormat)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"configure(Format, int, int[])","url":"configure(com.google.android.exoplayer2.Format,int,int[])"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"configure(Format, int, int[])","url":"configure(com.google.android.exoplayer2.Format,int,int[])"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"configure(Format, int, int[])","url":"configure(com.google.android.exoplayer2.Format,int,int[])"},{"p":"com.google.android.exoplayer2.testutil","c":"CapturingAudioSink","l":"configure(Format, int, int[])","url":"configure(com.google.android.exoplayer2.Format,int,int[])"},{"p":"com.google.android.exoplayer2.extractor","c":"ConstantBitrateSeekMap","l":"ConstantBitrateSeekMap(long, long, int, int)","url":"%3Cinit%3E(long,long,int,int)"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"constraintsFlagsAndReservedZero2Bits"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"constrainValue(float, float, float)","url":"constrainValue(float,float,float)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"constrainValue(int, int, int)","url":"constrainValue(int,int,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"constrainValue(long, long, long)","url":"constrainValue(long,long,long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"DataChunk","l":"consume(byte[], int)","url":"consume(byte[],int)"},{"p":"com.google.android.exoplayer2.extractor","c":"CeaUtil","l":"consume(long, ParsableByteArray, TrackOutput[])","url":"consume(long,com.google.android.exoplayer2.util.ParsableByteArray,com.google.android.exoplayer2.extractor.TrackOutput[])"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"SeiReader","l":"consume(long, ParsableByteArray)","url":"consume(long,com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PesReader","l":"consume(ParsableByteArray, int)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"SectionReader","l":"consume(ParsableByteArray, int)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader","l":"consume(ParsableByteArray, int)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray,int)"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","c":"RtpAc3Reader","l":"consume(ParsableByteArray, long, int, boolean)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray,long,int,boolean)"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","c":"RtpPayloadReader","l":"consume(ParsableByteArray, long, int, boolean)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray,long,int,boolean)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Reader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Reader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsReader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DtsReader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DvbSubtitleReader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"ElementaryStreamReader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H262Reader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H263Reader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H264Reader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H265Reader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Id3Reader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"LatmReader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"MpegAudioReader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PassthroughSectionPayloadReader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"SectionPayloadReader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor","c":"CeaUtil","l":"consumeCcData(long, ParsableByteArray, TrackOutput[])","url":"consumeCcData(long,com.google.android.exoplayer2.util.ParsableByteArray,com.google.android.exoplayer2.extractor.TrackOutput[])"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ContainerMediaChunk","l":"ContainerMediaChunk(DataSource, DataSpec, Format, int, Object, long, long, long, long, long, int, long, ChunkExtractor)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,com.google.android.exoplayer2.Format,int,java.lang.Object,long,long,long,long,long,int,long,com.google.android.exoplayer2.source.chunk.ChunkExtractor)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"containerMimeType"},{"p":"com.google.android.exoplayer2","c":"Player.Commands","l":"contains(int)"},{"p":"com.google.android.exoplayer2","c":"Player.Events","l":"contains(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.Events","l":"contains(int)"},{"p":"com.google.android.exoplayer2.util","c":"ExoFlags","l":"contains(int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"contains(Object[], Object)","url":"contains(java.lang.Object[],java.lang.Object)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadata","l":"contains(String)","url":"contains(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"DefaultContentMetadata","l":"contains(String)","url":"contains(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"Player.Events","l":"containsAny(int...)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.Events","l":"containsAny(int...)"},{"p":"com.google.android.exoplayer2.util","c":"ExoFlags","l":"containsAny(int...)"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"containsCodecsCorrespondingToMimeType(String, String)","url":"containsCodecsCorrespondingToMimeType(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.SelectionOverride","l":"containsTrack(int)"},{"p":"com.google.android.exoplayer2","c":"C","l":"CONTENT_TYPE_MOVIE"},{"p":"com.google.android.exoplayer2","c":"C","l":"CONTENT_TYPE_MUSIC"},{"p":"com.google.android.exoplayer2","c":"C","l":"CONTENT_TYPE_SONIFICATION"},{"p":"com.google.android.exoplayer2","c":"C","l":"CONTENT_TYPE_SPEECH"},{"p":"com.google.android.exoplayer2","c":"C","l":"CONTENT_TYPE_UNKNOWN"},{"p":"com.google.android.exoplayer2.upstream","c":"ContentDataSource","l":"ContentDataSource(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.upstream","c":"ContentDataSource.ContentDataSourceException","l":"ContentDataSourceException(IOException)","url":"%3Cinit%3E(java.io.IOException)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"contentDurationUs"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"contentLength"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.SingleSegmentRepresentation","l":"contentLength"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadataMutations","l":"ContentMetadataMutations()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"contentPositionMs"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes","l":"contentType"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.InvalidContentTypeException","l":"contentType"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"continueLoading(long)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeSequenceableLoader","l":"continueLoading(long)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"continueLoading(long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"continueLoading(long)"},{"p":"com.google.android.exoplayer2.source","c":"SequenceableLoader","l":"continueLoading(long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"continueLoading(long)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"continueLoading(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"continueLoading(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"continueLoading(long)"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","c":"AppInfoTable","l":"CONTROL_CODE_AUTOSTART"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","c":"AppInfoTable","l":"CONTROL_CODE_PRESENT"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","c":"AppInfoTable","l":"controlCode"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor.MediaDescriptionConverter","l":"convert(MediaDescriptionCompat)","url":"convert(android.support.v4.media.MediaDescriptionCompat)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"DefaultMediaItemConverter","l":"convertToExoPlayerMediaItem(MediaItem)","url":"convertToExoPlayerMediaItem(androidx.media2.common.MediaItem)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"MediaItemConverter","l":"convertToExoPlayerMediaItem(MediaItem)","url":"convertToExoPlayerMediaItem(androidx.media2.common.MediaItem)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"DefaultMediaItemConverter","l":"convertToMedia2MediaItem(MediaItem)","url":"convertToMedia2MediaItem(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"MediaItemConverter","l":"convertToMedia2MediaItem(MediaItem)","url":"convertToMedia2MediaItem(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"copy(Format[])","url":"copy(com.google.android.exoplayer2.Format[])"},{"p":"com.google.android.exoplayer2.offline","c":"FilterableManifest","l":"copy(List)","url":"copy(java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"copy(List)","url":"copy(java.util.List)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"copy(List)","url":"copy(java.util.List)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"copy(List)","url":"copy(java.util.List)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest","l":"copy(List)","url":"copy(java.util.List)"},{"p":"com.google.android.exoplayer2.util","c":"ListenerSet","l":"copy(Looper, ListenerSet.IterationFinishedEvent)","url":"copy(android.os.Looper,com.google.android.exoplayer2.util.ListenerSet.IterationFinishedEvent)"},{"p":"com.google.android.exoplayer2.util","c":"CopyOnWriteMultiset","l":"CopyOnWriteMultiset()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ProgramInformation","l":"copyright"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"copyWith(long, int)","url":"copyWith(long,int)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.Part","l":"copyWith(long, int)","url":"copyWith(long,int)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.Segment","l":"copyWith(long, int)","url":"copyWith(long,int)"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata","l":"copyWithAppendedEntries(Metadata.Entry...)","url":"copyWithAppendedEntries(com.google.android.exoplayer2.metadata.Metadata.Entry...)"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata","l":"copyWithAppendedEntriesFrom(Metadata)","url":"copyWithAppendedEntriesFrom(com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"copyWithBitrate(int)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"copyWithData(byte[])"},{"p":"com.google.android.exoplayer2","c":"Format","l":"copyWithDrmInitData(DrmInitData)","url":"copyWithDrmInitData(com.google.android.exoplayer2.drm.DrmInitData)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"copyWithEndTag()"},{"p":"com.google.android.exoplayer2","c":"Format","l":"copyWithExoMediaCryptoType(Class)","url":"copyWithExoMediaCryptoType(java.lang.Class)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"copyWithFormat(Format)","url":"copyWithFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Variant","l":"copyWithFormat(Format)","url":"copyWithFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"copyWithFrameRate(float)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"copyWithGaplessInfo(int, int)","url":"copyWithGaplessInfo(int,int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"copyWithId(String)","url":"copyWithId(java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"copyWithKeySetId(byte[])"},{"p":"com.google.android.exoplayer2","c":"Format","l":"copyWithLabel(String)","url":"copyWithLabel(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"copyWithManifestFormatInfo(Format)","url":"copyWithManifestFormatInfo(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"copyWithMaxInputSize(int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"copyWithMergedRequest(DownloadRequest)","url":"copyWithMergedRequest(com.google.android.exoplayer2.offline.DownloadRequest)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"copyWithMetadata(Metadata)","url":"copyWithMetadata(com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"DefaultContentMetadata","l":"copyWithMutationsApplied(ContentMetadataMutations)","url":"copyWithMutationsApplied(com.google.android.exoplayer2.upstream.cache.ContentMetadataMutations)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"copyWithPeriodUid(Object)","url":"copyWithPeriodUid(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource.MediaPeriodId","l":"copyWithPeriodUid(Object)","url":"copyWithPeriodUid(java.lang.Object)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"copyWithPictureFrames(List)","url":"copyWithPictureFrames(java.util.List)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"copyWithSchemeType(String)","url":"copyWithSchemeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"copyWithSeekTable(FlacStreamMetadata.SeekTable)","url":"copyWithSeekTable(com.google.android.exoplayer2.extractor.FlacStreamMetadata.SeekTable)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"copyWithSubsampleOffsetUs(long)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"copyWithVideoSize(int, int)","url":"copyWithVideoSize(int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"copyWithVorbisComments(List)","url":"copyWithVorbisComments(java.util.List)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"copyWithWindowSequenceNumber(long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource.MediaPeriodId","l":"copyWithWindowSequenceNumber(long)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"count"},{"p":"com.google.android.exoplayer2.util","c":"CopyOnWriteMultiset","l":"count(E)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"crc32(byte[], int, int, int)","url":"crc32(byte[],int,int,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"crc8(byte[], int, int, int)","url":"crc8(byte[],int,int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts.ExtractorFactory","l":"create()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod.TrackDataFactory","l":"create(Format, MediaSource.MediaPeriodId)","url":"create(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"create(int, int, int)","url":"create(int,int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput.Factory","l":"create(int, int)","url":"create(int,int)"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"create(int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter.Factory","l":"createAdapter(MediaCodecAdapter.Configuration)","url":"createAdapter(com.google.android.exoplayer2.mediacodec.MediaCodecAdapter.Configuration)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter.Factory","l":"createAdapter(MediaCodecAdapter.Configuration)","url":"createAdapter(com.google.android.exoplayer2.mediacodec.MediaCodecAdapter.Configuration)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionUtil.AdaptiveTrackSelectionFactory","l":"createAdaptiveTrackSelection(ExoTrackSelection.Definition)","url":"createAdaptiveTrackSelection(com.google.android.exoplayer2.trackselection.ExoTrackSelection.Definition)"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection.Factory","l":"createAdaptiveTrackSelection(TrackGroup, int[], int, BandwidthMeter, ImmutableList)","url":"createAdaptiveTrackSelection(com.google.android.exoplayer2.source.TrackGroup,int[],int,com.google.android.exoplayer2.upstream.BandwidthMeter,com.google.common.collect.ImmutableList)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"createAdPlaybackState(int, long...)","url":"createAdPlaybackState(int,long...)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"createAudioContainerFormat(String, String, String, String, String, Metadata, int, int, int, List, int, int, String)","url":"createAudioContainerFormat(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,com.google.android.exoplayer2.metadata.Metadata,int,int,int,java.util.List,int,int,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"createAudioSampleFormat(String, String, String, int, int, int, int, int, int, int, List, DrmInitData, int, String, Metadata)","url":"createAudioSampleFormat(java.lang.String,java.lang.String,java.lang.String,int,int,int,int,int,int,int,java.util.List,com.google.android.exoplayer2.drm.DrmInitData,int,java.lang.String,com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"createAudioSampleFormat(String, String, String, int, int, int, int, int, List, DrmInitData, int, String)","url":"createAudioSampleFormat(java.lang.String,java.lang.String,java.lang.String,int,int,int,int,int,java.util.List,com.google.android.exoplayer2.drm.DrmInitData,int,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"createAudioSampleFormat(String, String, String, int, int, int, int, List, DrmInitData, int, String)","url":"createAudioSampleFormat(java.lang.String,java.lang.String,java.lang.String,int,int,int,int,java.util.List,com.google.android.exoplayer2.drm.DrmInitData,int,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil","l":"createBuffer(float[])"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil","l":"createBuffer(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"createByteArray(int...)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"createByteList(int...)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource.Factory","l":"createChunkSource(ExoTrackSelection, long, TransferListener)","url":"createChunkSource(com.google.android.exoplayer2.trackselection.ExoTrackSelection,long,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource.Factory","l":"createChunkSource(LoaderErrorThrower, SsManifest, int, ExoTrackSelection, TransferListener)","url":"createChunkSource(com.google.android.exoplayer2.upstream.LoaderErrorThrower,com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest,int,com.google.android.exoplayer2.trackselection.ExoTrackSelection,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsChunkSource.Factory","l":"createChunkSource(LoaderErrorThrower, SsManifest, int, ExoTrackSelection, TransferListener)","url":"createChunkSource(com.google.android.exoplayer2.upstream.LoaderErrorThrower,com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest,int,com.google.android.exoplayer2.trackselection.ExoTrackSelection,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter.Factory","l":"createCodec(MediaCodecAdapter.Configuration)","url":"createCodec(com.google.android.exoplayer2.mediacodec.MediaCodecAdapter.Configuration)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeSequenceableLoaderFactory","l":"createCompositeSequenceableLoader(SequenceableLoader...)","url":"createCompositeSequenceableLoader(com.google.android.exoplayer2.source.SequenceableLoader...)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultCompositeSequenceableLoaderFactory","l":"createCompositeSequenceableLoader(SequenceableLoader...)","url":"createCompositeSequenceableLoader(com.google.android.exoplayer2.source.SequenceableLoader...)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"createContainerFormat(String, String, String, String, String, int, int, int, String)","url":"createContainerFormat(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,int,int,int,java.lang.String)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.MediaDescriptionAdapter","l":"createCurrentContentIntent(Player)","url":"createCurrentContentIntent(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.CustomActionReceiver","l":"createCustomActions(Context, int)","url":"createCustomActions(android.content.Context,int)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashChunkSource.Factory","l":"createDashChunkSource(LoaderErrorThrower, DashManifest, int, int[], ExoTrackSelection, int, long, boolean, List, PlayerEmsgHandler.PlayerTrackEmsgHandler, TransferListener)","url":"createDashChunkSource(com.google.android.exoplayer2.upstream.LoaderErrorThrower,com.google.android.exoplayer2.source.dash.manifest.DashManifest,int,int[],com.google.android.exoplayer2.trackselection.ExoTrackSelection,int,long,boolean,java.util.List,com.google.android.exoplayer2.source.dash.PlayerEmsgHandler.PlayerTrackEmsgHandler,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.Factory","l":"createDashChunkSource(LoaderErrorThrower, DashManifest, int, int[], ExoTrackSelection, int, long, boolean, List, PlayerEmsgHandler.PlayerTrackEmsgHandler, TransferListener)","url":"createDashChunkSource(com.google.android.exoplayer2.upstream.LoaderErrorThrower,com.google.android.exoplayer2.source.dash.manifest.DashManifest,int,int[],com.google.android.exoplayer2.trackselection.ExoTrackSelection,int,long,boolean,java.util.List,com.google.android.exoplayer2.source.dash.PlayerEmsgHandler.PlayerTrackEmsgHandler,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveDataSet.Factory","l":"createDataSet(TrackGroup, long)","url":"createDataSet(com.google.android.exoplayer2.source.TrackGroup,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FailOnCloseDataSink.Factory","l":"createDataSink()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSink.Factory","l":"createDataSink()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink.Factory","l":"createDataSink()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSinkFactory","l":"createDataSink()"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource.Factory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.ext.rtmp","c":"RtmpDataSourceFactory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource.Factory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSource.Factory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSourceFactory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource.Factory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSource.Factory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSourceFactory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.BaseFactory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.Factory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.upstream","c":"PriorityDataSourceFactory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.upstream","c":"ResolvingDataSource.Factory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSourceFactory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.source.hls","c":"DefaultHlsDataSourceFactory","l":"createDataSource(int)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsDataSourceFactory","l":"createDataSource(int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"createDataSourceForDownloading()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"createDataSourceForRemovingDownload()"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"createDataSourceInternal(HttpDataSource.RequestProperties)","url":"createDataSourceInternal(com.google.android.exoplayer2.upstream.HttpDataSource.RequestProperties)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSourceFactory","l":"createDataSourceInternal(HttpDataSource.RequestProperties)","url":"createDataSourceInternal(com.google.android.exoplayer2.upstream.HttpDataSource.RequestProperties)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSourceFactory","l":"createDataSourceInternal(HttpDataSource.RequestProperties)","url":"createDataSourceInternal(com.google.android.exoplayer2.upstream.HttpDataSource.RequestProperties)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.BaseFactory","l":"createDataSourceInternal(HttpDataSource.RequestProperties)","url":"createDataSourceInternal(com.google.android.exoplayer2.upstream.HttpDataSource.RequestProperties)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"createDecoder(Format, ExoMediaCrypto)","url":"createDecoder(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.drm.ExoMediaCrypto)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Libgav1VideoRenderer","l":"createDecoder(Format, ExoMediaCrypto)","url":"createDecoder(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.drm.ExoMediaCrypto)"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegAudioRenderer","l":"createDecoder(Format, ExoMediaCrypto)","url":"createDecoder(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.drm.ExoMediaCrypto)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"LibflacAudioRenderer","l":"createDecoder(Format, ExoMediaCrypto)","url":"createDecoder(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.drm.ExoMediaCrypto)"},{"p":"com.google.android.exoplayer2.ext.opus","c":"LibopusAudioRenderer","l":"createDecoder(Format, ExoMediaCrypto)","url":"createDecoder(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.drm.ExoMediaCrypto)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"LibvpxVideoRenderer","l":"createDecoder(Format, ExoMediaCrypto)","url":"createDecoder(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.drm.ExoMediaCrypto)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"createDecoder(Format, ExoMediaCrypto)","url":"createDecoder(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.drm.ExoMediaCrypto)"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataDecoderFactory","l":"createDecoder(Format)","url":"createDecoder(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleDecoderFactory","l":"createDecoder(Format)","url":"createDecoder(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"createDecoderException(Throwable, MediaCodecInfo)","url":"createDecoderException(java.lang.Throwable,com.google.android.exoplayer2.mediacodec.MediaCodecInfo)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"createDecoderException(Throwable, MediaCodecInfo)","url":"createDecoderException(java.lang.Throwable,com.google.android.exoplayer2.mediacodec.MediaCodecInfo)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl.Builder","l":"createDefaultLoadControl()"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloaderFactory","l":"createDownloader(DownloadRequest)","url":"createDownloader(com.google.android.exoplayer2.offline.DownloadRequest)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloaderFactory","l":"createDownloader(DownloadRequest)","url":"createDownloader(com.google.android.exoplayer2.offline.DownloadRequest)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"createDrmEventDispatcher(int, MediaSource.MediaPeriodId)","url":"createDrmEventDispatcher(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"createDrmEventDispatcher(MediaSource.MediaPeriodId)","url":"createDrmEventDispatcher(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"createEventDispatcher(int, MediaSource.MediaPeriodId, long)","url":"createEventDispatcher(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,long)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"createEventDispatcher(MediaSource.MediaPeriodId, long)","url":"createEventDispatcher(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,long)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"createEventDispatcher(MediaSource.MediaPeriodId)","url":"createEventDispatcher(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil","l":"createExternalTexture()"},{"p":"com.google.android.exoplayer2.source.hls","c":"DefaultHlsExtractorFactory","l":"createExtractor(Uri, Format, List, TimestampAdjuster, Map>, ExtractorInput)","url":"createExtractor(android.net.Uri,com.google.android.exoplayer2.Format,java.util.List,com.google.android.exoplayer2.util.TimestampAdjuster,java.util.Map,com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsExtractorFactory","l":"createExtractor(Uri, Format, List, TimestampAdjuster, Map>, ExtractorInput)","url":"createExtractor(android.net.Uri,com.google.android.exoplayer2.Format,java.util.List,com.google.android.exoplayer2.util.TimestampAdjuster,java.util.Map,com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"createExtractors()"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorsFactory","l":"createExtractors()"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"createExtractors(Uri, Map>)","url":"createExtractors(android.net.Uri,java.util.Map)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorsFactory","l":"createExtractors(Uri, Map>)","url":"createExtractors(android.net.Uri,java.util.Map)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource.AdLoadException","l":"createForAd(Exception)","url":"createForAd(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource.AdLoadException","l":"createForAdGroup(Exception, int)","url":"createForAdGroup(java.lang.Exception,int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource.AdLoadException","l":"createForAllAds(Exception)","url":"createForAllAds(java.lang.Exception)"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"createForRemote(String)","url":"createForRemote(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"createForRenderer(Exception)","url":"createForRenderer(java.lang.Exception)"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"createForRenderer(Throwable, String, int, Format, int, boolean)","url":"createForRenderer(java.lang.Throwable,java.lang.String,int,com.google.android.exoplayer2.Format,int,boolean)"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"createForRenderer(Throwable, String, int, Format, int)","url":"createForRenderer(java.lang.Throwable,java.lang.String,int,com.google.android.exoplayer2.Format,int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"createForSource(IOException)","url":"createForSource(java.io.IOException)"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"createForUnexpected(RuntimeException)","url":"createForUnexpected(java.lang.RuntimeException)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource.AdLoadException","l":"createForUnexpected(RuntimeException)","url":"createForUnexpected(java.lang.RuntimeException)"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"createFromCaptionStyle(CaptioningManager.CaptionStyle)","url":"createFromCaptionStyle(android.view.accessibility.CaptioningManager.CaptionStyle)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand.ComponentSplice","l":"createFromParcel(Parcel)","url":"createFromParcel(android.os.Parcel)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock","l":"createHandler(Looper, Handler.Callback)","url":"createHandler(android.os.Looper,android.os.Handler.Callback)"},{"p":"com.google.android.exoplayer2.util","c":"Clock","l":"createHandler(Looper, Handler.Callback)","url":"createHandler(android.os.Looper,android.os.Handler.Callback)"},{"p":"com.google.android.exoplayer2.util","c":"SystemClock","l":"createHandler(Looper, Handler.Callback)","url":"createHandler(android.os.Looper,android.os.Handler.Callback)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"createHandler(Looper, Handler.Callback)","url":"createHandler(android.os.Looper,android.os.Handler.Callback)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"createHandlerForCurrentLooper()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"createHandlerForCurrentLooper(Handler.Callback)","url":"createHandlerForCurrentLooper(android.os.Handler.Callback)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"createHandlerForCurrentOrMainLooper()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"createHandlerForCurrentOrMainLooper(Handler.Callback)","url":"createHandlerForCurrentOrMainLooper(android.os.Handler.Callback)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"createImageSampleFormat(String, String, int, List, String)","url":"createImageSampleFormat(java.lang.String,java.lang.String,int,java.util.List,java.lang.String)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DefaultTsPayloadReaderFactory","l":"createInitialPayloadReaders()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.Factory","l":"createInitialPayloadReaders()"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleDecoder","l":"createInputBuffer()"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Gav1Decoder","l":"createInputBuffer()"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacDecoder","l":"createInputBuffer()"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusDecoder","l":"createInputBuffer()"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxDecoder","l":"createInputBuffer()"},{"p":"com.google.android.exoplayer2.text","c":"SimpleSubtitleDecoder","l":"createInputBuffer()"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"createMediaCrypto(byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"createMediaCrypto(byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"createMediaCrypto(byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"createMediaCrypto(byte[])"},{"p":"com.google.android.exoplayer2.util","c":"MediaFormatUtil","l":"createMediaFormatFromFormat(Format)","url":"createMediaFormatFromFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaSource","l":"createMediaPeriod(MediaSource.MediaPeriodId, TrackGroupArray, Allocator, MediaSourceEventListener.EventDispatcher, DrmSessionManager, DrmSessionEventListener.EventDispatcher, TransferListener)","url":"createMediaPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.upstream.Allocator,com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"createMediaPeriod(MediaSource.MediaPeriodId, TrackGroupArray, Allocator, MediaSourceEventListener.EventDispatcher, DrmSessionManager, DrmSessionEventListener.EventDispatcher, TransferListener)","url":"createMediaPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.upstream.Allocator,com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaPeriodAsserts.FilterableManifestMediaPeriodFactory","l":"createMediaPeriod(T, int)","url":"createMediaPeriod(T,int)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Variant","l":"createMediaPlaylistVariantUrl(Uri)","url":"createMediaPlaylistVariantUrl(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource.Factory","l":"createMediaSource()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"createMediaSource(DashManifest, MediaItem)","url":"createMediaSource(com.google.android.exoplayer2.source.dash.manifest.DashManifest,com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"createMediaSource(DashManifest)","url":"createMediaSource(com.google.android.exoplayer2.source.dash.manifest.DashManifest)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"createMediaSource(DownloadRequest, DataSource.Factory, DrmSessionManager)","url":"createMediaSource(com.google.android.exoplayer2.offline.DownloadRequest,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.drm.DrmSessionManager)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"createMediaSource(DownloadRequest, DataSource.Factory)","url":"createMediaSource(com.google.android.exoplayer2.offline.DownloadRequest,com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource.Factory","l":"createMediaSource(MediaItem.Subtitle, long)","url":"createMediaSource(com.google.android.exoplayer2.MediaItem.Subtitle,long)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"createMediaSource(MediaItem)","url":"createMediaSource(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceFactory","l":"createMediaSource(MediaItem)","url":"createMediaSource(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"createMediaSource(MediaItem)","url":"createMediaSource(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"createMediaSource(MediaItem)","url":"createMediaSource(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"createMediaSource(MediaItem)","url":"createMediaSource(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.Factory","l":"createMediaSource(MediaItem)","url":"createMediaSource(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"createMediaSource(MediaItem)","url":"createMediaSource(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"createMediaSource(SsManifest, MediaItem)","url":"createMediaSource(com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest,com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"createMediaSource(SsManifest)","url":"createMediaSource(com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest)"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource.Factory","l":"createMediaSource(Uri, Format, long)","url":"createMediaSource(android.net.Uri,com.google.android.exoplayer2.Format,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceFactory","l":"createMediaSource(Uri)","url":"createMediaSource(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"createMediaSource(Uri)","url":"createMediaSource(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"createMediaSource(Uri)","url":"createMediaSource(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"createMediaSource(Uri)","url":"createMediaSource(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"createMediaSource(Uri)","url":"createMediaSource(android.net.Uri)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"createMessage(PlayerMessage.Target)","url":"createMessage(com.google.android.exoplayer2.PlayerMessage.Target)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"createMessage(PlayerMessage.Target)","url":"createMessage(com.google.android.exoplayer2.PlayerMessage.Target)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"createMessage(PlayerMessage.Target)","url":"createMessage(com.google.android.exoplayer2.PlayerMessage.Target)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"createMetadataInputBuffer(byte[])"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"createNotification(Player, NotificationCompat.Builder, boolean, Bitmap)","url":"createNotification(com.google.android.exoplayer2.Player,androidx.core.app.NotificationCompat.Builder,boolean,android.graphics.Bitmap)"},{"p":"com.google.android.exoplayer2.util","c":"NotificationUtil","l":"createNotificationChannel(Context, String, int, int, int)","url":"createNotificationChannel(android.content.Context,java.lang.String,int,int,int)"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleDecoder","l":"createOutputBuffer()"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Gav1Decoder","l":"createOutputBuffer()"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacDecoder","l":"createOutputBuffer()"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusDecoder","l":"createOutputBuffer()"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxDecoder","l":"createOutputBuffer()"},{"p":"com.google.android.exoplayer2.text","c":"SimpleSubtitleDecoder","l":"createOutputBuffer()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DefaultTsPayloadReaderFactory","l":"createPayloadReader(int, TsPayloadReader.EsInfo)","url":"createPayloadReader(int,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.EsInfo)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.Factory","l":"createPayloadReader(int, TsPayloadReader.EsInfo)","url":"createPayloadReader(int,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.EsInfo)"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","c":"DefaultRtpPayloadReaderFactory","l":"createPayloadReader(RtpPayloadFormat)","url":"createPayloadReader(com.google.android.exoplayer2.source.rtsp.RtpPayloadFormat)"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","c":"RtpPayloadReader.Factory","l":"createPayloadReader(RtpPayloadFormat)","url":"createPayloadReader(com.google.android.exoplayer2.source.rtsp.RtpPayloadFormat)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source","c":"LoopingMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"createPeriod(MediaSource.MediaPeriodId, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,long)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"createPeriod(MediaSource.MediaPeriodId)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"createPeriod(MediaSource.MediaPeriodId)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"createPlaceholder(Object)","url":"createPlaceholder(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistParserFactory","l":"createPlaylistParser()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"FilteringHlsPlaylistParserFactory","l":"createPlaylistParser()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistParserFactory","l":"createPlaylistParser()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistParserFactory","l":"createPlaylistParser(HlsMasterPlaylist, HlsMediaPlaylist)","url":"createPlaylistParser(com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist,com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"FilteringHlsPlaylistParserFactory","l":"createPlaylistParser(HlsMasterPlaylist, HlsMediaPlaylist)","url":"createPlaylistParser(com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist,com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistParserFactory","l":"createPlaylistParser(HlsMasterPlaylist, HlsMediaPlaylist)","url":"createPlaylistParser(com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist,com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaExtractor.Factory","l":"createProgressiveMediaExtractor()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkExtractor.Factory","l":"createProgressiveMediaExtractor(int, Format, boolean, List, TrackOutput)","url":"createProgressiveMediaExtractor(int,com.google.android.exoplayer2.Format,boolean,java.util.List,com.google.android.exoplayer2.extractor.TrackOutput)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"createRendererException(Throwable, Format, boolean)","url":"createRendererException(java.lang.Throwable,com.google.android.exoplayer2.Format,boolean)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"createRendererException(Throwable, Format)","url":"createRendererException(java.lang.Throwable,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"createRenderers(Handler, VideoRendererEventListener, AudioRendererEventListener, TextOutput, MetadataOutput)","url":"createRenderers(android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.text.TextOutput,com.google.android.exoplayer2.metadata.MetadataOutput)"},{"p":"com.google.android.exoplayer2","c":"RenderersFactory","l":"createRenderers(Handler, VideoRendererEventListener, AudioRendererEventListener, TextOutput, MetadataOutput)","url":"createRenderers(android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.text.TextOutput,com.google.android.exoplayer2.metadata.MetadataOutput)"},{"p":"com.google.android.exoplayer2.testutil","c":"CapturingRenderersFactory","l":"createRenderers(Handler, VideoRendererEventListener, AudioRendererEventListener, TextOutput, MetadataOutput)","url":"createRenderers(android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.text.TextOutput,com.google.android.exoplayer2.metadata.MetadataOutput)"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"createRetryAction(boolean, long)","url":"createRetryAction(boolean,long)"},{"p":"com.google.android.exoplayer2.robolectric","c":"RobolectricUtil","l":"createRobolectricConditionVariable()"},{"p":"com.google.android.exoplayer2","c":"Format","l":"createSampleFormat(String, String)","url":"createSampleFormat(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"createSampleStream(Allocator, MediaSourceEventListener.EventDispatcher, DrmSessionManager, DrmSessionEventListener.EventDispatcher, Format, List)","url":"createSampleStream(com.google.android.exoplayer2.upstream.Allocator,com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher,com.google.android.exoplayer2.Format,java.util.List)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"createSeekParamsForTargetTimeUs(long)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"createSessionCreationData(DrmInitData, DrmInitData)","url":"createSessionCreationData(com.google.android.exoplayer2.drm.DrmInitData,com.google.android.exoplayer2.drm.DrmInitData)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"createSingleVariantMasterPlaylist(String)","url":"createSingleVariantMasterPlaylist(java.lang.String)"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea608Decoder","l":"createSubtitle()"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea708Decoder","l":"createSubtitle()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"createTempDirectory(Context, String)","url":"createTempDirectory(android.content.Context,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"createTempFile(Context, String)","url":"createTempFile(android.content.Context,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"createTestFile(File, long)","url":"createTestFile(java.io.File,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"createTestFile(File, String, long)","url":"createTestFile(java.io.File,java.lang.String,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"createTestFile(File, String)","url":"createTestFile(java.io.File,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"createTextContainerFormat(String, String, String, String, String, int, int, int, String, int)","url":"createTextContainerFormat(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,int,int,int,java.lang.String,int)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"createTextContainerFormat(String, String, String, String, String, int, int, int, String)","url":"createTextContainerFormat(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,int,int,int,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"createTextSampleFormat(String, String, int, String, int, long, List)","url":"createTextSampleFormat(java.lang.String,java.lang.String,int,java.lang.String,int,long,java.util.List)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"createTextSampleFormat(String, String, int, String)","url":"createTextSampleFormat(java.lang.String,java.lang.String,int,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker.Factory","l":"createTracker(HlsDataSourceFactory, LoadErrorHandlingPolicy, HlsPlaylistParserFactory)","url":"createTracker(com.google.android.exoplayer2.source.hls.HlsDataSourceFactory,com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy,com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParserFactory)"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","c":"RtpAc3Reader","l":"createTracks(ExtractorOutput, int)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,int)"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","c":"RtpPayloadReader","l":"createTracks(ExtractorOutput, int)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Reader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Reader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsReader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DtsReader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DvbSubtitleReader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"ElementaryStreamReader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H262Reader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H263Reader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H264Reader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H265Reader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Id3Reader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"LatmReader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"MpegAudioReader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"SeiReader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection.Factory","l":"createTrackSelections(ExoTrackSelection.Definition[], BandwidthMeter, MediaSource.MediaPeriodId, Timeline)","url":"createTrackSelections(com.google.android.exoplayer2.trackselection.ExoTrackSelection.Definition[],com.google.android.exoplayer2.upstream.BandwidthMeter,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection.Factory","l":"createTrackSelections(ExoTrackSelection.Definition[], BandwidthMeter, MediaSource.MediaPeriodId, Timeline)","url":"createTrackSelections(com.google.android.exoplayer2.trackselection.ExoTrackSelection.Definition[],com.google.android.exoplayer2.upstream.BandwidthMeter,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.trackselection","c":"RandomTrackSelection.Factory","l":"createTrackSelections(ExoTrackSelection.Definition[], BandwidthMeter, MediaSource.MediaPeriodId, Timeline)","url":"createTrackSelections(com.google.android.exoplayer2.trackselection.ExoTrackSelection.Definition[],com.google.android.exoplayer2.upstream.BandwidthMeter,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionUtil","l":"createTrackSelectionsForDefinitions(ExoTrackSelection.Definition[], TrackSelectionUtil.AdaptiveTrackSelectionFactory)","url":"createTrackSelectionsForDefinitions(com.google.android.exoplayer2.trackselection.ExoTrackSelection.Definition[],com.google.android.exoplayer2.trackselection.TrackSelectionUtil.AdaptiveTrackSelectionFactory)"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleDecoder","l":"createUnexpectedDecodeException(Throwable)","url":"createUnexpectedDecodeException(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Gav1Decoder","l":"createUnexpectedDecodeException(Throwable)","url":"createUnexpectedDecodeException(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacDecoder","l":"createUnexpectedDecodeException(Throwable)","url":"createUnexpectedDecodeException(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusDecoder","l":"createUnexpectedDecodeException(Throwable)","url":"createUnexpectedDecodeException(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxDecoder","l":"createUnexpectedDecodeException(Throwable)","url":"createUnexpectedDecodeException(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.text","c":"SimpleSubtitleDecoder","l":"createUnexpectedDecodeException(Throwable)","url":"createUnexpectedDecodeException(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"createVideoContainerFormat(String, String, String, String, String, Metadata, int, int, int, float, List, int, int)","url":"createVideoContainerFormat(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,com.google.android.exoplayer2.metadata.Metadata,int,int,int,float,java.util.List,int,int)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"createVideoSampleFormat(String, String, String, int, int, int, int, float, List, DrmInitData)","url":"createVideoSampleFormat(java.lang.String,java.lang.String,java.lang.String,int,int,int,int,float,java.util.List,com.google.android.exoplayer2.drm.DrmInitData)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"createVideoSampleFormat(String, String, String, int, int, int, int, float, List, int, float, byte[], int, ColorInfo, DrmInitData)","url":"createVideoSampleFormat(java.lang.String,java.lang.String,java.lang.String,int,int,int,int,float,java.util.List,int,float,byte[],int,com.google.android.exoplayer2.video.ColorInfo,com.google.android.exoplayer2.drm.DrmInitData)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"createVideoSampleFormat(String, String, String, int, int, int, int, float, List, int, float, DrmInitData)","url":"createVideoSampleFormat(java.lang.String,java.lang.String,java.lang.String,int,int,int,int,float,java.util.List,int,float,com.google.android.exoplayer2.drm.DrmInitData)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"createWithDrm(Allocator, Looper, DrmSessionManager, DrmSessionEventListener.EventDispatcher)","url":"createWithDrm(com.google.android.exoplayer2.upstream.Allocator,android.os.Looper,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"createWithNotificationChannel(Context, String, int, int, int, PlayerNotificationManager.MediaDescriptionAdapter, PlayerNotificationManager.NotificationListener)","url":"createWithNotificationChannel(android.content.Context,java.lang.String,int,int,int,com.google.android.exoplayer2.ui.PlayerNotificationManager.MediaDescriptionAdapter,com.google.android.exoplayer2.ui.PlayerNotificationManager.NotificationListener)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"createWithNotificationChannel(Context, String, int, int, int, PlayerNotificationManager.MediaDescriptionAdapter)","url":"createWithNotificationChannel(android.content.Context,java.lang.String,int,int,int,com.google.android.exoplayer2.ui.PlayerNotificationManager.MediaDescriptionAdapter)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"createWithNotificationChannel(Context, String, int, int, PlayerNotificationManager.MediaDescriptionAdapter, PlayerNotificationManager.NotificationListener)","url":"createWithNotificationChannel(android.content.Context,java.lang.String,int,int,com.google.android.exoplayer2.ui.PlayerNotificationManager.MediaDescriptionAdapter,com.google.android.exoplayer2.ui.PlayerNotificationManager.NotificationListener)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"createWithNotificationChannel(Context, String, int, int, PlayerNotificationManager.MediaDescriptionAdapter)","url":"createWithNotificationChannel(android.content.Context,java.lang.String,int,int,com.google.android.exoplayer2.ui.PlayerNotificationManager.MediaDescriptionAdapter)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"createWithoutDrm(Allocator)","url":"createWithoutDrm(com.google.android.exoplayer2.upstream.Allocator)"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"Format","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"HeartRating","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"MediaItem.ClippingProperties","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"MediaItem.LiveConfiguration","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"PercentageRating","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"PlaybackParameters","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"Rating","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"StarRating","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"ThumbRating","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"CREATOR"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes","l":"CREATOR"},{"p":"com.google.android.exoplayer2.device","c":"DeviceInfo","l":"CREATOR"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"CREATOR"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","c":"AppInfoTable","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"VorbisComment","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyInfo","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ApicFrame","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"BinaryFrame","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterTocFrame","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"CommentFrame","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"GeobFrame","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"InternalFrame","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"MlltFrame","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"PrivFrame","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"TextInformationFrame","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"UrlLinkFrame","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MdtaMetadataEntry","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MotionPhotoMetadata","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData.Segment","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SmtaMetadataEntry","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"PrivateCommand","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceNullCommand","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"TimeSignalCommand","l":"CREATOR"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"CREATOR"},{"p":"com.google.android.exoplayer2.offline","c":"StreamKey","l":"CREATOR"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"CREATOR"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroup","l":"CREATOR"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroupArray","l":"CREATOR"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"CREATOR"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"CREATOR"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry","l":"CREATOR"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry.VariantInfo","l":"CREATOR"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"CREATOR"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.SelectionOverride","l":"CREATOR"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"CREATOR"},{"p":"com.google.android.exoplayer2.video","c":"ColorInfo","l":"CREATOR"},{"p":"com.google.android.exoplayer2.video","c":"VideoSize","l":"CREATOR"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.OpenException","l":"cronetConnectionStatus"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"CronetDataSource(CronetEngine, Executor, int, int, boolean, HttpDataSource.RequestProperties, boolean)","url":"%3Cinit%3E(org.chromium.net.CronetEngine,java.util.concurrent.Executor,int,int,boolean,com.google.android.exoplayer2.upstream.HttpDataSource.RequestProperties,boolean)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"CronetDataSource(CronetEngine, Executor, int, int, boolean, HttpDataSource.RequestProperties)","url":"%3Cinit%3E(org.chromium.net.CronetEngine,java.util.concurrent.Executor,int,int,boolean,com.google.android.exoplayer2.upstream.HttpDataSource.RequestProperties)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"CronetDataSource(CronetEngine, Executor, Predicate, int, int, boolean, HttpDataSource.RequestProperties, boolean)","url":"%3Cinit%3E(org.chromium.net.CronetEngine,java.util.concurrent.Executor,com.google.common.base.Predicate,int,int,boolean,com.google.android.exoplayer2.upstream.HttpDataSource.RequestProperties,boolean)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"CronetDataSource(CronetEngine, Executor, Predicate, int, int, boolean, HttpDataSource.RequestProperties)","url":"%3Cinit%3E(org.chromium.net.CronetEngine,java.util.concurrent.Executor,com.google.common.base.Predicate,int,int,boolean,com.google.android.exoplayer2.upstream.HttpDataSource.RequestProperties)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"CronetDataSource(CronetEngine, Executor, Predicate)","url":"%3Cinit%3E(org.chromium.net.CronetEngine,java.util.concurrent.Executor,com.google.common.base.Predicate)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"CronetDataSource(CronetEngine, Executor)","url":"%3Cinit%3E(org.chromium.net.CronetEngine,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"CronetDataSourceFactory(CronetEngineWrapper, Executor, HttpDataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper,java.util.concurrent.Executor,com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"CronetDataSourceFactory(CronetEngineWrapper, Executor, int, int, boolean, HttpDataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper,java.util.concurrent.Executor,int,int,boolean,com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"CronetDataSourceFactory(CronetEngineWrapper, Executor, int, int, boolean, String)","url":"%3Cinit%3E(com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper,java.util.concurrent.Executor,int,int,boolean,java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"CronetDataSourceFactory(CronetEngineWrapper, Executor, String)","url":"%3Cinit%3E(com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper,java.util.concurrent.Executor,java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"CronetDataSourceFactory(CronetEngineWrapper, Executor, TransferListener, HttpDataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper,java.util.concurrent.Executor,com.google.android.exoplayer2.upstream.TransferListener,com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"CronetDataSourceFactory(CronetEngineWrapper, Executor, TransferListener, int, int, boolean, HttpDataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper,java.util.concurrent.Executor,com.google.android.exoplayer2.upstream.TransferListener,int,int,boolean,com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"CronetDataSourceFactory(CronetEngineWrapper, Executor, TransferListener, int, int, boolean, String)","url":"%3Cinit%3E(com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper,java.util.concurrent.Executor,com.google.android.exoplayer2.upstream.TransferListener,int,int,boolean,java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"CronetDataSourceFactory(CronetEngineWrapper, Executor, TransferListener, String)","url":"%3Cinit%3E(com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper,java.util.concurrent.Executor,com.google.android.exoplayer2.upstream.TransferListener,java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"CronetDataSourceFactory(CronetEngineWrapper, Executor, TransferListener)","url":"%3Cinit%3E(com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper,java.util.concurrent.Executor,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"CronetDataSourceFactory(CronetEngineWrapper, Executor)","url":"%3Cinit%3E(com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetEngineWrapper","l":"CronetEngineWrapper(Context, String, boolean)","url":"%3Cinit%3E(android.content.Context,java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetEngineWrapper","l":"CronetEngineWrapper(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetEngineWrapper","l":"CronetEngineWrapper(CronetEngine)","url":"%3Cinit%3E(org.chromium.net.CronetEngine)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter.Configuration","l":"crypto"},{"p":"com.google.android.exoplayer2","c":"C","l":"CRYPTO_MODE_AES_CBC"},{"p":"com.google.android.exoplayer2","c":"C","l":"CRYPTO_MODE_AES_CTR"},{"p":"com.google.android.exoplayer2","c":"C","l":"CRYPTO_MODE_UNENCRYPTED"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"TrackEncryptionBox","l":"cryptoData"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput.CryptoData","l":"CryptoData(int, byte[], int, int)","url":"%3Cinit%3E(int,byte[],int,int)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"cryptoInfo"},{"p":"com.google.android.exoplayer2.decoder","c":"CryptoInfo","l":"CryptoInfo()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput.CryptoData","l":"cryptoMode"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"csrc"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"CSRC_SIZE"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"csrcCount"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCueInfo","l":"cue"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCueParser","l":"CUE_HEADER_PATTERN"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"Cue(CharSequence, Layout.Alignment, float, int, int, float, int, float, boolean, int)","url":"%3Cinit%3E(java.lang.CharSequence,android.text.Layout.Alignment,float,int,int,float,int,float,boolean,int)"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"Cue(CharSequence, Layout.Alignment, float, int, int, float, int, float, int, float)","url":"%3Cinit%3E(java.lang.CharSequence,android.text.Layout.Alignment,float,int,int,float,int,float,int,float)"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"Cue(CharSequence, Layout.Alignment, float, int, int, float, int, float)","url":"%3Cinit%3E(java.lang.CharSequence,android.text.Layout.Alignment,float,int,int,float,int,float)"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"Cue(CharSequence)","url":"%3Cinit%3E(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"CURRENT_POSITION_NOT_SET"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer.InsufficientCapacityException","l":"currentCapacity"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"currentMediaPeriodId"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"currentPlaybackPositionMs"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"currentTimeline"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock","l":"currentTimeMillis()"},{"p":"com.google.android.exoplayer2.util","c":"Clock","l":"currentTimeMillis()"},{"p":"com.google.android.exoplayer2.util","c":"SystemClock","l":"currentTimeMillis()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"currentWindowIndex"},{"p":"com.google.android.exoplayer2","c":"MediaItem.PlaybackProperties","l":"customCacheKey"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"customCacheKey"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"customData"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"d(String, String, Throwable)","url":"d(java.lang.String,java.lang.String,java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"d(String, String)","url":"d(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.offline","c":"DashDownloader","l":"DashDownloader(MediaItem, CacheDataSource.Factory, Executor)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.source.dash.offline","c":"DashDownloader","l":"DashDownloader(MediaItem, CacheDataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.dash.offline","c":"DashDownloader","l":"DashDownloader(MediaItem, ParsingLoadable.Parser, CacheDataSource.Factory, Executor)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.upstream.ParsingLoadable.Parser,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.source.dash.offline","c":"DashDownloader","l":"DashDownloader(Uri, List, CacheDataSource.Factory, Executor)","url":"%3Cinit%3E(android.net.Uri,java.util.List,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.source.dash.offline","c":"DashDownloader","l":"DashDownloader(Uri, List, CacheDataSource.Factory)","url":"%3Cinit%3E(android.net.Uri,java.util.List,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"DashManifest(long, long, long, boolean, long, long, long, long, ProgramInformation, UtcTimingElement, ServiceDescriptionElement, Uri, List)","url":"%3Cinit%3E(long,long,long,boolean,long,long,long,long,com.google.android.exoplayer2.source.dash.manifest.ProgramInformation,com.google.android.exoplayer2.source.dash.manifest.UtcTimingElement,com.google.android.exoplayer2.source.dash.manifest.ServiceDescriptionElement,android.net.Uri,java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"DashManifestParser()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashManifestStaleException","l":"DashManifestStaleException()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashWrappingSegmentIndex","l":"DashWrappingSegmentIndex(ChunkIndex, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.ChunkIndex,long)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"data"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleOutputBuffer","l":"data"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"data"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.VorbisIdHeader","l":"data"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"BinaryFrame","l":"data"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"GeobFrame","l":"data"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"data"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.ProtectionElement","l":"data"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData.Segment","l":"data"},{"p":"com.google.android.exoplayer2.upstream","c":"Allocation","l":"data"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"data"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"data"},{"p":"com.google.android.exoplayer2.audio","c":"WavUtil","l":"DATA_FOURCC"},{"p":"com.google.android.exoplayer2","c":"C","l":"DATA_TYPE_AD"},{"p":"com.google.android.exoplayer2","c":"C","l":"DATA_TYPE_CUSTOM_BASE"},{"p":"com.google.android.exoplayer2","c":"C","l":"DATA_TYPE_DRM"},{"p":"com.google.android.exoplayer2","c":"C","l":"DATA_TYPE_MANIFEST"},{"p":"com.google.android.exoplayer2","c":"C","l":"DATA_TYPE_MEDIA"},{"p":"com.google.android.exoplayer2","c":"C","l":"DATA_TYPE_MEDIA_INITIALIZATION"},{"p":"com.google.android.exoplayer2","c":"C","l":"DATA_TYPE_MEDIA_PROGRESSIVE_LIVE"},{"p":"com.google.android.exoplayer2","c":"C","l":"DATA_TYPE_TIME_SYNCHRONIZATION"},{"p":"com.google.android.exoplayer2","c":"C","l":"DATA_TYPE_UNKNOWN"},{"p":"com.google.android.exoplayer2.database","c":"ExoDatabaseProvider","l":"DATABASE_NAME"},{"p":"com.google.android.exoplayer2.database","c":"DatabaseIOException","l":"DatabaseIOException(SQLException, String)","url":"%3Cinit%3E(android.database.SQLException,java.lang.String)"},{"p":"com.google.android.exoplayer2.database","c":"DatabaseIOException","l":"DatabaseIOException(SQLException)","url":"%3Cinit%3E(android.database.SQLException)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"DataChunk","l":"DataChunk(DataSource, DataSpec, int, Format, int, Object, byte[])","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,int,com.google.android.exoplayer2.Format,int,java.lang.Object,byte[])"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSchemeDataSource","l":"DataSchemeDataSource()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource.Factory","l":"dataSetFactory"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"dataSource"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"DataSourceContractTest()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceException","l":"DataSourceException(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource.Factory","l":"dataSourceFactory"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceInputStream","l":"DataSourceInputStream(DataSource, DataSpec)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.drm","c":"MediaDrmCallbackException","l":"dataSpec"},{"p":"com.google.android.exoplayer2.offline","c":"SegmentDownloader.Segment","l":"dataSpec"},{"p":"com.google.android.exoplayer2.source","c":"LoadEventInfo","l":"dataSpec"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"dataSpec"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.HttpDataSourceException","l":"dataSpec"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"dataSpec"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"DataSpec(Uri, byte[], long, long, long, String, int)","url":"%3Cinit%3E(android.net.Uri,byte[],long,long,long,java.lang.String,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"DataSpec(Uri, int, byte[], long, long, long, String, int, Map)","url":"%3Cinit%3E(android.net.Uri,int,byte[],long,long,long,java.lang.String,int,java.util.Map)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"DataSpec(Uri, int, byte[], long, long, long, String, int)","url":"%3Cinit%3E(android.net.Uri,int,byte[],long,long,long,java.lang.String,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"DataSpec(Uri, int)","url":"%3Cinit%3E(android.net.Uri,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"DataSpec(Uri, long, long, long, String, int)","url":"%3Cinit%3E(android.net.Uri,long,long,long,java.lang.String,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"DataSpec(Uri, long, long, String, int, Map)","url":"%3Cinit%3E(android.net.Uri,long,long,java.lang.String,int,java.util.Map)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"DataSpec(Uri, long, long, String, int)","url":"%3Cinit%3E(android.net.Uri,long,long,java.lang.String,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"DataSpec(Uri, long, long, String)","url":"%3Cinit%3E(android.net.Uri,long,long,java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"DataSpec(Uri, long, long)","url":"%3Cinit%3E(android.net.Uri,long,long)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"DataSpec(Uri)","url":"%3Cinit%3E(android.net.Uri)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"dataSpecWithEndPositionOutOfRange_readsToEnd()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"dataSpecWithLength_readExpectedRange()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"dataSpecWithPosition_readUntilEnd()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"dataSpecWithPositionAndLength_readExpectedRange()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"dataSpecWithPositionAtEnd_throwsPositionOutOfRangeException()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"dataSpecWithPositionAtEndAndLength_throwsPositionOutOfRangeException()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"dataSpecWithPositionOutOfRange_throwsPositionOutOfRangeException()"},{"p":"com.google.android.exoplayer2.source","c":"MediaLoadData","l":"dataType"},{"p":"com.google.android.exoplayer2.util","c":"DebugTextViewHelper","l":"DebugTextViewHelper(SimpleExoPlayer, TextView)","url":"%3Cinit%3E(com.google.android.exoplayer2.SimpleExoPlayer,android.widget.TextView)"},{"p":"com.google.android.exoplayer2.text","c":"SimpleSubtitleDecoder","l":"decode(byte[], int, boolean)","url":"decode(byte[],int,boolean)"},{"p":"com.google.android.exoplayer2.text.dvb","c":"DvbDecoder","l":"decode(byte[], int, boolean)","url":"decode(byte[],int,boolean)"},{"p":"com.google.android.exoplayer2.text.pgs","c":"PgsDecoder","l":"decode(byte[], int, boolean)","url":"decode(byte[],int,boolean)"},{"p":"com.google.android.exoplayer2.text.ssa","c":"SsaDecoder","l":"decode(byte[], int, boolean)","url":"decode(byte[],int,boolean)"},{"p":"com.google.android.exoplayer2.text.subrip","c":"SubripDecoder","l":"decode(byte[], int, boolean)","url":"decode(byte[],int,boolean)"},{"p":"com.google.android.exoplayer2.text.ttml","c":"TtmlDecoder","l":"decode(byte[], int, boolean)","url":"decode(byte[],int,boolean)"},{"p":"com.google.android.exoplayer2.text.tx3g","c":"Tx3gDecoder","l":"decode(byte[], int, boolean)","url":"decode(byte[],int,boolean)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"Mp4WebvttDecoder","l":"decode(byte[], int, boolean)","url":"decode(byte[],int,boolean)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttDecoder","l":"decode(byte[], int, boolean)","url":"decode(byte[],int,boolean)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"Id3Decoder","l":"decode(byte[], int)","url":"decode(byte[],int)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacDecoder","l":"decode(DecoderInputBuffer, SimpleOutputBuffer, boolean)","url":"decode(com.google.android.exoplayer2.decoder.DecoderInputBuffer,com.google.android.exoplayer2.decoder.SimpleOutputBuffer,boolean)"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusDecoder","l":"decode(DecoderInputBuffer, SimpleOutputBuffer, boolean)","url":"decode(com.google.android.exoplayer2.decoder.DecoderInputBuffer,com.google.android.exoplayer2.decoder.SimpleOutputBuffer,boolean)"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleDecoder","l":"decode(I, O, boolean)","url":"decode(I,O,boolean)"},{"p":"com.google.android.exoplayer2.metadata","c":"SimpleMetadataDecoder","l":"decode(MetadataInputBuffer, ByteBuffer)","url":"decode(com.google.android.exoplayer2.metadata.MetadataInputBuffer,java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","c":"AppInfoTableDecoder","l":"decode(MetadataInputBuffer, ByteBuffer)","url":"decode(com.google.android.exoplayer2.metadata.MetadataInputBuffer,java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessageDecoder","l":"decode(MetadataInputBuffer, ByteBuffer)","url":"decode(com.google.android.exoplayer2.metadata.MetadataInputBuffer,java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyDecoder","l":"decode(MetadataInputBuffer, ByteBuffer)","url":"decode(com.google.android.exoplayer2.metadata.MetadataInputBuffer,java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"Id3Decoder","l":"decode(MetadataInputBuffer, ByteBuffer)","url":"decode(com.google.android.exoplayer2.metadata.MetadataInputBuffer,java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInfoDecoder","l":"decode(MetadataInputBuffer, ByteBuffer)","url":"decode(com.google.android.exoplayer2.metadata.MetadataInputBuffer,java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataDecoder","l":"decode(MetadataInputBuffer)","url":"decode(com.google.android.exoplayer2.metadata.MetadataInputBuffer)"},{"p":"com.google.android.exoplayer2.metadata","c":"SimpleMetadataDecoder","l":"decode(MetadataInputBuffer)","url":"decode(com.google.android.exoplayer2.metadata.MetadataInputBuffer)"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessageDecoder","l":"decode(ParsableByteArray)","url":"decode(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.text","c":"SimpleSubtitleDecoder","l":"decode(SubtitleInputBuffer, SubtitleOutputBuffer, boolean)","url":"decode(com.google.android.exoplayer2.text.SubtitleInputBuffer,com.google.android.exoplayer2.text.SubtitleOutputBuffer,boolean)"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea608Decoder","l":"decode(SubtitleInputBuffer)","url":"decode(com.google.android.exoplayer2.text.SubtitleInputBuffer)"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea708Decoder","l":"decode(SubtitleInputBuffer)","url":"decode(com.google.android.exoplayer2.text.SubtitleInputBuffer)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Gav1Decoder","l":"decode(VideoDecoderInputBuffer, VideoDecoderOutputBuffer, boolean)","url":"decode(com.google.android.exoplayer2.video.VideoDecoderInputBuffer,com.google.android.exoplayer2.video.VideoDecoderOutputBuffer,boolean)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxDecoder","l":"decode(VideoDecoderInputBuffer, VideoDecoderOutputBuffer, boolean)","url":"decode(com.google.android.exoplayer2.video.VideoDecoderInputBuffer,com.google.android.exoplayer2.video.VideoDecoderOutputBuffer,boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"DecoderAudioRenderer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"DecoderAudioRenderer(Handler, AudioRendererEventListener, AudioCapabilities, AudioProcessor...)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioCapabilities,com.google.android.exoplayer2.audio.AudioProcessor...)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"DecoderAudioRenderer(Handler, AudioRendererEventListener, AudioProcessor...)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioProcessor...)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"DecoderAudioRenderer(Handler, AudioRendererEventListener, AudioSink)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioSink)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"decoderCounters"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"decoderCounters"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"DecoderCounters()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderException","l":"DecoderException(String, Throwable)","url":"%3Cinit%3E(java.lang.String,java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderException","l":"DecoderException(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderException","l":"DecoderException(Throwable)","url":"%3Cinit%3E(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"decoderInitCount"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer.DecoderInitializationException","l":"DecoderInitializationException(Format, Throwable, boolean, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format,java.lang.Throwable,boolean,int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer.DecoderInitializationException","l":"DecoderInitializationException(Format, Throwable, boolean, MediaCodecInfo)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format,java.lang.Throwable,boolean,com.google.android.exoplayer2.mediacodec.MediaCodecInfo)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener.EventDispatcher","l":"decoderInitialized(String, long, long)","url":"decoderInitialized(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener.EventDispatcher","l":"decoderInitialized(String, long, long)","url":"decoderInitialized(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"DecoderInputBuffer(int, int)","url":"%3Cinit%3E(int,int)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"DecoderInputBuffer(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"decoderName"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"decoderPrivate"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"decoderReleaseCount"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener.EventDispatcher","l":"decoderReleased(String)","url":"decoderReleased(java.lang.String)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener.EventDispatcher","l":"decoderReleased(String)","url":"decoderReleased(java.lang.String)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DecoderReuseEvaluation(String, Format, Format, int, int)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format,int,int)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"DecoderVideoRenderer(long, Handler, VideoRendererEventListener, int)","url":"%3Cinit%3E(long,android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener,int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.DeviceComponent","l":"decreaseDeviceVolume()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"decreaseDeviceVolume()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"decreaseDeviceVolume()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"decreaseDeviceVolume()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"decreaseDeviceVolume()"},{"p":"com.google.android.exoplayer2.drm","c":"DecryptionException","l":"DecryptionException(int, String)","url":"%3Cinit%3E(int,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts.AssertionConfig","l":"deduplicateConsecutiveFormats"},{"p":"com.google.android.exoplayer2","c":"PlaybackParameters","l":"DEFAULT"},{"p":"com.google.android.exoplayer2","c":"RendererConfiguration","l":"DEFAULT"},{"p":"com.google.android.exoplayer2","c":"SeekParameters","l":"DEFAULT"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes","l":"DEFAULT"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter.Factory","l":"DEFAULT"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecSelector","l":"DEFAULT"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataDecoderFactory","l":"DEFAULT"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsExtractorFactory","l":"DEFAULT"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleDecoderFactory","l":"DEFAULT"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"DEFAULT"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"DEFAULT"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheKeyFactory","l":"DEFAULT"},{"p":"com.google.android.exoplayer2.util","c":"Clock","l":"DEFAULT"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DEFAULT_AD_MARKER_COLOR"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DEFAULT_AD_MARKER_WIDTH_DP"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"DEFAULT_AD_PRELOAD_TIMEOUT_MS"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"DEFAULT_ALLOWED_VIDEO_JOINING_TIME_MS"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_AUDIO_BUFFER_SIZE"},{"p":"com.google.android.exoplayer2.audio","c":"AudioCapabilities","l":"DEFAULT_AUDIO_CAPABILITIES"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_BACK_BUFFER_DURATION_MS"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"DEFAULT_BANDWIDTH_FRACTION"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DEFAULT_BAR_HEIGHT_DP"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"DEFAULT_BOTTOM_PADDING_FRACTION"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_BUFFER_FOR_PLAYBACK_MS"},{"p":"com.google.android.exoplayer2","c":"C","l":"DEFAULT_BUFFER_SEGMENT_SIZE"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink","l":"DEFAULT_BUFFER_SIZE"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheWriter","l":"DEFAULT_BUFFER_SIZE_BYTES"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DEFAULT_BUFFERED_COLOR"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"DEFAULT_BUFFERED_FRACTION_TO_LIVE_EDGE_FOR_QUALITY_INCREASE"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_CAMERA_MOTION_BUFFER_SIZE"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"DEFAULT_CONNECT_TIMEOUT_MILLIS"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"DEFAULT_CONNECT_TIMEOUT_MILLIS"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"DEFAULT_CONNECT_TIMEOUT_MILLIS"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"DEFAULT_DETACH_SURFACE_TIMEOUT_MS"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"DEFAULT_FACTORY"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl","l":"DEFAULT_FALLBACK_MAX_PLAYBACK_SPEED"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl","l":"DEFAULT_FALLBACK_MIN_PLAYBACK_SPEED"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource","l":"DEFAULT_FALLBACK_TARGET_LIVE_OFFSET_MS"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"DEFAULT_FAST_FORWARD_MS"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"DEFAULT_FOREGROUND_NOTIFICATION_UPDATE_INTERVAL"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink","l":"DEFAULT_FRAGMENT_SIZE"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"DEFAULT_INITIAL_BITRATE_COUNTRY_GROUPS"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"DEFAULT_INITIAL_BITRATE_ESTIMATE"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"DEFAULT_INITIAL_BITRATE_ESTIMATES_2G"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"DEFAULT_INITIAL_BITRATE_ESTIMATES_3G"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"DEFAULT_INITIAL_BITRATE_ESTIMATES_4G"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"DEFAULT_INITIAL_BITRATE_ESTIMATES_5G_NSA"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"DEFAULT_INITIAL_BITRATE_ESTIMATES_5G_SA"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"DEFAULT_INITIAL_BITRATE_ESTIMATES_WIFI"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource","l":"DEFAULT_LIVE_PRESENTATION_DELAY_MS"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource","l":"DEFAULT_LIVE_PRESENTATION_DELAY_MS"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource","l":"DEFAULT_LOADING_CHECK_INTERVAL_BYTES"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_MAX_BUFFER_MS"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl","l":"DEFAULT_MAX_LIVE_OFFSET_ERROR_MS_FOR_UNIT_SPEED"},{"p":"com.google.android.exoplayer2.upstream","c":"UdpDataSource","l":"DEFAULT_MAX_PACKET_SIZE"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"DEFAULT_MAX_PARALLEL_DOWNLOADS"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueNavigator","l":"DEFAULT_MAX_QUEUE_SIZE"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"DEFAULT_MEDIA_ID"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource","l":"DEFAULT_MEDIA_ID"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_METADATA_BUFFER_SIZE"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_MIN_BUFFER_MS"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_MIN_BUFFER_SIZE"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultLoadErrorHandlingPolicy","l":"DEFAULT_MIN_LOADABLE_RETRY_COUNT"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultLoadErrorHandlingPolicy","l":"DEFAULT_MIN_LOADABLE_RETRY_COUNT_PROGRESSIVE_LIVE"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl","l":"DEFAULT_MIN_POSSIBLE_LIVE_OFFSET_SMOOTHING_FACTOR"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"DEFAULT_MIN_RETRY_COUNT"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl","l":"DEFAULT_MIN_UPDATE_INTERVAL_MS"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"DEFAULT_MINIMUM_SILENCE_DURATION_US"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_MUXED_BUFFER_SIZE"},{"p":"com.google.android.exoplayer2.util","c":"SntpClient","l":"DEFAULT_NTP_HOST"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"DEFAULT_PADDING_SILENCE_US"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"DEFAULT_PLAYBACK_ACTIONS"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"DEFAULT_PLAYBACK_SPEED"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DEFAULT_PLAYED_AD_MARKER_COLOR"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DEFAULT_PLAYED_COLOR"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"DEFAULT_PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_PRIORITIZE_TIME_OVER_SIZE_THRESHOLDS"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl","l":"DEFAULT_PROPORTIONAL_CONTROL_FACTOR"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"DEFAULT_PROVIDER"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"DEFAULT_READ_TIMEOUT_MILLIS"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"DEFAULT_READ_TIMEOUT_MILLIS"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"DEFAULT_READ_TIMEOUT_MILLIS"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"DEFAULT_RELEASE_TIMEOUT_MS"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"RepeatModeActionProvider","l":"DEFAULT_REPEAT_TOGGLE_MODES"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"DEFAULT_REPEAT_TOGGLE_MODES"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"DEFAULT_REPEAT_TOGGLE_MODES"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"DEFAULT_REQUIREMENTS"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_RETAIN_BACK_BUFFER_FROM_KEYFRAME"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"DEFAULT_REWIND_MS"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DEFAULT_SCRUBBER_COLOR"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DEFAULT_SCRUBBER_DISABLED_SIZE_DP"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DEFAULT_SCRUBBER_DRAGGED_SIZE_DP"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DEFAULT_SCRUBBER_ENABLED_SIZE_DP"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"DEFAULT_SEEK_TIMEOUT_MS"},{"p":"com.google.android.exoplayer2.analytics","c":"DefaultPlaybackSessionManager","l":"DEFAULT_SESSION_ID_GENERATOR"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"DEFAULT_SESSION_KEEPALIVE_MS"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"DEFAULT_SHOW_TIMEOUT_MS"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"DEFAULT_SHOW_TIMEOUT_MS"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"DEFAULT_SILENCE_THRESHOLD_LEVEL"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"DEFAULT_SLIDING_WINDOW_MAX_WEIGHT"},{"p":"com.google.android.exoplayer2.upstream","c":"UdpDataSource","l":"DEFAULT_SOCKET_TIMEOUT_MILLIS"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_TARGET_BUFFER_BYTES"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl","l":"DEFAULT_TARGET_LIVE_OFFSET_INCREMENT_ON_REBUFFER_MS"},{"p":"com.google.android.exoplayer2.testutil","c":"DumpFileAsserts","l":"DEFAULT_TEST_ASSET_DIRECTORY"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_TEXT_BUFFER_SIZE"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"DEFAULT_TEXT_SIZE_FRACTION"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"DEFAULT_TIME_BAR_MIN_UPDATE_INTERVAL_MS"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"DEFAULT_TIME_BAR_MIN_UPDATE_INTERVAL_MS"},{"p":"com.google.android.exoplayer2.robolectric","c":"RobolectricUtil","l":"DEFAULT_TIMEOUT_MS"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource","l":"DEFAULT_TIMEOUT_MS"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"DEFAULT_TIMESTAMP_SEARCH_BYTES"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DEFAULT_TOUCH_TARGET_HEIGHT_DP"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultLoadErrorHandlingPolicy","l":"DEFAULT_TRACK_BLACKLIST_MS"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"DEFAULT_TRACK_SELECTOR_PARAMETERS"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"DEFAULT_TRACK_SELECTOR_PARAMETERS_WITHOUT_CONTEXT"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"DEFAULT_TRACK_SELECTOR_PARAMETERS_WITHOUT_VIEWPORT"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DEFAULT_UNPLAYED_COLOR"},{"p":"com.google.android.exoplayer2","c":"ExoPlayerLibraryInfo","l":"DEFAULT_USER_AGENT"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_VIDEO_BUFFER_SIZE"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"DEFAULT_WINDOW_DURATION_US"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"DEFAULT_WITHOUT_CONTEXT"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"DEFAULT_WITHOUT_CONTEXT"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultAllocator","l":"DefaultAllocator(boolean, int, int)","url":"%3Cinit%3E(boolean,int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultAllocator","l":"DefaultAllocator(boolean, int)","url":"%3Cinit%3E(boolean,int)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.DefaultAllowedCommandProvider","l":"DefaultAllowedCommandProvider(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink.DefaultAudioProcessorChain","l":"DefaultAudioProcessorChain(AudioProcessor...)","url":"%3Cinit%3E(com.google.android.exoplayer2.audio.AudioProcessor...)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink.DefaultAudioProcessorChain","l":"DefaultAudioProcessorChain(AudioProcessor[], SilenceSkippingAudioProcessor, SonicAudioProcessor)","url":"%3Cinit%3E(com.google.android.exoplayer2.audio.AudioProcessor[],com.google.android.exoplayer2.audio.SilenceSkippingAudioProcessor,com.google.android.exoplayer2.audio.SonicAudioProcessor)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"DefaultAudioSink(AudioCapabilities, AudioProcessor[], boolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.audio.AudioCapabilities,com.google.android.exoplayer2.audio.AudioProcessor[],boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"DefaultAudioSink(AudioCapabilities, AudioProcessor[])","url":"%3Cinit%3E(com.google.android.exoplayer2.audio.AudioCapabilities,com.google.android.exoplayer2.audio.AudioProcessor[])"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"DefaultAudioSink(AudioCapabilities, DefaultAudioSink.AudioProcessorChain, boolean, boolean, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.audio.AudioCapabilities,com.google.android.exoplayer2.audio.DefaultAudioSink.AudioProcessorChain,boolean,boolean,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"DefaultBandwidthMeter()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"DefaultCastOptionsProvider","l":"DefaultCastOptionsProvider()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source","c":"DefaultCompositeSequenceableLoaderFactory","l":"DefaultCompositeSequenceableLoaderFactory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"DefaultContentMetadata","l":"DefaultContentMetadata()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"DefaultContentMetadata","l":"DefaultContentMetadata(Map)","url":"%3Cinit%3E(java.util.Map)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"DefaultControlDispatcher()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"DefaultControlDispatcher(long, long)","url":"%3Cinit%3E(long,long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"DefaultDashChunkSource(ChunkExtractor.Factory, LoaderErrorThrower, DashManifest, int, int[], ExoTrackSelection, int, DataSource, long, int, boolean, List, PlayerEmsgHandler.PlayerTrackEmsgHandler)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.chunk.ChunkExtractor.Factory,com.google.android.exoplayer2.upstream.LoaderErrorThrower,com.google.android.exoplayer2.source.dash.manifest.DashManifest,int,int[],com.google.android.exoplayer2.trackselection.ExoTrackSelection,int,com.google.android.exoplayer2.upstream.DataSource,long,int,boolean,java.util.List,com.google.android.exoplayer2.source.dash.PlayerEmsgHandler.PlayerTrackEmsgHandler)"},{"p":"com.google.android.exoplayer2.database","c":"DefaultDatabaseProvider","l":"DefaultDatabaseProvider(SQLiteOpenHelper)","url":"%3Cinit%3E(android.database.sqlite.SQLiteOpenHelper)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSource","l":"DefaultDataSource(Context, boolean)","url":"%3Cinit%3E(android.content.Context,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSource","l":"DefaultDataSource(Context, DataSource)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.upstream.DataSource)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSource","l":"DefaultDataSource(Context, String, boolean)","url":"%3Cinit%3E(android.content.Context,java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSource","l":"DefaultDataSource(Context, String, int, int, boolean)","url":"%3Cinit%3E(android.content.Context,java.lang.String,int,int,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSourceFactory","l":"DefaultDataSourceFactory(Context, DataSource.Factory)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSourceFactory","l":"DefaultDataSourceFactory(Context, String, TransferListener)","url":"%3Cinit%3E(android.content.Context,java.lang.String,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSourceFactory","l":"DefaultDataSourceFactory(Context, String)","url":"%3Cinit%3E(android.content.Context,java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSourceFactory","l":"DefaultDataSourceFactory(Context, TransferListener, DataSource.Factory)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.upstream.TransferListener,com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSourceFactory","l":"DefaultDataSourceFactory(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloaderFactory","l":"DefaultDownloaderFactory(CacheDataSource.Factory, Executor)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloaderFactory","l":"DefaultDownloaderFactory(CacheDataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory)"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloadIndex","l":"DefaultDownloadIndex(DatabaseProvider, String)","url":"%3Cinit%3E(com.google.android.exoplayer2.database.DatabaseProvider,java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloadIndex","l":"DefaultDownloadIndex(DatabaseProvider)","url":"%3Cinit%3E(com.google.android.exoplayer2.database.DatabaseProvider)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"DefaultDrmSessionManager(UUID, ExoMediaDrm, MediaDrmCallback, HashMap, boolean, int)","url":"%3Cinit%3E(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm,com.google.android.exoplayer2.drm.MediaDrmCallback,java.util.HashMap,boolean,int)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"DefaultDrmSessionManager(UUID, ExoMediaDrm, MediaDrmCallback, HashMap, boolean)","url":"%3Cinit%3E(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm,com.google.android.exoplayer2.drm.MediaDrmCallback,java.util.HashMap,boolean)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"DefaultDrmSessionManager(UUID, ExoMediaDrm, MediaDrmCallback, HashMap)","url":"%3Cinit%3E(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm,com.google.android.exoplayer2.drm.MediaDrmCallback,java.util.HashMap)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManagerProvider","l":"DefaultDrmSessionManagerProvider()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"DefaultExtractorInput(DataReader, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataReader,long,long)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"DefaultExtractorsFactory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.hls","c":"DefaultHlsDataSourceFactory","l":"DefaultHlsDataSourceFactory(DataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.hls","c":"DefaultHlsExtractorFactory","l":"DefaultHlsExtractorFactory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.hls","c":"DefaultHlsExtractorFactory","l":"DefaultHlsExtractorFactory(int, boolean)","url":"%3Cinit%3E(int,boolean)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistParserFactory","l":"DefaultHlsPlaylistParserFactory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"DefaultHlsPlaylistTracker(HlsDataSourceFactory, LoadErrorHandlingPolicy, HlsPlaylistParserFactory, double)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.hls.HlsDataSourceFactory,com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy,com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParserFactory,double)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"DefaultHlsPlaylistTracker(HlsDataSourceFactory, LoadErrorHandlingPolicy, HlsPlaylistParserFactory)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.hls.HlsDataSourceFactory,com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy,com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParserFactory)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"DefaultHttpDataSource()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"DefaultHttpDataSource(String, int, int, boolean, HttpDataSource.RequestProperties)","url":"%3Cinit%3E(java.lang.String,int,int,boolean,com.google.android.exoplayer2.upstream.HttpDataSource.RequestProperties)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"DefaultHttpDataSource(String, int, int)","url":"%3Cinit%3E(java.lang.String,int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"DefaultHttpDataSource(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSourceFactory","l":"DefaultHttpDataSourceFactory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSourceFactory","l":"DefaultHttpDataSourceFactory(String, int, int, boolean)","url":"%3Cinit%3E(java.lang.String,int,int,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSourceFactory","l":"DefaultHttpDataSourceFactory(String, TransferListener, int, int, boolean)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.upstream.TransferListener,int,int,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSourceFactory","l":"DefaultHttpDataSourceFactory(String, TransferListener)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSourceFactory","l":"DefaultHttpDataSourceFactory(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"TrackEncryptionBox","l":"defaultInitializationVector"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DefaultLoadControl()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DefaultLoadControl(DefaultAllocator, int, int, int, int, int, boolean, int, boolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DefaultAllocator,int,int,int,int,int,boolean,int,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultLoadErrorHandlingPolicy","l":"DefaultLoadErrorHandlingPolicy()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultLoadErrorHandlingPolicy","l":"DefaultLoadErrorHandlingPolicy(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"DefaultMediaItemConverter","l":"DefaultMediaItemConverter()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"DefaultMediaItemConverter","l":"DefaultMediaItemConverter()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.DefaultMediaMetadataProvider","l":"DefaultMediaMetadataProvider(MediaControllerCompat, String)","url":"%3Cinit%3E(android.support.v4.media.session.MediaControllerCompat,java.lang.String)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"DefaultMediaSourceFactory(Context, ExtractorsFactory)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.extractor.ExtractorsFactory)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"DefaultMediaSourceFactory(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"DefaultMediaSourceFactory(DataSource.Factory, ExtractorsFactory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.extractor.ExtractorsFactory)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"DefaultMediaSourceFactory(DataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.analytics","c":"DefaultPlaybackSessionManager","l":"DefaultPlaybackSessionManager()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.analytics","c":"DefaultPlaybackSessionManager","l":"DefaultPlaybackSessionManager(Supplier)","url":"%3Cinit%3E(com.google.common.base.Supplier)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"defaultPositionUs"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"defaultPositionUs"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"DefaultRenderersFactory(Context, int, long)","url":"%3Cinit%3E(android.content.Context,int,long)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"DefaultRenderersFactory(Context, int)","url":"%3Cinit%3E(android.content.Context,int)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"DefaultRenderersFactory(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.testutil","c":"DefaultRenderersFactoryAsserts","l":"DefaultRenderersFactoryAsserts()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","c":"DefaultRtpPayloadReaderFactory","l":"DefaultRtpPayloadReaderFactory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.DefaultSeekTimestampConverter","l":"DefaultSeekTimestampConverter()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.DefaultShuffleOrder","l":"DefaultShuffleOrder(int, long)","url":"%3Cinit%3E(int,long)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.DefaultShuffleOrder","l":"DefaultShuffleOrder(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.DefaultShuffleOrder","l":"DefaultShuffleOrder(int[], long)","url":"%3Cinit%3E(int[],long)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource","l":"DefaultSsChunkSource(LoaderErrorThrower, SsManifest, int, ExoTrackSelection, DataSource)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.LoaderErrorThrower,com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest,int,com.google.android.exoplayer2.trackselection.ExoTrackSelection,com.google.android.exoplayer2.upstream.DataSource)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DefaultTimeBar(Context, AttributeSet, int, AttributeSet, int)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet,int,android.util.AttributeSet,int)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DefaultTimeBar(Context, AttributeSet, int, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet,int,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DefaultTimeBar(Context, AttributeSet, int)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet,int)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DefaultTimeBar(Context, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DefaultTimeBar(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTrackNameProvider","l":"DefaultTrackNameProvider(Resources)","url":"%3Cinit%3E(android.content.res.Resources)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"DefaultTrackSelector()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"DefaultTrackSelector(Context, ExoTrackSelection.Factory)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.trackselection.ExoTrackSelection.Factory)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"DefaultTrackSelector(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"DefaultTrackSelector(DefaultTrackSelector.Parameters, ExoTrackSelection.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters,com.google.android.exoplayer2.trackselection.ExoTrackSelection.Factory)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"DefaultTrackSelector(ExoTrackSelection.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.trackselection.ExoTrackSelection.Factory)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DefaultTsPayloadReaderFactory","l":"DefaultTsPayloadReaderFactory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DefaultTsPayloadReaderFactory","l":"DefaultTsPayloadReaderFactory(int, List)","url":"%3Cinit%3E(int,java.util.List)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DefaultTsPayloadReaderFactory","l":"DefaultTsPayloadReaderFactory(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection.Definition","l":"Definition(TrackGroup, int...)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroup,int...)"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection.Definition","l":"Definition(TrackGroup, int[], int)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroup,int[],int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"delay(long)"},{"p":"com.google.android.exoplayer2.util","c":"AtomicFile","l":"delete()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"delete(File, DatabaseProvider)","url":"delete(java.io.File,com.google.android.exoplayer2.database.DatabaseProvider)"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"deltaPicOrderAlwaysZeroFlag"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistParser.DeltaUpdateException","l":"DeltaUpdateException()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"depth"},{"p":"com.google.android.exoplayer2.decoder","c":"Decoder","l":"dequeueInputBuffer()"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleDecoder","l":"dequeueInputBuffer()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"dequeueInputBufferIndex()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"dequeueInputBufferIndex()"},{"p":"com.google.android.exoplayer2.decoder","c":"Decoder","l":"dequeueOutputBuffer()"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleDecoder","l":"dequeueOutputBuffer()"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea608Decoder","l":"dequeueOutputBuffer()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"dequeueOutputBufferIndex(MediaCodec.BufferInfo)","url":"dequeueOutputBufferIndex(android.media.MediaCodec.BufferInfo)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"dequeueOutputBufferIndex(MediaCodec.BufferInfo)","url":"dequeueOutputBufferIndex(android.media.MediaCodec.BufferInfo)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"describeContents()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"describeContents()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","c":"AppInfoTable","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"VorbisComment","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyInfo","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"Id3Frame","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"MlltFrame","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MdtaMetadataEntry","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MotionPhotoMetadata","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData.Segment","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SmtaMetadataEntry","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceCommand","l":"describeContents()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"describeContents()"},{"p":"com.google.android.exoplayer2.offline","c":"StreamKey","l":"describeContents()"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"describeContents()"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroup","l":"describeContents()"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroupArray","l":"describeContents()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry","l":"describeContents()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry.VariantInfo","l":"describeContents()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"describeContents()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.SelectionOverride","l":"describeContents()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"describeContents()"},{"p":"com.google.android.exoplayer2.video","c":"ColorInfo","l":"describeContents()"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"description"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"description"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ApicFrame","l":"description"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"CommentFrame","l":"description"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"GeobFrame","l":"description"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"InternalFrame","l":"description"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"TextInformationFrame","l":"description"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"UrlLinkFrame","l":"description"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Descriptor","l":"Descriptor(String, String, String)","url":"%3Cinit%3E(java.lang.String,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.EsInfo","l":"descriptorBytes"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"DEVICE"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"DEVICE_CHARGING"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"DEVICE_DEBUG_INFO"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"DEVICE_IDLE"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"DEVICE_STORAGE_NOT_LOW"},{"p":"com.google.android.exoplayer2.device","c":"DeviceInfo","l":"DeviceInfo(@com.google.android.exoplayer2.device.DeviceInfo.PlaybackType int, int, int)","url":"%3Cinit%3E(@com.google.android.exoplayer2.device.DeviceInfo.PlaybackTypeint,int,int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecDecoderException","l":"diagnosticInfo"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer.DecoderInitializationException","l":"diagnosticInfo"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"DIMEN_UNSET"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"disable()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"disable()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"disable()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"disable()"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"disable()"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"disable()"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"disable()"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"disable(MediaSource.MediaSourceCaller)","url":"disable(com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"disable(MediaSource.MediaSourceCaller)","url":"disable(com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"disableChildSource(T)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener.EventDispatcher","l":"disabled(DecoderCounters)","url":"disabled(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener.EventDispatcher","l":"disabled(DecoderCounters)","url":"disabled(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"disabledTextTrackSelectionFlags"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"disableInternal()"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"disableInternal()"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"disableInternal()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"disableRenderer(int)"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"disableSeeking()"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"disableSeeking()"},{"p":"com.google.android.exoplayer2.source","c":"BundledExtractorsAdapter","l":"disableSeekingOnMp3Streams()"},{"p":"com.google.android.exoplayer2.source","c":"MediaParserExtractorAdapter","l":"disableSeekingOnMp3Streams()"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaExtractor","l":"disableSeekingOnMp3Streams()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"disableTunneling()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"disableTunneling()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"disableTunneling()"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_APP_OVERRIDE"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_AUDIO_CHANNEL_COUNT_CHANGED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_AUDIO_ENCODING_CHANGED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_AUDIO_SAMPLE_RATE_CHANGED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_DRM_SESSION_CHANGED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_INITIALIZATION_DATA_CHANGED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_MAX_INPUT_SIZE_EXCEEDED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_MIME_TYPE_CHANGED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_OPERATING_RATE_CHANGED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_REUSE_NOT_IMPLEMENTED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_VIDEO_COLOR_INFO_CHANGED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_VIDEO_MAX_RESOLUTION_EXCEEDED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_VIDEO_RESOLUTION_CHANGED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_VIDEO_ROTATION_CHANGED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_WORKAROUND"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"discardBuffer(long, boolean)","url":"discardBuffer(long,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"discardBuffer(long, boolean)","url":"discardBuffer(long,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"discardBuffer(long, boolean)","url":"discardBuffer(long,boolean)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"discardBuffer(long, boolean)","url":"discardBuffer(long,boolean)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"discardBuffer(long, boolean)","url":"discardBuffer(long,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"discardBuffer(long, boolean)","url":"discardBuffer(long,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"discardBuffer(long, boolean)","url":"discardBuffer(long,boolean)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"discardReasons"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"discardSampleMetadataToRead()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"discardTo(long, boolean, boolean)","url":"discardTo(long,boolean,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"discardTo(long, boolean)","url":"discardTo(long,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"discardToEnd()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"discardToRead()"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil","l":"discardToSps(ByteBuffer)","url":"discardToSps(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"discardUpstreamFrom(long)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"discardUpstreamSamples(int)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"DISCONTINUITY_REASON_AUTO_TRANSITION"},{"p":"com.google.android.exoplayer2","c":"Player","l":"DISCONTINUITY_REASON_INTERNAL"},{"p":"com.google.android.exoplayer2","c":"Player","l":"DISCONTINUITY_REASON_REMOVE"},{"p":"com.google.android.exoplayer2","c":"Player","l":"DISCONTINUITY_REASON_SEEK"},{"p":"com.google.android.exoplayer2","c":"Player","l":"DISCONTINUITY_REASON_SEEK_ADJUSTMENT"},{"p":"com.google.android.exoplayer2","c":"Player","l":"DISCONTINUITY_REASON_SKIP"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"discontinuitySequence"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher","l":"dispatch(RecordedRequest)","url":"dispatch(okhttp3.mockwebserver.RecordedRequest)"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"dispatchFastForward(Player)","url":"dispatchFastForward(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"dispatchFastForward(Player)","url":"dispatchFastForward(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"dispatchKeyEvent(KeyEvent)","url":"dispatchKeyEvent(android.view.KeyEvent)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"dispatchKeyEvent(KeyEvent)","url":"dispatchKeyEvent(android.view.KeyEvent)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"dispatchKeyEvent(KeyEvent)","url":"dispatchKeyEvent(android.view.KeyEvent)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"dispatchKeyEvent(KeyEvent)","url":"dispatchKeyEvent(android.view.KeyEvent)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"dispatchMediaKeyEvent(KeyEvent)","url":"dispatchMediaKeyEvent(android.view.KeyEvent)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"dispatchMediaKeyEvent(KeyEvent)","url":"dispatchMediaKeyEvent(android.view.KeyEvent)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"dispatchMediaKeyEvent(KeyEvent)","url":"dispatchMediaKeyEvent(android.view.KeyEvent)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"dispatchMediaKeyEvent(KeyEvent)","url":"dispatchMediaKeyEvent(android.view.KeyEvent)"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"dispatchNext(Player)","url":"dispatchNext(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"dispatchNext(Player)","url":"dispatchNext(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"dispatchPrepare(Player)","url":"dispatchPrepare(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"dispatchPrepare(Player)","url":"dispatchPrepare(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"dispatchPrevious(Player)","url":"dispatchPrevious(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"dispatchPrevious(Player)","url":"dispatchPrevious(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"dispatchRewind(Player)","url":"dispatchRewind(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"dispatchRewind(Player)","url":"dispatchRewind(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"dispatchSeekTo(Player, int, long)","url":"dispatchSeekTo(com.google.android.exoplayer2.Player,int,long)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"dispatchSeekTo(Player, int, long)","url":"dispatchSeekTo(com.google.android.exoplayer2.Player,int,long)"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"dispatchSetPlaybackParameters(Player, PlaybackParameters)","url":"dispatchSetPlaybackParameters(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"dispatchSetPlaybackParameters(Player, PlaybackParameters)","url":"dispatchSetPlaybackParameters(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"dispatchSetPlayWhenReady(Player, boolean)","url":"dispatchSetPlayWhenReady(com.google.android.exoplayer2.Player,boolean)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"dispatchSetPlayWhenReady(Player, boolean)","url":"dispatchSetPlayWhenReady(com.google.android.exoplayer2.Player,boolean)"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"dispatchSetRepeatMode(Player, int)","url":"dispatchSetRepeatMode(com.google.android.exoplayer2.Player,int)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"dispatchSetRepeatMode(Player, int)","url":"dispatchSetRepeatMode(com.google.android.exoplayer2.Player,int)"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"dispatchSetShuffleModeEnabled(Player, boolean)","url":"dispatchSetShuffleModeEnabled(com.google.android.exoplayer2.Player,boolean)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"dispatchSetShuffleModeEnabled(Player, boolean)","url":"dispatchSetShuffleModeEnabled(com.google.android.exoplayer2.Player,boolean)"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"dispatchStop(Player, boolean)","url":"dispatchStop(com.google.android.exoplayer2.Player,boolean)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"dispatchStop(Player, boolean)","url":"dispatchStop(com.google.android.exoplayer2.Player,boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"dispatchTouchEvent(MotionEvent)","url":"dispatchTouchEvent(android.view.MotionEvent)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"displayHeight"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"displayTitle"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"displayWidth"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"DO_NOT_OFFSET"},{"p":"com.google.android.exoplayer2.testutil","c":"Action","l":"doActionAndScheduleNext(SimpleExoPlayer, DefaultTrackSelector, Surface, HandlerWrapper, ActionSchedule.ActionNode)","url":"doActionAndScheduleNext(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface,com.google.android.exoplayer2.util.HandlerWrapper,com.google.android.exoplayer2.testutil.ActionSchedule.ActionNode)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action","l":"doActionAndScheduleNextImpl(SimpleExoPlayer, DefaultTrackSelector, Surface, HandlerWrapper, ActionSchedule.ActionNode)","url":"doActionAndScheduleNextImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface,com.google.android.exoplayer2.util.HandlerWrapper,com.google.android.exoplayer2.testutil.ActionSchedule.ActionNode)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.PlayUntilPosition","l":"doActionAndScheduleNextImpl(SimpleExoPlayer, DefaultTrackSelector, Surface, HandlerWrapper, ActionSchedule.ActionNode)","url":"doActionAndScheduleNextImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface,com.google.android.exoplayer2.util.HandlerWrapper,com.google.android.exoplayer2.testutil.ActionSchedule.ActionNode)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForIsLoading","l":"doActionAndScheduleNextImpl(SimpleExoPlayer, DefaultTrackSelector, Surface, HandlerWrapper, ActionSchedule.ActionNode)","url":"doActionAndScheduleNextImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface,com.google.android.exoplayer2.util.HandlerWrapper,com.google.android.exoplayer2.testutil.ActionSchedule.ActionNode)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForMessage","l":"doActionAndScheduleNextImpl(SimpleExoPlayer, DefaultTrackSelector, Surface, HandlerWrapper, ActionSchedule.ActionNode)","url":"doActionAndScheduleNextImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface,com.google.android.exoplayer2.util.HandlerWrapper,com.google.android.exoplayer2.testutil.ActionSchedule.ActionNode)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForPendingPlayerCommands","l":"doActionAndScheduleNextImpl(SimpleExoPlayer, DefaultTrackSelector, Surface, HandlerWrapper, ActionSchedule.ActionNode)","url":"doActionAndScheduleNextImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface,com.google.android.exoplayer2.util.HandlerWrapper,com.google.android.exoplayer2.testutil.ActionSchedule.ActionNode)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForPlayWhenReady","l":"doActionAndScheduleNextImpl(SimpleExoPlayer, DefaultTrackSelector, Surface, HandlerWrapper, ActionSchedule.ActionNode)","url":"doActionAndScheduleNextImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface,com.google.android.exoplayer2.util.HandlerWrapper,com.google.android.exoplayer2.testutil.ActionSchedule.ActionNode)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForPlaybackState","l":"doActionAndScheduleNextImpl(SimpleExoPlayer, DefaultTrackSelector, Surface, HandlerWrapper, ActionSchedule.ActionNode)","url":"doActionAndScheduleNextImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface,com.google.android.exoplayer2.util.HandlerWrapper,com.google.android.exoplayer2.testutil.ActionSchedule.ActionNode)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForPositionDiscontinuity","l":"doActionAndScheduleNextImpl(SimpleExoPlayer, DefaultTrackSelector, Surface, HandlerWrapper, ActionSchedule.ActionNode)","url":"doActionAndScheduleNextImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface,com.google.android.exoplayer2.util.HandlerWrapper,com.google.android.exoplayer2.testutil.ActionSchedule.ActionNode)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForTimelineChanged","l":"doActionAndScheduleNextImpl(SimpleExoPlayer, DefaultTrackSelector, Surface, HandlerWrapper, ActionSchedule.ActionNode)","url":"doActionAndScheduleNextImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface,com.google.android.exoplayer2.util.HandlerWrapper,com.google.android.exoplayer2.testutil.ActionSchedule.ActionNode)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.AddMediaItems","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.ClearMediaItems","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.ClearVideoSurface","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.ExecuteRunnable","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.MoveMediaItem","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.PlayUntilPosition","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.Prepare","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.RemoveMediaItem","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.RemoveMediaItems","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.Seek","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SendMessages","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetAudioAttributes","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetMediaItems","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetMediaItemsResetPosition","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetPlayWhenReady","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetPlaybackParameters","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetRendererDisabled","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetRepeatMode","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetShuffleModeEnabled","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetShuffleOrder","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetVideoSurface","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.Stop","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.ThrowPlaybackException","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForIsLoading","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForMessage","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForPendingPlayerCommands","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForPlayWhenReady","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForPlaybackState","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForPositionDiscontinuity","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForTimelineChanged","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"InternalFrame","l":"domain"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"DONT_RETRY"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"DONT_RETRY_FATAL"},{"p":"com.google.android.exoplayer2.offline","c":"Downloader","l":"download(Downloader.ProgressListener)","url":"download(com.google.android.exoplayer2.offline.Downloader.ProgressListener)"},{"p":"com.google.android.exoplayer2.offline","c":"ProgressiveDownloader","l":"download(Downloader.ProgressListener)","url":"download(com.google.android.exoplayer2.offline.Downloader.ProgressListener)"},{"p":"com.google.android.exoplayer2.offline","c":"SegmentDownloader","l":"download(Downloader.ProgressListener)","url":"download(com.google.android.exoplayer2.offline.Downloader.ProgressListener)"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"Download(DownloadRequest, int, long, long, long, int, int, DownloadProgress)","url":"%3Cinit%3E(com.google.android.exoplayer2.offline.DownloadRequest,int,long,long,long,int,int,com.google.android.exoplayer2.offline.DownloadProgress)"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"Download(DownloadRequest, int, long, long, long, int, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.offline.DownloadRequest,int,long,long,long,int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"DownloadBuilder(DownloadRequest)","url":"%3Cinit%3E(com.google.android.exoplayer2.offline.DownloadRequest)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"DownloadBuilder(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadException","l":"DownloadException(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadException","l":"DownloadException(Throwable)","url":"%3Cinit%3E(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"DownloadHelper(MediaItem, MediaSource, DefaultTrackSelector.Parameters, RendererCapabilities[])","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.source.MediaSource,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters,com.google.android.exoplayer2.RendererCapabilities[])"},{"p":"com.google.android.exoplayer2.drm","c":"OfflineLicenseHelper","l":"downloadLicense(Format)","url":"downloadLicense(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"DownloadManager(Context, DatabaseProvider, Cache, DataSource.Factory, Executor)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.database.DatabaseProvider,com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.DataSource.Factory,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"DownloadManager(Context, DatabaseProvider, Cache, DataSource.Factory)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.database.DatabaseProvider,com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"DownloadManager(Context, WritableDownloadIndex, DownloaderFactory)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.offline.WritableDownloadIndex,com.google.android.exoplayer2.offline.DownloaderFactory)"},{"p":"com.google.android.exoplayer2.ui","c":"DownloadNotificationHelper","l":"DownloadNotificationHelper(Context, String)","url":"%3Cinit%3E(android.content.Context,java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadProgress","l":"DownloadProgress()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"DownloadService(int, long, String, int, int)","url":"%3Cinit%3E(int,long,java.lang.String,int,int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"DownloadService(int, long, String, int)","url":"%3Cinit%3E(int,long,java.lang.String,int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"DownloadService(int, long)","url":"%3Cinit%3E(int,long)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"DownloadService(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"downstreamFormatChanged(int, Format, int, Object, long)","url":"downstreamFormatChanged(int,com.google.android.exoplayer2.Format,int,java.lang.Object,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"downstreamFormatChanged(MediaLoadData)","url":"downstreamFormatChanged(com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.ext.workmanager","c":"WorkManagerScheduler.SchedulerWorker","l":"doWork()"},{"p":"com.google.android.exoplayer2.util","c":"RunnableFutureTask","l":"doWork()"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"drawableStateChanged()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionManager","l":"DRM_UNSUPPORTED"},{"p":"com.google.android.exoplayer2","c":"MediaItem.PlaybackProperties","l":"drmConfiguration"},{"p":"com.google.android.exoplayer2","c":"Format","l":"drmInitData"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.SegmentBase","l":"drmInitData"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"DrmInitData(DrmInitData.SchemeData...)","url":"%3Cinit%3E(com.google.android.exoplayer2.drm.DrmInitData.SchemeData...)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"DrmInitData(List)","url":"%3Cinit%3E(java.util.List)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"DrmInitData(String, DrmInitData.SchemeData...)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.drm.DrmInitData.SchemeData...)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"DrmInitData(String, List)","url":"%3Cinit%3E(java.lang.String,java.util.List)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener.EventDispatcher","l":"drmKeysLoaded()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener.EventDispatcher","l":"drmKeysRemoved()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener.EventDispatcher","l":"drmKeysRestored()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser.RepresentationInfo","l":"drmSchemeDatas"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser.RepresentationInfo","l":"drmSchemeType"},{"p":"com.google.android.exoplayer2","c":"FormatHolder","l":"drmSession"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener.EventDispatcher","l":"drmSessionAcquired(int)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession.DrmSessionException","l":"DrmSessionException(Throwable)","url":"%3Cinit%3E(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener.EventDispatcher","l":"drmSessionManagerError(Exception)","url":"drmSessionManagerError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener.EventDispatcher","l":"drmSessionReleased()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"dropOutputBuffer(MediaCodecAdapter, int, long)","url":"dropOutputBuffer(com.google.android.exoplayer2.mediacodec.MediaCodecAdapter,int,long)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"dropOutputBuffer(VideoDecoderOutputBuffer)","url":"dropOutputBuffer(com.google.android.exoplayer2.video.VideoDecoderOutputBuffer)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"droppedBufferCount"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener.EventDispatcher","l":"droppedFrames(int, long)","url":"droppedFrames(int,long)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"droppedToKeyframeCount"},{"p":"com.google.android.exoplayer2.audio","c":"DtsUtil","l":"DTS_HD_MAX_RATE_BYTES_PER_SECOND"},{"p":"com.google.android.exoplayer2.audio","c":"DtsUtil","l":"DTS_MAX_RATE_BYTES_PER_SECOND"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DtsReader","l":"DtsReader(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionManager","l":"DUMMY"},{"p":"com.google.android.exoplayer2.upstream","c":"LoaderErrorThrower.Dummy","l":"Dummy()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"DummyExoMediaDrm()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor","c":"DummyExtractorOutput","l":"DummyExtractorOutput()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"DummyMainThread","l":"DummyMainThread()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor","c":"DummyTrackOutput","l":"DummyTrackOutput()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.robolectric","c":"PlaybackOutput","l":"dump(Dumper)","url":"dump(com.google.android.exoplayer2.testutil.Dumper)"},{"p":"com.google.android.exoplayer2.testutil","c":"CapturingAudioSink","l":"dump(Dumper)","url":"dump(com.google.android.exoplayer2.testutil.Dumper)"},{"p":"com.google.android.exoplayer2.testutil","c":"CapturingRenderersFactory","l":"dump(Dumper)","url":"dump(com.google.android.exoplayer2.testutil.Dumper)"},{"p":"com.google.android.exoplayer2.testutil","c":"DumpableFormat","l":"dump(Dumper)","url":"dump(com.google.android.exoplayer2.testutil.Dumper)"},{"p":"com.google.android.exoplayer2.testutil","c":"Dumper.Dumpable","l":"dump(Dumper)","url":"dump(com.google.android.exoplayer2.testutil.Dumper)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorOutput","l":"dump(Dumper)","url":"dump(com.google.android.exoplayer2.testutil.Dumper)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"dump(Dumper)","url":"dump(com.google.android.exoplayer2.testutil.Dumper)"},{"p":"com.google.android.exoplayer2.testutil","c":"DumpableFormat","l":"DumpableFormat(Format, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"Dumper","l":"Dumper()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts.AssertionConfig","l":"dumpFilesPrefix"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"durationMs"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"durationMs"},{"p":"com.google.android.exoplayer2.extractor","c":"ChunkIndex","l":"durationsUs"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"durationsUs"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"durationUs"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"durationUs"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"durationUs"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"durationUs"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.SegmentBase","l":"durationUs"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest","l":"durationUs"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"durationUs"},{"p":"com.google.android.exoplayer2.text.dvb","c":"DvbDecoder","l":"DvbDecoder(List)","url":"%3Cinit%3E(java.util.List)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.DvbSubtitleInfo","l":"DvbSubtitleInfo(String, int, byte[])","url":"%3Cinit%3E(java.lang.String,int,byte[])"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.EsInfo","l":"dvbSubtitleInfos"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DvbSubtitleReader","l":"DvbSubtitleReader(List)","url":"%3Cinit%3E(java.util.List)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest","l":"dvrWindowLengthUs"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"dynamic"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"E_AC_3_CODEC_STRING"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"E_AC3_MAX_RATE_BYTES_PER_SECOND"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"e(String, String, Throwable)","url":"e(java.lang.String,java.lang.String,java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"e(String, String)","url":"e(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"EDGE_TYPE_DEPRESSED"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"EDGE_TYPE_DROP_SHADOW"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"EDGE_TYPE_NONE"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"EDGE_TYPE_OUTLINE"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"EDGE_TYPE_RAISED"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"edgeColor"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"edgeType"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"editListDurations"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"editListMediaTimes"},{"p":"com.google.android.exoplayer2.audio","c":"AuxEffectInfo","l":"effectId"},{"p":"com.google.android.exoplayer2.util","c":"EGLSurfaceTexture","l":"EGLSurfaceTexture(Handler, EGLSurfaceTexture.TextureImageListener)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.util.EGLSurfaceTexture.TextureImageListener)"},{"p":"com.google.android.exoplayer2.util","c":"EGLSurfaceTexture","l":"EGLSurfaceTexture(Handler)","url":"%3Cinit%3E(android.os.Handler)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock","l":"elapsedRealtime()"},{"p":"com.google.android.exoplayer2.util","c":"Clock","l":"elapsedRealtime()"},{"p":"com.google.android.exoplayer2.util","c":"SystemClock","l":"elapsedRealtime()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"elapsedRealtimeEpochOffsetMs"},{"p":"com.google.android.exoplayer2.source","c":"LoadEventInfo","l":"elapsedRealtimeMs"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"ELEMENT_TYPE_BINARY"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"ELEMENT_TYPE_FLOAT"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"ELEMENT_TYPE_MASTER"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"ELEMENT_TYPE_STRING"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"ELEMENT_TYPE_UNKNOWN"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"ELEMENT_TYPE_UNSIGNED_INT"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterTocFrame","l":"elementId"},{"p":"com.google.android.exoplayer2.util","c":"CopyOnWriteMultiset","l":"elementSet()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream.EmbeddedSampleStream","l":"EmbeddedSampleStream(ChunkSampleStream, SampleQueue, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.chunk.ChunkSampleStream,com.google.android.exoplayer2.source.SampleQueue,int)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"EMPTY"},{"p":"com.google.android.exoplayer2","c":"Player.Commands","l":"EMPTY"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"EMPTY"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"EMPTY"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionManager.DrmSessionReference","l":"EMPTY"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorsFactory","l":"EMPTY"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroupArray","l":"EMPTY"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaChunkIterator","l":"EMPTY"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"EMPTY"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"EMPTY"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"DefaultContentMetadata","l":"EMPTY"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor","l":"EMPTY_BUFFER"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"EMPTY_BYTE_ARRAY"},{"p":"com.google.android.exoplayer2.source","c":"EmptySampleStream","l":"EmptySampleStream()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"enable()"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"enable()"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"enable()"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"enable()"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"enable(MediaSource.MediaSourceCaller)","url":"enable(com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"enable(MediaSource.MediaSourceCaller)","url":"enable(com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"enable(RendererConfiguration, Format[], SampleStream, long, boolean, boolean, long, long)","url":"enable(com.google.android.exoplayer2.RendererConfiguration,com.google.android.exoplayer2.Format[],com.google.android.exoplayer2.source.SampleStream,long,boolean,boolean,long,long)"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"enable(RendererConfiguration, Format[], SampleStream, long, boolean, boolean, long, long)","url":"enable(com.google.android.exoplayer2.RendererConfiguration,com.google.android.exoplayer2.Format[],com.google.android.exoplayer2.source.SampleStream,long,boolean,boolean,long,long)"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"enable(RendererConfiguration, Format[], SampleStream, long, boolean, boolean, long, long)","url":"enable(com.google.android.exoplayer2.RendererConfiguration,com.google.android.exoplayer2.Format[],com.google.android.exoplayer2.source.SampleStream,long,boolean,boolean,long,long)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"enableChildSource(T)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"enableCount"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener.EventDispatcher","l":"enabled(DecoderCounters)","url":"enabled(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener.EventDispatcher","l":"enabled(DecoderCounters)","url":"enabled(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"enableInternal()"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"enableInternal()"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"enableInternal()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"enableRenderer(int)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"enableTunnelingV21()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"enableTunnelingV21()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"enableTunnelingV21()"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessageEncoder","l":"encode(EventMessage)","url":"encode(com.google.android.exoplayer2.metadata.emsg.EventMessage)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"encoderDelay"},{"p":"com.google.android.exoplayer2.extractor","c":"GaplessInfoHolder","l":"encoderDelay"},{"p":"com.google.android.exoplayer2","c":"Format","l":"encoderPadding"},{"p":"com.google.android.exoplayer2.extractor","c":"GaplessInfoHolder","l":"encoderPadding"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor.AudioFormat","l":"encoding"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_AAC_ELD"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_AAC_ER_BSAC"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_AAC_HE_V1"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_AAC_HE_V2"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_AAC_LC"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_AAC_XHE"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_AC3"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_AC4"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_DOLBY_TRUEHD"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_DTS"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_DTS_HD"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_E_AC3"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_E_AC3_JOC"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_INVALID"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_MP3"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_PCM_16BIT"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_PCM_16BIT_BIG_ENDIAN"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_PCM_24BIT"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_PCM_32BIT"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_PCM_8BIT"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_PCM_FLOAT"},{"p":"com.google.android.exoplayer2.decoder","c":"CryptoInfo","l":"encryptedBlocks"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput.CryptoData","l":"encryptedBlocks"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.SegmentBase","l":"encryptionIV"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput.CryptoData","l":"encryptionKey"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream.FakeSampleStreamItem","l":"END_OF_STREAM_ITEM"},{"p":"com.google.android.exoplayer2.testutil","c":"Dumper","l":"endBlock()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData","l":"endData()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"endedCount"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"endMasterElement(int)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"endMasterElement(int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"endOffset"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkHolder","l":"endOfStream"},{"p":"com.google.android.exoplayer2","c":"MediaItem.ClippingProperties","l":"endPositionMs"},{"p":"com.google.android.exoplayer2.util","c":"TraceUtil","l":"endSection()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"endTimeMs"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData.Segment","l":"endTimeMs"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"endTimeUs"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCueInfo","l":"endTimeUs"},{"p":"com.google.android.exoplayer2.extractor","c":"DummyExtractorOutput","l":"endTracks()"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorOutput","l":"endTracks()"},{"p":"com.google.android.exoplayer2.extractor.jpeg","c":"StartOffsetExtractorOutput","l":"endTracks()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BundledChunkExtractor","l":"endTracks()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorOutput","l":"endTracks()"},{"p":"com.google.android.exoplayer2.util","c":"AtomicFile","l":"endWrite(OutputStream)","url":"endWrite(java.io.OutputStream)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"ensureCapacity(int)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"ensureSpaceForWrite(int)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"ensureUpdated()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"DefaultContentMetadata","l":"entrySet()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor.MediaIdEqualityChecker","l":"equals(MediaDescriptionCompat, MediaDescriptionCompat)","url":"equals(android.support.v4.media.MediaDescriptionCompat,android.support.v4.media.MediaDescriptionCompat)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"HeartRating","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.AdsConfiguration","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.ClippingProperties","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.DrmConfiguration","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.LiveConfiguration","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.PlaybackProperties","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Subtitle","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"PercentageRating","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"PlaybackParameters","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"Player.Commands","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"RendererConfiguration","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"SeekParameters","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"StarRating","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"ThumbRating","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndException","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndFormat","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndPlaybackState","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioCapabilities","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.audio","c":"AuxEffectInfo","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.device","c":"DeviceInfo","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap.SeekPoints","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekPoint","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput.CryptoData","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"VorbisComment","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyInfo","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ApicFrame","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"BinaryFrame","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterTocFrame","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"CommentFrame","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"GeobFrame","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"InternalFrame","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"MlltFrame","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"PrivFrame","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"TextInformationFrame","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"UrlLinkFrame","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MdtaMetadataEntry","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MotionPhotoMetadata","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData.Segment","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SmtaMetadataEntry","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.offline","c":"StreamKey","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroup","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroupArray","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Descriptor","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ProgramInformation","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"RangedUri","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SegmentTimelineElement","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry.VariantInfo","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPayloadFormat","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.testutil","c":"DumpableFormat","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection.AdaptationCheckpoint","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.SelectionOverride","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionArray","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"DefaultContentMetadata","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.util","c":"ExoFlags","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.video","c":"ColorInfo","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.video","c":"VideoSize","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.WriteException","l":"errorCode"},{"p":"com.google.android.exoplayer2.drm","c":"DecryptionException","l":"errorCode"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy.LoadErrorInfo","l":"errorCount"},{"p":"com.google.android.exoplayer2.drm","c":"ErrorStateDrmSession","l":"ErrorStateDrmSession(DrmSession.DrmSessionException)","url":"%3Cinit%3E(com.google.android.exoplayer2.drm.DrmSession.DrmSessionException)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"escapeFileName(String)","url":"escapeFileName(java.lang.String)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.EsInfo","l":"EsInfo(int, String, List, byte[])","url":"%3Cinit%3E(int,java.lang.String,java.util.List,byte[])"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"AdaptationSet","l":"essentialProperties"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"Id3Decoder.FramePredicate","l":"evaluate(int, int, int, int, int)","url":"evaluate(int,int,int,int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"evaluateQueueSize(long, List)","url":"evaluateQueueSize(long,java.util.List)"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"evaluateQueueSize(long, List)","url":"evaluateQueueSize(long,java.util.List)"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"evaluateQueueSize(long, List)","url":"evaluateQueueSize(long,java.util.List)"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"evaluateQueueSize(long, List)","url":"evaluateQueueSize(long,java.util.List)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_AUDIO_ATTRIBUTES_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_AUDIO_CODEC_ERROR"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_AUDIO_DECODER_INITIALIZED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_AUDIO_DECODER_RELEASED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_AUDIO_DISABLED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_AUDIO_ENABLED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_AUDIO_INPUT_FORMAT_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_AUDIO_POSITION_ADVANCING"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_AUDIO_SESSION_ID"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_AUDIO_SINK_ERROR"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_AUDIO_UNDERRUN"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_AVAILABLE_COMMANDS_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_BANDWIDTH_ESTIMATE"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_DOWNSTREAM_FORMAT_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_DRM_KEYS_LOADED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_DRM_KEYS_REMOVED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_DRM_KEYS_RESTORED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_DRM_SESSION_ACQUIRED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_DRM_SESSION_MANAGER_ERROR"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_DRM_SESSION_RELEASED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_DROPPED_VIDEO_FRAMES"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_IS_LOADING_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_IS_LOADING_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_IS_PLAYING_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_IS_PLAYING_CHANGED"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"EVENT_KEY_EXPIRED"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"EVENT_KEY_REQUIRED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_LOAD_CANCELED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_LOAD_COMPLETED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_LOAD_ERROR"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_LOAD_STARTED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_MEDIA_ITEM_TRANSITION"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_MEDIA_ITEM_TRANSITION"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_MEDIA_METADATA_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_MEDIA_METADATA_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_METADATA"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_PLAY_WHEN_READY_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_PLAY_WHEN_READY_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_PLAYBACK_PARAMETERS_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_PLAYBACK_PARAMETERS_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_PLAYBACK_STATE_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_PLAYBACK_STATE_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_PLAYER_ERROR"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_PLAYER_ERROR"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_PLAYER_RELEASED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_POSITION_DISCONTINUITY"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_POSITION_DISCONTINUITY"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"EVENT_PROVISION_REQUIRED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_RENDERED_FIRST_FRAME"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_REPEAT_MODE_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_REPEAT_MODE_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_SHUFFLE_MODE_ENABLED_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_SHUFFLE_MODE_ENABLED_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_SKIP_SILENCE_ENABLED_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_STATIC_METADATA_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_STATIC_METADATA_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_SURFACE_SIZE_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_TIMELINE_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_TIMELINE_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_TRACKS_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_TRACKS_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_UPSTREAM_DISCARDED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_VIDEO_CODEC_ERROR"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_VIDEO_DECODER_INITIALIZED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_VIDEO_DECODER_RELEASED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_VIDEO_DISABLED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_VIDEO_ENABLED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_VIDEO_FRAME_PROCESSING_OFFSET"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_VIDEO_INPUT_FORMAT_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_VIDEO_SIZE_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_VOLUME_CHANGED"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener.EventDispatcher","l":"EventDispatcher()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"EventDispatcher()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"BandwidthMeter.EventListener.EventDispatcher","l":"EventDispatcher()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener.EventDispatcher","l":"EventDispatcher(Handler, AudioRendererEventListener)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener.EventDispatcher","l":"EventDispatcher(Handler, VideoRendererEventListener)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"EventLogger(MappingTrackSelector, String)","url":"%3Cinit%3E(com.google.android.exoplayer2.trackselection.MappingTrackSelector,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"EventLogger(MappingTrackSelector)","url":"%3Cinit%3E(com.google.android.exoplayer2.trackselection.MappingTrackSelector)"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"EventMessage(String, String, long, long, byte[])","url":"%3Cinit%3E(java.lang.String,java.lang.String,long,long,byte[])"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessageDecoder","l":"EventMessageDecoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessageEncoder","l":"EventMessageEncoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"eventPlaybackPositionMs"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand","l":"events"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"EventStream","l":"events"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.Events","l":"Events(ExoFlags, SparseArray)","url":"%3Cinit%3E(com.google.android.exoplayer2.util.ExoFlags,android.util.SparseArray)"},{"p":"com.google.android.exoplayer2","c":"Player.Events","l":"Events(ExoFlags)","url":"%3Cinit%3E(com.google.android.exoplayer2.util.ExoFlags)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"EventStream","l":"EventStream(String, String, long, long[], EventMessage[])","url":"%3Cinit%3E(java.lang.String,java.lang.String,long,long[],com.google.android.exoplayer2.metadata.emsg.EventMessage[])"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Period","l":"eventStreams"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndException","l":"eventTime"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndFormat","l":"eventTime"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndPlaybackState","l":"eventTime"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"EventTime(long, Timeline, int, MediaSource.MediaPeriodId, long, Timeline, int, MediaSource.MediaPeriodId, long, long)","url":"%3Cinit%3E(long,com.google.android.exoplayer2.Timeline,int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,long,com.google.android.exoplayer2.Timeline,int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,long,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndException","l":"EventTimeAndException(AnalyticsListener.EventTime, Exception)","url":"%3Cinit%3E(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndFormat","l":"EventTimeAndFormat(AnalyticsListener.EventTime, Format)","url":"%3Cinit%3E(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndPlaybackState","l":"EventTimeAndPlaybackState(AnalyticsListener.EventTime, @com.google.android.exoplayer2.analytics.PlaybackStats.PlaybackState int)","url":"%3Cinit%3E(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,@com.google.android.exoplayer2.analytics.PlaybackStats.PlaybackStateint)"},{"p":"com.google.android.exoplayer2","c":"SeekParameters","l":"EXACT"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"exceedAudioConstraintsIfNecessary"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"exceedRendererCapabilitiesIfNecessary"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"exceedVideoConstraintsIfNecessary"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndException","l":"exception"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData.Segment","l":"exception"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy.LoadErrorInfo","l":"exception"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData.Segment","l":"exceptionCleared"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData.Segment","l":"exceptionThrown"},{"p":"com.google.android.exoplayer2.offline","c":"SegmentDownloader","l":"execute(RunnableFutureTask, boolean)","url":"execute(com.google.android.exoplayer2.util.RunnableFutureTask,boolean)"},{"p":"com.google.android.exoplayer2.drm","c":"HttpMediaDrmCallback","l":"executeKeyRequest(UUID, ExoMediaDrm.KeyRequest)","url":"executeKeyRequest(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm.KeyRequest)"},{"p":"com.google.android.exoplayer2.drm","c":"LocalMediaDrmCallback","l":"executeKeyRequest(UUID, ExoMediaDrm.KeyRequest)","url":"executeKeyRequest(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm.KeyRequest)"},{"p":"com.google.android.exoplayer2.drm","c":"MediaDrmCallback","l":"executeKeyRequest(UUID, ExoMediaDrm.KeyRequest)","url":"executeKeyRequest(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm.KeyRequest)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm.LicenseServer","l":"executeKeyRequest(UUID, ExoMediaDrm.KeyRequest)","url":"executeKeyRequest(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm.KeyRequest)"},{"p":"com.google.android.exoplayer2.drm","c":"HttpMediaDrmCallback","l":"executeProvisionRequest(UUID, ExoMediaDrm.ProvisionRequest)","url":"executeProvisionRequest(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm.ProvisionRequest)"},{"p":"com.google.android.exoplayer2.drm","c":"LocalMediaDrmCallback","l":"executeProvisionRequest(UUID, ExoMediaDrm.ProvisionRequest)","url":"executeProvisionRequest(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm.ProvisionRequest)"},{"p":"com.google.android.exoplayer2.drm","c":"MediaDrmCallback","l":"executeProvisionRequest(UUID, ExoMediaDrm.ProvisionRequest)","url":"executeProvisionRequest(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm.ProvisionRequest)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm.LicenseServer","l":"executeProvisionRequest(UUID, ExoMediaDrm.ProvisionRequest)","url":"executeProvisionRequest(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm.ProvisionRequest)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"executeRunnable(Runnable)","url":"executeRunnable(java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.ExecuteRunnable","l":"ExecuteRunnable(String, Runnable)","url":"%3Cinit%3E(java.lang.String,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.util","c":"AtomicFile","l":"exists()"},{"p":"com.google.android.exoplayer2.database","c":"ExoDatabaseProvider","l":"ExoDatabaseProvider(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"ExoHostedTest(String, boolean)","url":"%3Cinit%3E(java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"ExoHostedTest(String, long, boolean)","url":"%3Cinit%3E(java.lang.String,long,boolean)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"exoMediaCryptoType"},{"p":"com.google.android.exoplayer2","c":"ExoTimeoutException","l":"ExoTimeoutException(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"EXPECTED_PLAYING_TIME_MEDIA_DURATION_MS"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"EXPECTED_PLAYING_TIME_UNSET"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.UnexpectedDiscontinuityException","l":"expectedPresentationTimeUs"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"experimentalFlushWithoutAudioTrackRelease()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"experimentalFlushWithoutAudioTrackRelease()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"experimentalFlushWithoutAudioTrackRelease()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"experimentalIsSleepingForOffload()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"experimentalIsSleepingForOffload()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"experimentalIsSleepingForOffload()"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"experimentalSetAsynchronousBufferQueueingEnabled(boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"experimentalSetAsynchronousBufferQueueingEnabled(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"experimentalSetEnableKeepAudioTrackOnSeek(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"experimentalSetEnableKeepAudioTrackOnSeek(boolean)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"experimentalSetForceAsyncQueueingSynchronizationWorkaround(boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"experimentalSetForceAsyncQueueingSynchronizationWorkaround(boolean)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"experimentalSetForegroundModeTimeoutMs(long)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"experimentalSetForegroundModeTimeoutMs(long)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"experimentalSetOffloadSchedulingEnabled(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"experimentalSetOffloadSchedulingEnabled(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"experimentalSetOffloadSchedulingEnabled(boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"experimentalSetSkipAndContinueIfSampleTooLarge(boolean)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"experimentalSetSynchronizeCodecInteractionsWithQueueingEnabled(boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"experimentalSetSynchronizeCodecInteractionsWithQueueingEnabled(boolean)"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil","l":"EXTENDED_SAR"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"extension"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"EXTENSION_RENDERER_MODE_OFF"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"EXTENSION_RENDERER_MODE_ON"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"EXTENSION_RENDERER_MODE_PREFER"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor","l":"EXTRA_FROM_INDEX"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"EXTRA_INSTANCE_ID"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor","l":"EXTRA_TO_INDEX"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"extractAllSamplesFromFile(Extractor, Context, String)","url":"extractAllSamplesFromFile(com.google.android.exoplayer2.extractor.Extractor,android.content.Context,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"extractSeekMap(Extractor, FakeExtractorOutput, DataSource, Uri)","url":"extractSeekMap(com.google.android.exoplayer2.extractor.Extractor,com.google.android.exoplayer2.testutil.FakeExtractorOutput,com.google.android.exoplayer2.upstream.DataSource,android.net.Uri)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"extras"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"EXTRAS_SPEED"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.amr","c":"AmrExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.flac","c":"FlacExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.flv","c":"FlvExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.ogg","c":"OggExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Extractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Extractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.wav","c":"WavExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.source","c":"MediaParserExtractorAdapter","l":"FACTORY"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BundledChunkExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaParserChunkExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.source.hls","c":"MediaParserHlsMediaChunkExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"FACTORY"},{"p":"com.google.android.exoplayer2.upstream","c":"DummyDataSource","l":"FACTORY"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter.Factory","l":"Factory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource.Factory","l":"Factory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.Factory","l":"Factory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource.Factory","l":"Factory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection.Factory","l":"Factory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.trackselection","c":"RandomTrackSelection.Factory","l":"Factory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource.Factory","l":"Factory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSource.Factory","l":"Factory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink.Factory","l":"Factory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"Factory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FailOnCloseDataSink.Factory","l":"Factory(Cache, AtomicBoolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,java.util.concurrent.atomic.AtomicBoolean)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource.Factory","l":"Factory(Call.Factory)","url":"%3Cinit%3E(okhttp3.Call.Factory)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.Factory","l":"Factory(ChunkExtractor.Factory, DataSource.Factory, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.chunk.ChunkExtractor.Factory,com.google.android.exoplayer2.upstream.DataSource.Factory,int)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"Factory(CronetEngineWrapper, Executor)","url":"%3Cinit%3E(com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"Factory(DashChunkSource.Factory, DataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.dash.DashChunkSource.Factory,com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"Factory(DataSource.Factory, ExtractorsFactory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.extractor.ExtractorsFactory)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.Factory","l":"Factory(DataSource.Factory, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory,int)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"Factory(DataSource.Factory, ProgressiveMediaExtractor.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.source.ProgressiveMediaExtractor.Factory)"},{"p":"com.google.android.exoplayer2.upstream","c":"ResolvingDataSource.Factory","l":"Factory(DataSource.Factory, ResolvingDataSource.Resolver)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.upstream.ResolvingDataSource.Resolver)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"Factory(DataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource.Factory","l":"Factory(DataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"Factory(DataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.Factory","l":"Factory(DataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"Factory(DataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource.Factory","l":"Factory(DataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"Factory(DataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource.Factory","l":"Factory(FakeAdaptiveDataSet.Factory, FakeDataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.testutil.FakeAdaptiveDataSet.Factory,com.google.android.exoplayer2.testutil.FakeDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"Factory(HlsDataSourceFactory)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.hls.HlsDataSourceFactory)"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection.Factory","l":"Factory(int, int, int, float, float, Clock)","url":"%3Cinit%3E(int,int,int,float,float,com.google.android.exoplayer2.util.Clock)"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection.Factory","l":"Factory(int, int, int, float)","url":"%3Cinit%3E(int,int,int,float)"},{"p":"com.google.android.exoplayer2.trackselection","c":"RandomTrackSelection.Factory","l":"Factory(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveDataSet.Factory","l":"Factory(long, double, Random)","url":"%3Cinit%3E(long,double,java.util.Random)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"Factory(SsChunkSource.Factory, DataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.smoothstreaming.SsChunkSource.Factory,com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.testutil","c":"FailOnCloseDataSink","l":"FailOnCloseDataSink(Cache, AtomicBoolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,java.util.concurrent.atomic.AtomicBoolean)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"failOnSpuriousAudioTimestamp"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"FAILURE_REASON_NONE"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"FAILURE_REASON_UNKNOWN"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"failureReason"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"FAKE_MEDIA_ITEM"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"FAKE_MEDIA_ITEM"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"FAKE_PROVISION_REQUEST"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"FakeAdaptiveMediaPeriod(TrackGroupArray, MediaSourceEventListener.EventDispatcher, Allocator, FakeChunkSource.Factory, long, TransferListener)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher,com.google.android.exoplayer2.upstream.Allocator,com.google.android.exoplayer2.testutil.FakeChunkSource.Factory,long,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaSource","l":"FakeAdaptiveMediaSource(Timeline, TrackGroupArray, FakeChunkSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.Timeline,com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.testutil.FakeChunkSource.Factory)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAudioRenderer","l":"FakeAudioRenderer(Handler, AudioRendererEventListener)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource","l":"FakeChunkSource(ExoTrackSelection, DataSource, FakeAdaptiveDataSet)","url":"%3Cinit%3E(com.google.android.exoplayer2.trackselection.ExoTrackSelection,com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.testutil.FakeAdaptiveDataSet)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock","l":"FakeClock(boolean)","url":"%3Cinit%3E(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock","l":"FakeClock(long, boolean)","url":"%3Cinit%3E(long,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock","l":"FakeClock(long, long, boolean)","url":"%3Cinit%3E(long,long,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock","l":"FakeClock(long)","url":"%3Cinit%3E(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource.Factory","l":"fakeDataSet"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet","l":"FakeDataSet()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource","l":"FakeDataSource()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource","l":"FakeDataSource(FakeDataSet, boolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.testutil.FakeDataSet,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource","l":"FakeDataSource(FakeDataSet)","url":"%3Cinit%3E(com.google.android.exoplayer2.testutil.FakeDataSet)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"FakeExoMediaDrm()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"FakeExoMediaDrm(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorOutput","l":"FakeExtractorOutput()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorOutput","l":"FakeExtractorOutput(FakeTrackOutput.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.testutil.FakeTrackOutput.Factory)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaChunk","l":"FakeMediaChunk(Format, long, long, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format,long,long,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaChunk","l":"FakeMediaChunk(Format, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format,long,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaChunkIterator","l":"FakeMediaChunkIterator(long[], long[])","url":"%3Cinit%3E(long[],long[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaClockRenderer","l":"FakeMediaClockRenderer(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"FakeMediaPeriod(TrackGroupArray, Allocator, FakeMediaPeriod.TrackDataFactory, MediaSourceEventListener.EventDispatcher, DrmSessionManager, DrmSessionEventListener.EventDispatcher, boolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.upstream.Allocator,com.google.android.exoplayer2.testutil.FakeMediaPeriod.TrackDataFactory,com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"FakeMediaPeriod(TrackGroupArray, Allocator, long, MediaSourceEventListener.EventDispatcher, DrmSessionManager, DrmSessionEventListener.EventDispatcher, boolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.upstream.Allocator,long,com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"FakeMediaPeriod(TrackGroupArray, Allocator, long, MediaSourceEventListener.EventDispatcher)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.upstream.Allocator,long,com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"FakeMediaSource()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"FakeMediaSource(Timeline, DrmSessionManager, FakeMediaPeriod.TrackDataFactory, Format...)","url":"%3Cinit%3E(com.google.android.exoplayer2.Timeline,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.testutil.FakeMediaPeriod.TrackDataFactory,com.google.android.exoplayer2.Format...)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"FakeMediaSource(Timeline, DrmSessionManager, FakeMediaPeriod.TrackDataFactory, TrackGroupArray)","url":"%3Cinit%3E(com.google.android.exoplayer2.Timeline,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.testutil.FakeMediaPeriod.TrackDataFactory,com.google.android.exoplayer2.source.TrackGroupArray)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"FakeMediaSource(Timeline, DrmSessionManager, Format...)","url":"%3Cinit%3E(com.google.android.exoplayer2.Timeline,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.Format...)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"FakeMediaSource(Timeline, Format...)","url":"%3Cinit%3E(com.google.android.exoplayer2.Timeline,com.google.android.exoplayer2.Format...)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"FakeRenderer(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"FakeSampleStream(Allocator, MediaSourceEventListener.EventDispatcher, DrmSessionManager, DrmSessionEventListener.EventDispatcher, Format, List)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.Allocator,com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher,com.google.android.exoplayer2.Format,java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeShuffleOrder","l":"FakeShuffleOrder(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"FakeTimeline()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"FakeTimeline(FakeTimeline.TimelineWindowDefinition...)","url":"%3Cinit%3E(com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition...)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"FakeTimeline(int, Object...)","url":"%3Cinit%3E(int,java.lang.Object...)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"FakeTimeline(Object[], FakeTimeline.TimelineWindowDefinition...)","url":"%3Cinit%3E(java.lang.Object[],com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition...)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"FakeTrackOutput(boolean)","url":"%3Cinit%3E(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"FakeTrackSelection(TrackGroup)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroup)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelector","l":"FakeTrackSelector()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelector","l":"FakeTrackSelector(boolean)","url":"%3Cinit%3E(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.FakeTransferListener","l":"FakeTransferListener()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeVideoRenderer","l":"FakeVideoRenderer(Handler, VideoRendererEventListener)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer.DecoderInitializationException","l":"fallbackDecoderInitializationException"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"fatalErrorCount"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"fatalErrorHistory"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"fatalErrorPlaybackCount"},{"p":"com.google.android.exoplayer2.database","c":"VersionTable","l":"FEATURE_CACHE_CONTENT_METADATA"},{"p":"com.google.android.exoplayer2.database","c":"VersionTable","l":"FEATURE_CACHE_FILE_METADATA"},{"p":"com.google.android.exoplayer2.database","c":"VersionTable","l":"FEATURE_EXTERNAL"},{"p":"com.google.android.exoplayer2.database","c":"VersionTable","l":"FEATURE_OFFLINE"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegAudioRenderer","l":"FfmpegAudioRenderer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegAudioRenderer","l":"FfmpegAudioRenderer(Handler, AudioRendererEventListener, AudioProcessor...)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioProcessor...)"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegAudioRenderer","l":"FfmpegAudioRenderer(Handler, AudioRendererEventListener, AudioSink)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioSink)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheSpan","l":"file"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSource","l":"FileDataSource()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSource.FileDataSourceException","l":"FileDataSourceException(IOException)","url":"%3Cinit%3E(java.io.IOException)"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSource.FileDataSourceException","l":"FileDataSourceException(String, IOException)","url":"%3Cinit%3E(java.lang.String,java.io.IOException)"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSourceFactory","l":"FileDataSourceFactory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSourceFactory","l":"FileDataSourceFactory(TransferListener)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"GeobFrame","l":"filename"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"FilteringHlsPlaylistParserFactory","l":"FilteringHlsPlaylistParserFactory(HlsPlaylistParserFactory, List)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParserFactory,java.util.List)"},{"p":"com.google.android.exoplayer2.offline","c":"FilteringManifestParser","l":"FilteringManifestParser(ParsingLoadable.Parser, List)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.ParsingLoadable.Parser,java.util.List)"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"filterRequirements(int)"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil","l":"findNalUnit(byte[], int, int, boolean[])","url":"findNalUnit(byte[],int,int,boolean[])"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttParserUtil","l":"findNextCueHeader(ParsableByteArray)","url":"findNextCueHeader(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsUtil","l":"findSyncBytePosition(byte[], int, int)","url":"findSyncBytePosition(byte[],int,int)"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"findTrueHdSyncframeOffset(ByteBuffer)","url":"findTrueHdSyncframeOffset(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.analytics","c":"DefaultPlaybackSessionManager","l":"finishAllSessions(AnalyticsListener.EventTime)","url":"finishAllSessions(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackSessionManager","l":"finishAllSessions(AnalyticsListener.EventTime)","url":"finishAllSessions(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap.SeekPoints","l":"first"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"firstPeriodIndex"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"firstReportedTimeMs"},{"p":"com.google.android.exoplayer2.trackselection","c":"FixedTrackSelection","l":"FixedTrackSelection(TrackGroup, int, int, int, Object)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroup,int,int,int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.trackselection","c":"FixedTrackSelection","l":"FixedTrackSelection(TrackGroup, int, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroup,int,int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"FixedTrackSelection","l":"FixedTrackSelection(TrackGroup, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroup,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"fixSmoothStreamingIsmManifestUri(Uri)","url":"fixSmoothStreamingIsmManifestUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"FLAC"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacDecoder","l":"FlacDecoder(int, int, int, List)","url":"%3Cinit%3E(int,int,int,java.util.List)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacExtractor","l":"FlacExtractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.flac","c":"FlacExtractor","l":"FlacExtractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacExtractor","l":"FlacExtractor(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.extractor.flac","c":"FlacExtractor","l":"FlacExtractor(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacSeekTableSeekMap","l":"FlacSeekTableSeekMap(FlacStreamMetadata, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.FlacStreamMetadata,long)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacMetadataReader.FlacStreamMetadataHolder","l":"flacStreamMetadata"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"FlacStreamMetadata(byte[], int)","url":"%3Cinit%3E(byte[],int)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"FlacStreamMetadata(int, int, int, int, int, int, int, long, ArrayList, ArrayList)","url":"%3Cinit%3E(int,int,int,int,int,int,int,long,java.util.ArrayList,java.util.ArrayList)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacMetadataReader.FlacStreamMetadataHolder","l":"FlacStreamMetadataHolder(FlacStreamMetadata)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.FlacStreamMetadata)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"FLAG_ALLOW_CACHE_FRAGMENTATION"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"FLAG_ALLOW_GZIP"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DefaultTsPayloadReaderFactory","l":"FLAG_ALLOW_NON_IDR_KEYFRAMES"},{"p":"com.google.android.exoplayer2","c":"C","l":"FLAG_AUDIBILITY_ENFORCED"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"FLAG_BLOCK_ON_CACHE"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader","l":"FLAG_DATA_ALIGNMENT_INDICATOR"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DefaultTsPayloadReaderFactory","l":"FLAG_DETECT_ACCESS_UNITS"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacExtractor","l":"FLAG_DISABLE_ID3_METADATA"},{"p":"com.google.android.exoplayer2.extractor.flac","c":"FlacExtractor","l":"FLAG_DISABLE_ID3_METADATA"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"FLAG_DISABLE_ID3_METADATA"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"FLAG_DISABLE_SEEK_FOR_CUES"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"FLAG_DONT_CACHE_IF_LENGTH_UNKNOWN"},{"p":"com.google.android.exoplayer2.extractor.amr","c":"AmrExtractor","l":"FLAG_ENABLE_CONSTANT_BITRATE_SEEKING"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"FLAG_ENABLE_CONSTANT_BITRATE_SEEKING"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsExtractor","l":"FLAG_ENABLE_CONSTANT_BITRATE_SEEKING"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"FLAG_ENABLE_EMSG_TRACK"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DefaultTsPayloadReaderFactory","l":"FLAG_ENABLE_HDMV_DTS_AUDIO_STREAMS"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"FLAG_ENABLE_INDEX_SEEKING"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DefaultTsPayloadReaderFactory","l":"FLAG_IGNORE_AAC_STREAM"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"FLAG_IGNORE_CACHE_FOR_UNSET_LENGTH_REQUESTS"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"FLAG_IGNORE_CACHE_ON_ERROR"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DefaultTsPayloadReaderFactory","l":"FLAG_IGNORE_H264_STREAM"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DefaultTsPayloadReaderFactory","l":"FLAG_IGNORE_SPLICE_INFO_STREAM"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"FLAG_MIGHT_NOT_USE_FULL_NETWORK_SPEED"},{"p":"com.google.android.exoplayer2.source","c":"SampleStream","l":"FLAG_OMIT_SAMPLE_DATA"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DefaultTsPayloadReaderFactory","l":"FLAG_OVERRIDE_CAPTION_DESCRIPTORS"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader","l":"FLAG_PAYLOAD_UNIT_START_INDICATOR"},{"p":"com.google.android.exoplayer2.source","c":"SampleStream","l":"FLAG_PEEK"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader","l":"FLAG_RANDOM_ACCESS_INDICATOR"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"FLAG_READ_MOTION_PHOTO_METADATA"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"FLAG_READ_SEF_DATA"},{"p":"com.google.android.exoplayer2.source","c":"SampleStream","l":"FLAG_REQUIRE_FORMAT"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"FLAG_WORKAROUND_IGNORE_EDIT_LISTS"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"FLAG_WORKAROUND_IGNORE_EDIT_LISTS"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"FLAG_WORKAROUND_IGNORE_TFDT_BOX"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes","l":"flags"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter.Configuration","l":"flags"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"flags"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"flip()"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"floatElement(int, double)","url":"floatElement(int,double)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"floatElement(int, double)","url":"floatElement(int,double)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor","l":"flush()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"flush()"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"flush()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"flush()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"flush()"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"flush()"},{"p":"com.google.android.exoplayer2.decoder","c":"Decoder","l":"flush()"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleDecoder","l":"flush()"},{"p":"com.google.android.exoplayer2.ext.gvr","c":"GvrAudioProcessor","l":"flush()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"flush()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"flush()"},{"p":"com.google.android.exoplayer2.testutil","c":"CapturingAudioSink","l":"flush()"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea608Decoder","l":"flush()"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea708Decoder","l":"flush()"},{"p":"com.google.android.exoplayer2.audio","c":"TeeAudioProcessor.AudioBufferSink","l":"flush(int, int, int)","url":"flush(int,int,int)"},{"p":"com.google.android.exoplayer2.audio","c":"TeeAudioProcessor.WavFileAudioBufferSink","l":"flush(int, int, int)","url":"flush(int,int,int)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"flushDecoder()"},{"p":"com.google.android.exoplayer2.util","c":"ListenerSet","l":"flushEvents()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"flushOrReinitializeCodec()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"flushOrReleaseCodec()"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"FLV"},{"p":"com.google.android.exoplayer2.extractor.flv","c":"FlvExtractor","l":"FlvExtractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.audio","c":"WavUtil","l":"FMT_FOURCC"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPayloadFormat","l":"fmtpParameters"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"focusSkipButton()"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"FOLDER_TYPE_ALBUMS"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"FOLDER_TYPE_ARTISTS"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"FOLDER_TYPE_GENRES"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"FOLDER_TYPE_MIXED"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"FOLDER_TYPE_PLAYLISTS"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"FOLDER_TYPE_TITLES"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"FOLDER_TYPE_YEARS"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"folderType"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"FONT_SIZE_UNIT_EM"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"FONT_SIZE_UNIT_PERCENT"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"FONT_SIZE_UNIT_PIXEL"},{"p":"com.google.android.exoplayer2.robolectric","c":"ShadowMediaCodecConfig","l":"forAllSupportedMimeTypes()"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaCrypto","l":"forceAllowInsecureDecoderComponents"},{"p":"com.google.android.exoplayer2","c":"MediaItem.DrmConfiguration","l":"forceDefaultLicenseUri"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"forceHighestSupportedBitrate"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"forceLowestBitrate"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"forceStop()"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity.HostedTest","l":"forceStop()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forDash(Context, Uri, DataSource.Factory, RenderersFactory)","url":"forDash(android.content.Context,android.net.Uri,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.RenderersFactory)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forDash(Uri, DataSource.Factory, RenderersFactory, DrmSessionManager, DefaultTrackSelector.Parameters)","url":"forDash(android.net.Uri,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.RenderersFactory,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"FOREGROUND_NOTIFICATION_ID_NONE"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"foregroundColor"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"foregroundPlaybackCount"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forHls(Context, Uri, DataSource.Factory, RenderersFactory)","url":"forHls(android.content.Context,android.net.Uri,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.RenderersFactory)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forHls(Uri, DataSource.Factory, RenderersFactory, DrmSessionManager, DefaultTrackSelector.Parameters)","url":"forHls(android.net.Uri,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.RenderersFactory,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters)"},{"p":"com.google.android.exoplayer2","c":"FormatHolder","l":"format"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndFormat","l":"format"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.ConfigurationException","l":"format"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.InitializationException","l":"format"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.WriteException","l":"format"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"format"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter.Configuration","l":"format"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser.RepresentationInfo","l":"format"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"format"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Rendition","l":"format"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Variant","l":"format"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPayloadFormat","l":"format"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderInputBuffer","l":"format"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"format"},{"p":"com.google.android.exoplayer2","c":"C","l":"FORMAT_EXCEEDS_CAPABILITIES"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"FORMAT_EXCEEDS_CAPABILITIES"},{"p":"com.google.android.exoplayer2","c":"C","l":"FORMAT_HANDLED"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"FORMAT_HANDLED"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"FORMAT_SUPPORT_MASK"},{"p":"com.google.android.exoplayer2","c":"C","l":"FORMAT_UNSUPPORTED_DRM"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"FORMAT_UNSUPPORTED_DRM"},{"p":"com.google.android.exoplayer2","c":"C","l":"FORMAT_UNSUPPORTED_SUBTYPE"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"FORMAT_UNSUPPORTED_SUBTYPE"},{"p":"com.google.android.exoplayer2","c":"C","l":"FORMAT_UNSUPPORTED_TYPE"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"FORMAT_UNSUPPORTED_TYPE"},{"p":"com.google.android.exoplayer2.extractor","c":"DummyTrackOutput","l":"format(Format)","url":"format(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput","l":"format(Format)","url":"format(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"format(Format)","url":"format(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler.PlayerTrackEmsgHandler","l":"format(Format)","url":"format(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream.FakeSampleStreamItem","l":"format(Format)","url":"format(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"format(Format)","url":"format(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2","c":"FormatHolder","l":"FormatHolder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"formatInvariant(String, Object...)","url":"formatInvariant(java.lang.String,java.lang.Object...)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"formats"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forMediaItem(Context, MediaItem, RenderersFactory, DataSource.Factory)","url":"forMediaItem(android.content.Context,com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.RenderersFactory,com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forMediaItem(Context, MediaItem)","url":"forMediaItem(android.content.Context,com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forMediaItem(MediaItem, DefaultTrackSelector.Parameters, RenderersFactory, DataSource.Factory, DrmSessionManager)","url":"forMediaItem(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters,com.google.android.exoplayer2.RenderersFactory,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.drm.DrmSessionManager)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forMediaItem(MediaItem, DefaultTrackSelector.Parameters, RenderersFactory, DataSource.Factory)","url":"forMediaItem(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters,com.google.android.exoplayer2.RenderersFactory,com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forProgressive(Context, Uri, String)","url":"forProgressive(android.content.Context,android.net.Uri,java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forProgressive(Context, Uri)","url":"forProgressive(android.content.Context,android.net.Uri)"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher","l":"forResources(Iterable)","url":"forResources(java.lang.Iterable)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forSmoothStreaming(Context, Uri, DataSource.Factory, RenderersFactory)","url":"forSmoothStreaming(android.content.Context,android.net.Uri,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.RenderersFactory)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forSmoothStreaming(Uri, DataSource.Factory, RenderersFactory, DrmSessionManager, DefaultTrackSelector.Parameters)","url":"forSmoothStreaming(android.net.Uri,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.RenderersFactory,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forSmoothStreaming(Uri, DataSource.Factory, RenderersFactory)","url":"forSmoothStreaming(android.net.Uri,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.RenderersFactory)"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"ForwardingAudioSink(AudioSink)","url":"%3Cinit%3E(com.google.android.exoplayer2.audio.AudioSink)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"ForwardingExtractorInput(ExtractorInput)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.source","c":"ForwardingTimeline","l":"ForwardingTimeline(Timeline)","url":"%3Cinit%3E(com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"FragmentedMp4Extractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"FragmentedMp4Extractor(int, TimestampAdjuster, Track, List, TrackOutput)","url":"%3Cinit%3E(int,com.google.android.exoplayer2.util.TimestampAdjuster,com.google.android.exoplayer2.extractor.mp4.Track,java.util.List,com.google.android.exoplayer2.extractor.TrackOutput)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"FragmentedMp4Extractor(int, TimestampAdjuster, Track, List)","url":"%3Cinit%3E(int,com.google.android.exoplayer2.util.TimestampAdjuster,com.google.android.exoplayer2.extractor.mp4.Track,java.util.List)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"FragmentedMp4Extractor(int, TimestampAdjuster, Track)","url":"%3Cinit%3E(int,com.google.android.exoplayer2.util.TimestampAdjuster,com.google.android.exoplayer2.extractor.mp4.Track)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"FragmentedMp4Extractor(int, TimestampAdjuster)","url":"%3Cinit%3E(int,com.google.android.exoplayer2.util.TimestampAdjuster)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"FragmentedMp4Extractor(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"frameMbsOnlyFlag"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"frameNumLength"},{"p":"com.google.android.exoplayer2","c":"Format","l":"frameRate"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util.SyncFrameInfo","l":"frameSize"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util.SyncFrameInfo","l":"frameSize"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil.Header","l":"frameSize"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaCrypto","l":"FrameworkMediaCrypto(UUID, byte[], boolean)","url":"%3Cinit%3E(java.util.UUID,byte[],boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.VorbisIdHeader","l":"framingFlag"},{"p":"com.google.android.exoplayer2","c":"Bundleable.Creator","l":"fromBundle(Bundle)","url":"fromBundle(android.os.Bundle)"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"fromUri(String)","url":"fromUri(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"fromUri(Uri)","url":"fromUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"fromUtf8Bytes(byte[], int, int)","url":"fromUtf8Bytes(byte[],int,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"fromUtf8Bytes(byte[])"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.SegmentBase","l":"fullSegmentEncryptionKeyUri"},{"p":"com.google.android.exoplayer2.extractor","c":"GaplessInfoHolder","l":"GaplessInfoHolder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Gav1Decoder","l":"Gav1Decoder(int, int, int, int)","url":"%3Cinit%3E(int,int,int,int)"},{"p":"com.google.android.exoplayer2","c":"C","l":"generateAudioSessionIdV21(Context)","url":"generateAudioSessionIdV21(android.content.Context)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"generateCurrentPlayerMediaPeriodEventTime()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"generateEventTime(Timeline, int, MediaSource.MediaPeriodId)","url":"generateEventTime(com.google.android.exoplayer2.Timeline,int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.TrackIdGenerator","l":"generateNewId()"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"genre"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"GeobFrame","l":"GeobFrame(String, String, String, byte[])","url":"%3Cinit%3E(java.lang.String,java.lang.String,java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.util","c":"RunnableFutureTask","l":"get()"},{"p":"com.google.android.exoplayer2","c":"Player.Commands","l":"get(int)"},{"p":"com.google.android.exoplayer2","c":"Player.Events","l":"get(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.Events","l":"get(int)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"get(int)"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata","l":"get(int)"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroupArray","l":"get(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionArray","l":"get(int)"},{"p":"com.google.android.exoplayer2.util","c":"ExoFlags","l":"get(int)"},{"p":"com.google.android.exoplayer2.util","c":"LongArray","l":"get(int)"},{"p":"com.google.android.exoplayer2.util","c":"RunnableFutureTask","l":"get(long, TimeUnit)","url":"get(long,java.util.concurrent.TimeUnit)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManagerProvider","l":"get(MediaItem)","url":"get(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionManagerProvider","l":"get(MediaItem)","url":"get(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadata","l":"get(String, byte[])","url":"get(java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"DefaultContentMetadata","l":"get(String, byte[])","url":"get(java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadata","l":"get(String, long)","url":"get(java.lang.String,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"DefaultContentMetadata","l":"get(String, long)","url":"get(java.lang.String,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadata","l":"get(String, String)","url":"get(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"DefaultContentMetadata","l":"get(String, String)","url":"get(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getAbandonedBeforeReadyRatio()"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util","l":"getAc4SampleHeader(int, ParsableByteArray)","url":"getAc4SampleHeader(int,com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"getActionIndicesForCompactView(List, Player)","url":"getActionIndicesForCompactView(java.util.List,com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"getActions(Player)","url":"getActions(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.QueueNavigator","l":"getActiveQueueItemId(Player)","url":"getActiveQueueItemId(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueNavigator","l":"getActiveQueueItemId(Player)","url":"getActiveQueueItemId(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.analytics","c":"DefaultPlaybackSessionManager","l":"getActiveSessionId()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackSessionManager","l":"getActiveSessionId()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Period","l":"getAdaptationSetIndex(int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getAdaptiveMimeTypeForContentType(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"getAdaptiveSupport(int, int, boolean)","url":"getAdaptiveSupport(int,int,boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"getAdaptiveSupport(int, int, int[])","url":"getAdaptiveSupport(int,int,int[])"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"getAdaptiveSupport(int)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getAdCountInAdGroup(int)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"getAdDisplayContainer()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"DefaultCastOptionsProvider","l":"getAdditionalSessionProviders(Context)","url":"getAdditionalSessionProviders(android.content.Context)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getAdDurationUs(int, int)","url":"getAdDurationUs(int,int)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getAdGroupCount()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"getAdGroupIndexAfterPositionUs(long, long)","url":"getAdGroupIndexAfterPositionUs(long,long)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getAdGroupIndexAfterPositionUs(long)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"getAdGroupIndexForPositionUs(long, long)","url":"getAdGroupIndexForPositionUs(long,long)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getAdGroupIndexForPositionUs(long)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getAdGroupTimeUs(int)"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl","l":"getAdjustedPlaybackSpeed(long, long)","url":"getAdjustedPlaybackSpeed(long,long)"},{"p":"com.google.android.exoplayer2","c":"LivePlaybackSpeedControl","l":"getAdjustedPlaybackSpeed(long, long)","url":"getAdjustedPlaybackSpeed(long,long)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"getAdjustedSeekPositionUs(long, SeekParameters)","url":"getAdjustedSeekPositionUs(long,com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"getAdjustedSeekPositionUs(long, SeekParameters)","url":"getAdjustedSeekPositionUs(long,com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"getAdjustedSeekPositionUs(long, SeekParameters)","url":"getAdjustedSeekPositionUs(long,com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"getAdjustedSeekPositionUs(long, SeekParameters)","url":"getAdjustedSeekPositionUs(long,com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSource","l":"getAdjustedSeekPositionUs(long, SeekParameters)","url":"getAdjustedSeekPositionUs(long,com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"getAdjustedSeekPositionUs(long, SeekParameters)","url":"getAdjustedSeekPositionUs(long,com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"getAdjustedSeekPositionUs(long, SeekParameters)","url":"getAdjustedSeekPositionUs(long,com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource","l":"getAdjustedSeekPositionUs(long, SeekParameters)","url":"getAdjustedSeekPositionUs(long,com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"getAdjustedSeekPositionUs(long, SeekParameters)","url":"getAdjustedSeekPositionUs(long,com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource","l":"getAdjustedSeekPositionUs(long, SeekParameters)","url":"getAdjustedSeekPositionUs(long,com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"getAdjustedSeekPositionUs(long, SeekParameters)","url":"getAdjustedSeekPositionUs(long,com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"getAdjustedUpstreamFormat(Format)","url":"getAdjustedUpstreamFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.source.hls","c":"TimestampAdjusterProvider","l":"getAdjuster(int)"},{"p":"com.google.android.exoplayer2.ui","c":"AdViewProvider","l":"getAdOverlayInfos()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getAdOverlayInfos()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getAdOverlayInfos()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getAdResumePositionUs()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getAdsId()"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"getAdsLoader()"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory.AdsLoaderProvider","l":"getAdsLoader(MediaItem.AdsConfiguration)","url":"getAdsLoader(com.google.android.exoplayer2.MediaItem.AdsConfiguration)"},{"p":"com.google.android.exoplayer2.ui","c":"AdViewProvider","l":"getAdViewGroup()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getAdViewGroup()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getAdViewGroup()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionArray","l":"getAll()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet","l":"getAllData()"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"getAllocator()"},{"p":"com.google.android.exoplayer2","c":"LoadControl","l":"getAllocator()"},{"p":"com.google.android.exoplayer2.robolectric","c":"RandomizedMp3Decoder","l":"getAllOutputBytes()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.AllowedCommandProvider","l":"getAllowedCommands(MediaSession, MediaSession.ControllerInfo, SessionCommandGroup)","url":"getAllowedCommands(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo,androidx.media2.session.SessionCommandGroup)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.DefaultAllowedCommandProvider","l":"getAllowedCommands(MediaSession, MediaSession.ControllerInfo, SessionCommandGroup)","url":"getAllowedCommands(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo,androidx.media2.session.SessionCommandGroup)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelector","l":"getAllTrackSelections()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getAnalyticsCollector()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource","l":"getAndClearOpenedDataSpecs()"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"InputReaderAdapterV30","l":"getAndResetSeekPosition()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getApplicationLooper()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getApplicationLooper()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getApplicationLooper()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"getApplicationLooper()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getApplicationLooper()"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer","l":"getApplicationLooper()"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"getApproxBytesPerFrame()"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil","l":"getAttributes(int)"},{"p":"com.google.android.exoplayer2.util","c":"XmlPullParserUtil","l":"getAttributeValue(XmlPullParser, String)","url":"getAttributeValue(org.xmlpull.v1.XmlPullParser,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"XmlPullParserUtil","l":"getAttributeValueIgnorePrefix(XmlPullParser, String)","url":"getAttributeValueIgnorePrefix(org.xmlpull.v1.XmlPullParser,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioComponent","l":"getAudioAttributes()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getAudioAttributes()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getAudioAttributes()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getAudioAttributes()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getAudioAttributes()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getAudioAttributes()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes","l":"getAudioAttributesV21()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getAudioComponent()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getAudioComponent()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getAudioComponent()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getAudioContentTypeForStreamType(int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getAudioDecoderCounters()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getAudioFormat()"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"getAudioMediaMimeType(String)","url":"getAudioMediaMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink.AudioProcessorChain","l":"getAudioProcessors()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink.DefaultAudioProcessorChain","l":"getAudioProcessors()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioComponent","l":"getAudioSessionId()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getAudioSessionId()"},{"p":"com.google.android.exoplayer2.util","c":"DebugTextViewHelper","l":"getAudioString()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getAudioTrackChannelConfig(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getAudioUnderrunRate()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getAudioUsageForStreamType(int)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getAvailableCommands()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getAvailableCommands()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getAvailableCommands()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getAvailableCommands()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"getAvailableCommands(Player.Commands)","url":"getAvailableCommands(com.google.android.exoplayer2.Player.Commands)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashSegmentIndex","l":"getAvailableSegmentCount(long, long)","url":"getAvailableSegmentCount(long,long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashWrappingSegmentIndex","l":"getAvailableSegmentCount(long, long)","url":"getAvailableSegmentCount(long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"getAvailableSegmentCount(long, long)","url":"getAvailableSegmentCount(long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.MultiSegmentBase","l":"getAvailableSegmentCount(long, long)","url":"getAvailableSegmentCount(long,long)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"getBackBufferDurationUs()"},{"p":"com.google.android.exoplayer2","c":"LoadControl","l":"getBackBufferDurationUs()"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"getBackgroundColor()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"getBandwidthMeter()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelector","l":"getBandwidthMeter()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getBigEndianInt(ByteBuffer, int)","url":"getBigEndianInt(java.nio.ByteBuffer,int)"},{"p":"com.google.android.exoplayer2.util","c":"BundleUtil","l":"getBinder(Bundle, String)","url":"getBinder(android.os.Bundle,java.lang.String)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getBitmap()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"getBitmap(Context, String)","url":"getBitmap(android.content.Context,java.lang.String)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getBitmapHeight()"},{"p":"com.google.android.exoplayer2.upstream","c":"BandwidthMeter","l":"getBitrateEstimate()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"getBitrateEstimate()"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy","l":"getBlacklistDurationMsFor(int, long, IOException, int)","url":"getBlacklistDurationMsFor(int,long,java.io.IOException,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultLoadErrorHandlingPolicy","l":"getBlacklistDurationMsFor(LoadErrorHandlingPolicy.LoadErrorInfo)","url":"getBlacklistDurationMsFor(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.LoadErrorInfo)"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy","l":"getBlacklistDurationMsFor(LoadErrorHandlingPolicy.LoadErrorInfo)","url":"getBlacklistDurationMsFor(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.LoadErrorInfo)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"getBufferedPercentage()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getBufferedPercentage()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getBufferedPosition()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getBufferedPosition()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getBufferedPosition()"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"getBufferedPosition()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getBufferedPosition()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getBufferedPosition()"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"getBufferedPositionUs()"},{"p":"com.google.android.exoplayer2.source","c":"CompositeSequenceableLoader","l":"getBufferedPositionUs()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"getBufferedPositionUs()"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"getBufferedPositionUs()"},{"p":"com.google.android.exoplayer2.source","c":"SequenceableLoader","l":"getBufferedPositionUs()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"getBufferedPositionUs()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"getBufferedPositionUs()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"getBufferedPositionUs()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"getBufferedPositionUs()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getBufferingState()"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxLibrary","l":"getBuildConfig()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"getByteArray(Context, String)","url":"getByteArray(android.content.Context,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"getBytePosition()"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"getBytesDownloaded()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getBytesFromHexString(String)","url":"getBytesFromHexString(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"StatsDataSource","l":"getBytesRead()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"getCache()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"getCache()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"getCachedBytes(String, long, long)","url":"getCachedBytes(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"getCachedBytes(String, long, long)","url":"getCachedBytes(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"getCachedLength(String, long, long)","url":"getCachedLength(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"getCachedLength(String, long, long)","url":"getCachedLength(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"getCachedSpans(String)","url":"getCachedSpans(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"getCachedSpans(String)","url":"getCachedSpans(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"getCacheKey()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"getCacheKey()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.SingleSegmentRepresentation","l":"getCacheKey()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"getCacheKeyFactory()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"getCacheKeyFactory()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"getCacheSpace()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"getCacheSpace()"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView","l":"getCameraMotionListener()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"getCapabilities()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"getCapabilities()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"getCapabilities()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioCapabilities","l":"getCapabilities(Context)","url":"getCapabilities(android.content.Context)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"DefaultCastOptionsProvider","l":"getCastOptions(Context)","url":"getCastOptions(android.content.Context)"},{"p":"com.google.android.exoplayer2.audio","c":"OpusUtil","l":"getChannelCount(byte[])"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getChildIndexByChildUid(Object)","url":"getChildIndexByChildUid(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getChildIndexByPeriodIndex(int)"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getChildIndexByWindowIndex(int)"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getChildPeriodUidFromConcatenatedUid(Object)","url":"getChildPeriodUidFromConcatenatedUid(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getChildTimelineUidFromConcatenatedUid(Object)","url":"getChildTimelineUidFromConcatenatedUid(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getChildUidByChildIndex(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveDataSet","l":"getChunkCount()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveDataSet","l":"getChunkDuration(int)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"getChunkDurationUs(int)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaChunkIterator","l":"getChunkEndTimeUs()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationSegmentIterator","l":"getChunkEndTimeUs()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveDataSet.Iterator","l":"getChunkEndTimeUs()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaChunkIterator","l":"getChunkEndTimeUs()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BundledChunkExtractor","l":"getChunkIndex()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkExtractor","l":"getChunkIndex()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaParserChunkExtractor","l":"getChunkIndex()"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"getChunkIndex()"},{"p":"com.google.android.exoplayer2.extractor","c":"ChunkIndex","l":"getChunkIndex(long)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"getChunkIndex(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveDataSet","l":"getChunkIndexByPosition(long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"getChunkSource()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaChunkIterator","l":"getChunkStartTimeUs()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationSegmentIterator","l":"getChunkStartTimeUs()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveDataSet.Iterator","l":"getChunkStartTimeUs()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaChunkIterator","l":"getChunkStartTimeUs()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getClock()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getClock()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getClock()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"getClock()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"getCodec()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getCodecCountOfType(String, int)","url":"getCodecCountOfType(java.lang.String,int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"getCodecInfo()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"getCodecMaxInputSize(MediaCodecInfo, Format, Format[])","url":"getCodecMaxInputSize(com.google.android.exoplayer2.mediacodec.MediaCodecInfo,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format[])"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"getCodecMaxValues(MediaCodecInfo, Format, Format[])","url":"getCodecMaxValues(com.google.android.exoplayer2.mediacodec.MediaCodecInfo,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format[])"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"getCodecNeedsEosPropagation()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"getCodecNeedsEosPropagation()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"getCodecOperatingRate()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"getCodecOperatingRateV23(float, Format, Format[])","url":"getCodecOperatingRateV23(float,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format[])"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"getCodecOperatingRateV23(float, Format, Format[])","url":"getCodecOperatingRateV23(float,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format[])"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"getCodecOperatingRateV23(float, Format, Format[])","url":"getCodecOperatingRateV23(float,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format[])"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"getCodecOutputMediaFormat()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecUtil","l":"getCodecProfileAndLevel(Format)","url":"getCodecProfileAndLevel(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"getCodecsCorrespondingToMimeType(String, String)","url":"getCodecsCorrespondingToMimeType(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getCodecsOfType(String, int)","url":"getCodecsOfType(java.lang.String,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"getCombinedPlaybackStats()"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"getCombineUpright()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getCommaDelimitedSimpleClassNames(Object[])","url":"getCommaDelimitedSimpleClassNames(java.lang.Object[])"},{"p":"com.google.android.exoplayer2.offline","c":"SegmentDownloader","l":"getCompressibleDataSpec(Uri)","url":"getCompressibleDataSpec(android.net.Uri)"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getConcatenatedUid(Object, Object)","url":"getConcatenatedUid(java.lang.Object,java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"getConfiguration()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"getConfiguration()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getContentBufferedPosition()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getContentBufferedPosition()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getContentBufferedPosition()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getContentBufferedPosition()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"getContentDuration()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getContentDuration()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadata","l":"getContentLength(ContentMetadata)","url":"getContentLength(com.google.android.exoplayer2.upstream.cache.ContentMetadata)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpUtil","l":"getContentLength(String, String)","url":"getContentLength(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"getContentMetadata(String)","url":"getContentMetadata(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"getContentMetadata(String)","url":"getContentMetadata(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getContentPosition()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getContentPosition()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getContentPosition()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getContentPosition()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getControllerAutoShow()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getControllerAutoShow()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getControllerHideOnTouch()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getControllerHideOnTouch()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getControllerShowTimeoutMs()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getControllerShowTimeoutMs()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"getCount()"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts.RequestSet","l":"getCount()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getCountryCode(Context)","url":"getCountryCode(android.content.Context)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"getCreatedMediaPeriods()"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetEngineWrapper","l":"getCronetEngineSource()"},{"p":"com.google.android.exoplayer2.text","c":"Subtitle","l":"getCues(long)"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleOutputBuffer","l":"getCues(long)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentAdGroupIndex()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getCurrentAdGroupIndex()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getCurrentAdGroupIndex()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getCurrentAdGroupIndex()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentAdIndexInAdGroup()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getCurrentAdIndexInAdGroup()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getCurrentAdIndexInAdGroup()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getCurrentAdIndexInAdGroup()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.MediaDescriptionAdapter","l":"getCurrentContentText(Player)","url":"getCurrentContentText(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.MediaDescriptionAdapter","l":"getCurrentContentTitle(Player)","url":"getCurrentContentTitle(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.TextComponent","l":"getCurrentCues()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentCues()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getCurrentCues()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getCurrentCues()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getCurrentCues()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getCurrentDisplayModeSize(Context, Display)","url":"getCurrentDisplayModeSize(android.content.Context,android.view.Display)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getCurrentDisplayModeSize(Context)","url":"getCurrentDisplayModeSize(android.content.Context)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"getCurrentDownloads()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunkIterator","l":"getCurrentIndex()"},{"p":"com.google.android.exoplayer2.source","c":"BundledExtractorsAdapter","l":"getCurrentInputPosition()"},{"p":"com.google.android.exoplayer2.source","c":"MediaParserExtractorAdapter","l":"getCurrentInputPosition()"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaExtractor","l":"getCurrentInputPosition()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.MediaDescriptionAdapter","l":"getCurrentLargeIcon(Player, PlayerNotificationManager.BitmapCallback)","url":"getCurrentLargeIcon(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ui.PlayerNotificationManager.BitmapCallback)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"getCurrentLiveOffset()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentLiveOffset()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"getCurrentManifest()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentManifest()"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector","l":"getCurrentMappedTrackInfo()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"getCurrentMediaItem()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentMediaItem()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getCurrentMediaItem()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getCurrentMediaItemIndex()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getCurrentOrMainLooper()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentPeriodIndex()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getCurrentPeriodIndex()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getCurrentPeriodIndex()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getCurrentPeriodIndex()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentPosition()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getCurrentPosition()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getCurrentPosition()"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"getCurrentPosition()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getCurrentPosition()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getCurrentPosition()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"getCurrentPositionUs(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"getCurrentPositionUs(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"getCurrentPositionUs(boolean)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentStaticMetadata()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getCurrentStaticMetadata()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getCurrentStaticMetadata()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getCurrentStaticMetadata()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.MediaDescriptionAdapter","l":"getCurrentSubText(Player)","url":"getCurrentSubText(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"getCurrentTag()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentTag()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentTimeline()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getCurrentTimeline()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getCurrentTimeline()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getCurrentTimeline()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentTrackGroups()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getCurrentTrackGroups()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getCurrentTrackGroups()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getCurrentTrackGroups()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentTrackSelections()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getCurrentTrackSelections()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getCurrentTrackSelections()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getCurrentTrackSelections()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"getCurrentUnixTimeMs()"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"getCurrentUrlRequest()"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"getCurrentUrlResponseInfo()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentWindowIndex()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getCurrentWindowIndex()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getCurrentWindowIndex()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getCurrentWindowIndex()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.CustomActionProvider","l":"getCustomAction(Player)","url":"getCustomAction(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"RepeatModeActionProvider","l":"getCustomAction(Player)","url":"getCustomAction(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.CustomActionReceiver","l":"getCustomActions(Player)","url":"getCustomActions(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.CustomCommandProvider","l":"getCustomCommands(MediaSession, MediaSession.ControllerInfo)","url":"getCustomCommands(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyRequest","l":"getData()"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.ProvisionRequest","l":"getData()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData","l":"getData()"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource","l":"getData()"},{"p":"com.google.android.exoplayer2.upstream","c":"ByteArrayDataSink","l":"getData()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"getData()"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts.RequestSet","l":"getData(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet","l":"getData(String)","url":"getData(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet","l":"getData(Uri)","url":"getData(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"DataChunk","l":"getDataHolder()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource","l":"getDataSet()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaChunkIterator","l":"getDataSpec()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationSegmentIterator","l":"getDataSpec()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveDataSet.Iterator","l":"getDataSpec()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaChunkIterator","l":"getDataSpec()"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts.RequestSet","l":"getDataSpec(int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getDataUriForString(String, String)","url":"getDataUriForString(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"DebugTextViewHelper","l":"getDebugString()"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"getDecodedBitrate()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecUtil","l":"getDecoderInfo(String, boolean, boolean)","url":"getDecoderInfo(java.lang.String,boolean,boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"getDecoderInfos(MediaCodecSelector, Format, boolean)","url":"getDecoderInfos(com.google.android.exoplayer2.mediacodec.MediaCodecSelector,com.google.android.exoplayer2.Format,boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"getDecoderInfos(MediaCodecSelector, Format, boolean)","url":"getDecoderInfos(com.google.android.exoplayer2.mediacodec.MediaCodecSelector,com.google.android.exoplayer2.Format,boolean)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"getDecoderInfos(MediaCodecSelector, Format, boolean)","url":"getDecoderInfos(com.google.android.exoplayer2.mediacodec.MediaCodecSelector,com.google.android.exoplayer2.Format,boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecSelector","l":"getDecoderInfos(String, boolean, boolean)","url":"getDecoderInfos(java.lang.String,boolean,boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecUtil","l":"getDecoderInfos(String, boolean, boolean)","url":"getDecoderInfos(java.lang.String,boolean,boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecUtil","l":"getDecoderInfosSortedByFormatSupport(List, Format)","url":"getDecoderInfosSortedByFormatSupport(java.util.List,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecUtil","l":"getDecryptOnlyDecoderInfo()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getDefaultArtwork()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getDefaultArtwork()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"getDefaultPositionMs()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"getDefaultPositionUs()"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"getDefaultRequestProperties()"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource.Factory","l":"getDefaultRequestProperties()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource.Factory","l":"getDefaultRequestProperties()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.BaseFactory","l":"getDefaultRequestProperties()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.Factory","l":"getDefaultRequestProperties()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"getDefaults(Context)","url":"getDefaults(android.content.Context)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"getDefaults(Context)","url":"getDefaults(android.content.Context)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"getDefaultTrackSelectorParameters(Context)","url":"getDefaultTrackSelectorParameters(android.content.Context)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.ProvisionRequest","l":"getDefaultUrl()"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"getDeleteAfterDelivery()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getDeviceComponent()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getDeviceComponent()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getDeviceComponent()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.DeviceComponent","l":"getDeviceInfo()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getDeviceInfo()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getDeviceInfo()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getDeviceInfo()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getDeviceInfo()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.DeviceComponent","l":"getDeviceVolume()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getDeviceVolume()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getDeviceVolume()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getDeviceVolume()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getDeviceVolume()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpUtil","l":"getDocumentSize(String)","url":"getDocumentSize(java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"getDownload()"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloadIndex","l":"getDownload(String)","url":"getDownload(java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadIndex","l":"getDownload(String)","url":"getDownload(java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"getDownloadIndex()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"getDownloadManager()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"getDownloadRequest(byte[])"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"getDownloadRequest(String, byte[])","url":"getDownloadRequest(java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloadIndex","l":"getDownloads(int...)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadIndex","l":"getDownloads(int...)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"getDownloadsPaused()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getDrmUuid(String)","url":"getDrmUuid(java.lang.String)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getDroppedFramesRate()"},{"p":"com.google.android.exoplayer2.audio","c":"DtsUtil","l":"getDtsFrameSize(byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionManager","l":"getDummyDrmSessionManager()"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"getDummySeekMap()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getDuration()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getDuration()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getDuration()"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"getDuration()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getDuration()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getDuration()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getDurationMs()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"getDurationMs()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getDurationUs()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"getDurationUs()"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.BinarySearchSeekMap","l":"getDurationUs()"},{"p":"com.google.android.exoplayer2.extractor","c":"ChunkIndex","l":"getDurationUs()"},{"p":"com.google.android.exoplayer2.extractor","c":"ConstantBitrateSeekMap","l":"getDurationUs()"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacSeekTableSeekMap","l":"getDurationUs()"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"getDurationUs()"},{"p":"com.google.android.exoplayer2.extractor","c":"IndexSeekMap","l":"getDurationUs()"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap","l":"getDurationUs()"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap.Unseekable","l":"getDurationUs()"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"getDurationUs()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"getDurationUs()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashSegmentIndex","l":"getDurationUs(long, long)","url":"getDurationUs(long,long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashWrappingSegmentIndex","l":"getDurationUs(long, long)","url":"getDurationUs(long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"getDurationUs(long, long)","url":"getDurationUs(long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadataMutations","l":"getEditedValues()"},{"p":"com.google.android.exoplayer2.util","c":"SntpClient","l":"getElapsedRealtimeOffsetMs()"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"getElementType(int)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"getElementType(int)"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"getEncoding(String, String)","url":"getEncoding(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"getEncodingForAudioObjectType(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getEndedRatio()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"getEndTimeUs()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"getError()"},{"p":"com.google.android.exoplayer2.drm","c":"ErrorStateDrmSession","l":"getError()"},{"p":"com.google.android.exoplayer2.util","c":"ErrorMessageProvider","l":"getErrorMessage(T)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.Events","l":"getEventTime(int)"},{"p":"com.google.android.exoplayer2.text","c":"Subtitle","l":"getEventTime(int)"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleOutputBuffer","l":"getEventTime(int)"},{"p":"com.google.android.exoplayer2.text","c":"Subtitle","l":"getEventTimeCount()"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleOutputBuffer","l":"getEventTimeCount()"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"getExoMediaCryptoType()"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"getExoMediaCryptoType()"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"getExoMediaCryptoType()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"getExoMediaCryptoType()"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"getExoMediaCryptoType(Format)","url":"getExoMediaCryptoType(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionManager","l":"getExoMediaCryptoType(Format)","url":"getExoMediaCryptoType(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.TestResource","l":"getExpectedBytes()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"getExtractorInputFromPosition(DataSource, long, Uri)","url":"getExtractorInputFromPosition(com.google.android.exoplayer2.upstream.DataSource,long,android.net.Uri)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"getFastForwardIncrementMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getFatalErrorRate()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getFatalErrorRatio()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"getFirstAdIndexToPlay()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getFirstAdIndexToPlay(int)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashSegmentIndex","l":"getFirstAvailableSegmentNum(long, long)","url":"getFirstAvailableSegmentNum(long,long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashWrappingSegmentIndex","l":"getFirstAvailableSegmentNum(long, long)","url":"getFirstAvailableSegmentNum(long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"getFirstAvailableSegmentNum(long, long)","url":"getFirstAvailableSegmentNum(long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.MultiSegmentBase","l":"getFirstAvailableSegmentNum(long, long)","url":"getFirstAvailableSegmentNum(long,long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationHolder","l":"getFirstAvailableSegmentNum(long)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"getFirstIndex()"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder","l":"getFirstIndex()"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.DefaultShuffleOrder","l":"getFirstIndex()"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.UnshuffledShuffleOrder","l":"getFirstIndex()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeShuffleOrder","l":"getFirstIndex()"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getFirstPeriodIndexByChildIndex(int)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunk","l":"getFirstSampleIndex(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacFrameReader","l":"getFirstSampleNumber(ExtractorInput, FlacStreamMetadata)","url":"getFirstSampleNumber(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.FlacStreamMetadata)"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"getFirstSampleTimestampUs()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashSegmentIndex","l":"getFirstSegmentNum()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashWrappingSegmentIndex","l":"getFirstSegmentNum()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationHolder","l":"getFirstSegmentNum()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"getFirstSegmentNum()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.MultiSegmentBase","l":"getFirstSegmentNum()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"getFirstTimestampUs()"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getFirstWindowIndex(boolean)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getFirstWindowIndex(boolean)"},{"p":"com.google.android.exoplayer2.source","c":"ForwardingTimeline","l":"getFirstWindowIndex(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"getFirstWindowIndex(boolean)"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getFirstWindowIndexByChildIndex(int)"},{"p":"com.google.android.exoplayer2.decoder","c":"Buffer","l":"getFlag(int)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"getFontColor()"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"getFontFamily()"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"getFontSize()"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"getFontSizeUnit()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"getForegroundNotification(List)","url":"getForegroundNotification(java.util.List)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"getFormat(byte[], Metadata)","url":"getFormat(byte[],com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroup","l":"getFormat(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"getFormat(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"getFormat(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelection","l":"getFormat(int)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"getFormatHolder()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.TrackIdGenerator","l":"getFormatId()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"getFormatLanguageScore(Format, String, boolean)","url":"getFormatLanguageScore(com.google.android.exoplayer2.Format,java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"getFormatsRead()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"getFormatSupport(Format)","url":"getFormatSupport(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"getFormatSupport(Format)","url":"getFormatSupport(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"getFormatSupport(Format)","url":"getFormatSupport(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"getFormatSupport(int)"},{"p":"com.google.android.exoplayer2","c":"C","l":"getFormatSupportString(int)"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil","l":"getFrameSize(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacMetadataReader","l":"getFrameStartMarker(ExtractorInput)","url":"getFrameStartMarker(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.decoder","c":"CryptoInfo","l":"getFrameworkCryptoInfo()"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource","l":"getGzipSupport()"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil","l":"getH265NalUnitType(byte[], int)","url":"getH265NalUnitType(byte[],int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"getHttpMethodString()"},{"p":"com.google.android.exoplayer2.offline","c":"ActionFileUpgradeUtil.DownloadIdProvider","l":"getId(DownloadRequest)","url":"getId(com.google.android.exoplayer2.offline.DownloadRequest)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpUtils","l":"getIncomingRtpDataSpec(int)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"getIndex()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"getIndex()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"getIndex()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"getIndex()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.SingleSegmentRepresentation","l":"getIndex()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SingleSegmentBase","l":"getIndex()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"getIndexInTrackGroup(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"getIndexInTrackGroup(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelection","l":"getIndexInTrackGroup(int)"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getIndexOfPeriod(Object)","url":"getIndexOfPeriod(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getIndexOfPeriod(Object)","url":"getIndexOfPeriod(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"ForwardingTimeline","l":"getIndexOfPeriod(Object)","url":"getIndexOfPeriod(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource.PlaceholderTimeline","l":"getIndexOfPeriod(Object)","url":"getIndexOfPeriod(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"getIndexOfPeriod(Object)","url":"getIndexOfPeriod(java.lang.Object)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"getIndexOfPeriod(Object)","url":"getIndexOfPeriod(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"getIndexUri()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"getIndexUri()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.SingleSegmentRepresentation","l":"getIndexUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"Allocator","l":"getIndividualAllocationLength()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultAllocator","l":"getIndividualAllocationLength()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase","l":"getInitialization(Representation)","url":"getInitialization(com.google.android.exoplayer2.source.dash.manifest.Representation)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SegmentTemplate","l":"getInitialization(Representation)","url":"getInitialization(com.google.android.exoplayer2.source.dash.manifest.Representation)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"getInitializationUri()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"getInitialStartTimeUs()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"getInitialStartTimeUs()"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"getInitialTimeline()"},{"p":"com.google.android.exoplayer2.source","c":"LoopingMediaSource","l":"getInitialTimeline()"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"getInitialTimeline()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"getInitialTimeline()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"getInMemoryDatabaseProvider()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"getInputBuffer(int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"getInputBuffer(int)"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegLibrary","l":"getInputBufferPaddingSize()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"getInputStream(Context, String)","url":"getInputStream(android.content.Context,java.lang.String)"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"getInstance()"},{"p":"com.google.android.exoplayer2.util","c":"NetworkTypeObserver","l":"getInstance(Context)","url":"getInstance(android.content.Context)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getIntegerCodeForString(String)","url":"getIntegerCodeForString(java.lang.String)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionView","l":"getIsDisabled()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getItem(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getJoinTimeRatio()"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyStatus","l":"getKeyId()"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"getKeyRequest(byte[], List, int, HashMap)","url":"getKeyRequest(byte[],java.util.List,int,java.util.HashMap)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"getKeyRequest(byte[], List, int, HashMap)","url":"getKeyRequest(byte[],java.util.List,int,java.util.HashMap)"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"getKeyRequest(byte[], List, int, HashMap)","url":"getKeyRequest(byte[],java.util.List,int,java.util.HashMap)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"getKeyRequest(byte[], List, int, HashMap)","url":"getKeyRequest(byte[],java.util.List,int,java.util.HashMap)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"getKeys()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"getKeys()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.DrmConfiguration","l":"getKeySetId()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"getLargestQueuedTimestampUs()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"getLargestQueuedTimestampUs()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"getLargestReadTimestampUs()"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"getLastAdjustedTimestampUs()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationHolder","l":"getLastAvailableSegmentNum(long)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder","l":"getLastIndex()"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.DefaultShuffleOrder","l":"getLastIndex()"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.UnshuffledShuffleOrder","l":"getLastIndex()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeShuffleOrder","l":"getLastIndex()"},{"p":"com.google.android.exoplayer2.upstream","c":"StatsDataSource","l":"getLastOpenedUri()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"getLastResetPositionUs()"},{"p":"com.google.android.exoplayer2.upstream","c":"StatsDataSource","l":"getLastResponseHeaders()"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getLastWindowIndex(boolean)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getLastWindowIndex(boolean)"},{"p":"com.google.android.exoplayer2.source","c":"ForwardingTimeline","l":"getLastWindowIndex(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"getLastWindowIndex(boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"getLength()"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"getLength()"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"getLength()"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder","l":"getLength()"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.DefaultShuffleOrder","l":"getLength()"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.UnshuffledShuffleOrder","l":"getLength()"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"InputReaderAdapterV30","l":"getLength()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"getLength()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeShuffleOrder","l":"getLength()"},{"p":"com.google.android.exoplayer2.drm","c":"OfflineLicenseHelper","l":"getLicenseDurationRemainingSec(byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"WidevineUtil","l":"getLicenseDurationRemainingSec(DrmSession)","url":"getLicenseDurationRemainingSec(com.google.android.exoplayer2.drm.DrmSession)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyRequest","l":"getLicenseServerUrl()"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getLine()"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getLineAnchor()"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getLineType()"},{"p":"com.google.android.exoplayer2","c":"BundleListRetriever","l":"getList(IBinder)","url":"getList(android.os.IBinder)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"getLoadControl()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getLocaleLanguageTag(Locale)","url":"getLocaleLanguageTag(java.util.Locale)"},{"p":"com.google.android.exoplayer2.upstream","c":"UdpDataSource","l":"getLocalPort()"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"getLogLevel()"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"getLogStackTraces()"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"getLooper()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"getLooper()"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"getLooper()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"getManifest()"},{"p":"com.google.android.exoplayer2.offline","c":"SegmentDownloader","l":"getManifest(DataSource, DataSpec, boolean)","url":"getManifest(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"getMappedTrackInfo(int)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"getMasterPlaylist()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"getMasterPlaylist()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioCapabilities","l":"getMaxChannelCount()"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"getMaxDecodedFrameSize()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"getMaxInputSize(MediaCodecInfo, Format)","url":"getMaxInputSize(com.google.android.exoplayer2.mediacodec.MediaCodecInfo,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"getMaxParallelDownloads()"},{"p":"com.google.android.exoplayer2","c":"StarRating","l":"getMaxStars()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"getMaxSupportedInstances()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanAudioFormatBitrate()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanBandwidth()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanElapsedTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanInitialAudioFormatBitrate()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanInitialVideoFormatBitrate()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanInitialVideoFormatHeight()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanJoinTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanNonFatalErrorCount()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanPauseBufferCount()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanPauseCount()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanPausedTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanPlayAndWaitTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanPlayTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanRebufferCount()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanRebufferTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanSeekCount()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanSeekTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanSingleRebufferTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanSingleSeekTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanTimeBetweenFatalErrors()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanTimeBetweenNonFatalErrors()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanTimeBetweenRebuffers()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanVideoFormatBitrate()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanVideoFormatHeight()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanWaitTimeMs()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"getMediaClock()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"getMediaClock()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"getMediaClock()"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"getMediaClock()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"getMediaClock()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaClockRenderer","l":"getMediaClock()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"getMediaCodecConfiguration(MediaCodecInfo, Format, MediaCrypto, float)","url":"getMediaCodecConfiguration(com.google.android.exoplayer2.mediacodec.MediaCodecInfo,com.google.android.exoplayer2.Format,android.media.MediaCrypto,float)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"getMediaCodecConfiguration(MediaCodecInfo, Format, MediaCrypto, float)","url":"getMediaCodecConfiguration(com.google.android.exoplayer2.mediacodec.MediaCodecInfo,com.google.android.exoplayer2.Format,android.media.MediaCrypto,float)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"getMediaCodecConfiguration(MediaCodecInfo, Format, MediaCrypto, float)","url":"getMediaCodecConfiguration(com.google.android.exoplayer2.mediacodec.MediaCodecInfo,com.google.android.exoplayer2.Format,android.media.MediaCrypto,float)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"getMediaCrypto()"},{"p":"com.google.android.exoplayer2.drm","c":"ErrorStateDrmSession","l":"getMediaCrypto()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueNavigator","l":"getMediaDescription(Player, int)","url":"getMediaDescription(com.google.android.exoplayer2.Player,int)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink.AudioProcessorChain","l":"getMediaDuration(long)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink.DefaultAudioProcessorChain","l":"getMediaDuration(long)"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"getMediaDuration(long)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getMediaDurationForPlayoutDuration(long, float)","url":"getMediaDurationForPlayoutDuration(long,float)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"getMediaFormat(Format, String, int, float)","url":"getMediaFormat(com.google.android.exoplayer2.Format,java.lang.String,int,float)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"getMediaFormat(Format, String, MediaCodecVideoRenderer.CodecMaxValues, float, boolean, int)","url":"getMediaFormat(com.google.android.exoplayer2.Format,java.lang.String,com.google.android.exoplayer2.video.MediaCodecVideoRenderer.CodecMaxValues,float,boolean,int)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source","c":"LoopingMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"getMediaItemAt(int)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getMediaItemAt(int)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"getMediaItemCount()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getMediaItemCount()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getMediaMetadata()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getMediaMetadata()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getMediaMetadata()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getMediaMetadata()"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"getMediaMimeType(String)","url":"getMediaMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"getMediaPeriodIdForChildMediaPeriodId(ConcatenatingMediaSource.MediaSourceHolder, MediaSource.MediaPeriodId)","url":"getMediaPeriodIdForChildMediaPeriodId(com.google.android.exoplayer2.source.ConcatenatingMediaSource.MediaSourceHolder,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"getMediaPeriodIdForChildMediaPeriodId(Integer, MediaSource.MediaPeriodId)","url":"getMediaPeriodIdForChildMediaPeriodId(java.lang.Integer,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource","l":"getMediaPeriodIdForChildMediaPeriodId(MediaSource.MediaPeriodId, MediaSource.MediaPeriodId)","url":"getMediaPeriodIdForChildMediaPeriodId(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"getMediaPeriodIdForChildMediaPeriodId(T, MediaSource.MediaPeriodId)","url":"getMediaPeriodIdForChildMediaPeriodId(T,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source","c":"LoopingMediaSource","l":"getMediaPeriodIdForChildMediaPeriodId(Void, MediaSource.MediaPeriodId)","url":"getMediaPeriodIdForChildMediaPeriodId(java.lang.Void,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource","l":"getMediaPeriodIdForChildMediaPeriodId(Void, MediaSource.MediaPeriodId)","url":"getMediaPeriodIdForChildMediaPeriodId(java.lang.Void,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"getMediaSource(int)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"getMediaTimeForChildMediaTime(T, long)","url":"getMediaTimeForChildMediaTime(T,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMediaTimeMsAtRealtimeMs(long)"},{"p":"com.google.android.exoplayer2","c":"PlaybackParameters","l":"getMediaTimeUsForPlayoutTimeMs(long)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"DefaultMediaItemConverter","l":"getMetadata(MediaItem)","url":"getMetadata(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.DefaultMediaMetadataProvider","l":"getMetadata(Player)","url":"getMetadata(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.MediaMetadataProvider","l":"getMetadata(Player)","url":"getMetadata(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getMetadataComponent()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getMetadataComponent()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getMetadataComponent()"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"getMetadataCopyWithAppendedEntriesFrom(Metadata)","url":"getMetadataCopyWithAppendedEntriesFrom(com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"getMetrics()"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"getMetrics()"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"getMetrics()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"getMetrics()"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"getMimeTypeFromMp4ObjectType(int)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPayloadFormat","l":"getMimeTypeFromRtpMediaType(String)","url":"getMimeTypeFromRtpMediaType(java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"getMinDurationToRetainAfterDiscardUs()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultLoadErrorHandlingPolicy","l":"getMinimumLoadableRetryCount(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy","l":"getMinimumLoadableRetryCount(int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"getMinRetryCount()"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil","l":"getNalUnitType(byte[], int)","url":"getNalUnitType(byte[],int)"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"getName()"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"getName()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"getName()"},{"p":"com.google.android.exoplayer2.decoder","c":"Decoder","l":"getName()"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Gav1Decoder","l":"getName()"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Libgav1VideoRenderer","l":"getName()"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegAudioRenderer","l":"getName()"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacDecoder","l":"getName()"},{"p":"com.google.android.exoplayer2.ext.flac","c":"LibflacAudioRenderer","l":"getName()"},{"p":"com.google.android.exoplayer2.ext.opus","c":"LibopusAudioRenderer","l":"getName()"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusDecoder","l":"getName()"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"LibvpxVideoRenderer","l":"getName()"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxDecoder","l":"getName()"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataRenderer","l":"getName()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.TestResource","l":"getName()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"getName()"},{"p":"com.google.android.exoplayer2.text","c":"SimpleSubtitleDecoder","l":"getName()"},{"p":"com.google.android.exoplayer2.text","c":"TextRenderer","l":"getName()"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea608Decoder","l":"getName()"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea708Decoder","l":"getName()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"getName()"},{"p":"com.google.android.exoplayer2.video.spherical","c":"CameraMotionRenderer","l":"getName()"},{"p":"com.google.android.exoplayer2.util","c":"NetworkTypeObserver","l":"getNetworkType()"},{"p":"com.google.android.exoplayer2.source","c":"LoadEventInfo","l":"getNewId()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getNextAdIndexToPlay(int, int)","url":"getNextAdIndexToPlay(int,int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"getNextAdIndexToPlay(int)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSource","l":"getNextChunk(long, long, List, ChunkHolder)","url":"getNextChunk(long,long,java.util.List,com.google.android.exoplayer2.source.chunk.ChunkHolder)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"getNextChunk(long, long, List, ChunkHolder)","url":"getNextChunk(long,long,java.util.List,com.google.android.exoplayer2.source.chunk.ChunkHolder)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource","l":"getNextChunk(long, long, List, ChunkHolder)","url":"getNextChunk(long,long,java.util.List,com.google.android.exoplayer2.source.chunk.ChunkHolder)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource","l":"getNextChunk(long, long, List, ChunkHolder)","url":"getNextChunk(long,long,java.util.List,com.google.android.exoplayer2.source.chunk.ChunkHolder)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ContainerMediaChunk","l":"getNextChunkIndex()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaChunk","l":"getNextChunkIndex()"},{"p":"com.google.android.exoplayer2.text","c":"Subtitle","l":"getNextEventTimeIndex(long)"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleOutputBuffer","l":"getNextEventTimeIndex(long)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder","l":"getNextIndex(int)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.DefaultShuffleOrder","l":"getNextIndex(int)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.UnshuffledShuffleOrder","l":"getNextIndex(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeShuffleOrder","l":"getNextIndex(int)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"getNextLoadPositionUs()"},{"p":"com.google.android.exoplayer2.source","c":"CompositeSequenceableLoader","l":"getNextLoadPositionUs()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"getNextLoadPositionUs()"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"getNextLoadPositionUs()"},{"p":"com.google.android.exoplayer2.source","c":"SequenceableLoader","l":"getNextLoadPositionUs()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"getNextLoadPositionUs()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"getNextLoadPositionUs()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"getNextLoadPositionUs()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"getNextLoadPositionUs()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getNextMediaItemIndex()"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getNextPeriodIndex(int, Timeline.Period, Timeline.Window, int, boolean)","url":"getNextPeriodIndex(int,com.google.android.exoplayer2.Timeline.Period,com.google.android.exoplayer2.Timeline.Window,int,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"RepeatModeUtil","l":"getNextRepeatMode(int, int)","url":"getNextRepeatMode(int,int)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashSegmentIndex","l":"getNextSegmentAvailableTimeUs(long, long)","url":"getNextSegmentAvailableTimeUs(long,long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashWrappingSegmentIndex","l":"getNextSegmentAvailableTimeUs(long, long)","url":"getNextSegmentAvailableTimeUs(long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"getNextSegmentAvailableTimeUs(long, long)","url":"getNextSegmentAvailableTimeUs(long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.MultiSegmentBase","l":"getNextSegmentAvailableTimeUs(long, long)","url":"getNextSegmentAvailableTimeUs(long,long)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"getNextWindowIndex()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getNextWindowIndex()"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getNextWindowIndex(int, int, boolean)","url":"getNextWindowIndex(int,int,boolean)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getNextWindowIndex(int, int, boolean)","url":"getNextWindowIndex(int,int,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"ForwardingTimeline","l":"getNextWindowIndex(int, int, boolean)","url":"getNextWindowIndex(int,int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"getNextWindowIndex(int, int, boolean)","url":"getNextWindowIndex(int,int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"HttpDataSourceTestEnv","l":"getNonexistentUrl()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getNonFatalErrorRate()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"getNotFoundUri()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"getNotMetRequirements()"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"getNotMetRequirements(Context)","url":"getNotMetRequirements(android.content.Context)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getNowUnixTimeMs(long)"},{"p":"com.google.android.exoplayer2.util","c":"SntpClient","l":"getNtpHost()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"getOfflineLicenseKeySetId()"},{"p":"com.google.android.exoplayer2.drm","c":"ErrorStateDrmSession","l":"getOfflineLicenseKeySetId()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"getOngoing(Player)","url":"getOngoing(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor","l":"getOutput()"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"getOutput()"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"getOutput()"},{"p":"com.google.android.exoplayer2.ext.gvr","c":"GvrAudioProcessor","l":"getOutput()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunk","l":"getOutput()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"getOutputBuffer(int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"getOutputBuffer(int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"getOutputFormat()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"getOutputFormat()"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegAudioRenderer","l":"getOutputFormat(FfmpegAudioDecoder)","url":"getOutputFormat(com.google.android.exoplayer2.ext.ffmpeg.FfmpegAudioDecoder)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"LibflacAudioRenderer","l":"getOutputFormat(FlacDecoder)","url":"getOutputFormat(com.google.android.exoplayer2.ext.flac.FlacDecoder)"},{"p":"com.google.android.exoplayer2.ext.opus","c":"LibopusAudioRenderer","l":"getOutputFormat(OpusDecoder)","url":"getOutputFormat(com.google.android.exoplayer2.ext.opus.OpusDecoder)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"getOutputFormat(T)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"getOutputStreamOffsetUs()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getOverlayFrameLayout()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getOverlayFrameLayout()"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionView","l":"getOverrides()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"getParameters()"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource","l":"getPath()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getPauseAtEndOfMediaItems()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getPauseAtEndOfMediaItems()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getPauseAtEndOfMediaItems()"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"getPayload()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getPcmEncoding(int)"},{"p":"com.google.android.exoplayer2.audio","c":"WavUtil","l":"getPcmEncodingForType(int, int)","url":"getPcmEncodingForType(int,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getPcmFormat(int, int, int)","url":"getPcmFormat(int,int,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getPcmFrameSize(int, int)","url":"getPcmFrameSize(int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"getPeekPosition()"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"getPeekPosition()"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"getPeekPosition()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"getPeekPosition()"},{"p":"com.google.android.exoplayer2","c":"PercentageRating","l":"getPercent()"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"getPercentDownloaded()"},{"p":"com.google.android.exoplayer2.util","c":"SlidingPercentile","l":"getPercentile(float)"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getPeriod(int, Timeline.Period, boolean)","url":"getPeriod(int,com.google.android.exoplayer2.Timeline.Period,boolean)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getPeriod(int, Timeline.Period, boolean)","url":"getPeriod(int,com.google.android.exoplayer2.Timeline.Period,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"ForwardingTimeline","l":"getPeriod(int, Timeline.Period, boolean)","url":"getPeriod(int,com.google.android.exoplayer2.Timeline.Period,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource.PlaceholderTimeline","l":"getPeriod(int, Timeline.Period, boolean)","url":"getPeriod(int,com.google.android.exoplayer2.Timeline.Period,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"getPeriod(int, Timeline.Period, boolean)","url":"getPeriod(int,com.google.android.exoplayer2.Timeline.Period,boolean)"},{"p":"com.google.android.exoplayer2.source.ads","c":"SinglePeriodAdTimeline","l":"getPeriod(int, Timeline.Period, boolean)","url":"getPeriod(int,com.google.android.exoplayer2.Timeline.Period,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"getPeriod(int, Timeline.Period, boolean)","url":"getPeriod(int,com.google.android.exoplayer2.Timeline.Period,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"NoUidTimeline","l":"getPeriod(int, Timeline.Period, boolean)","url":"getPeriod(int,com.google.android.exoplayer2.Timeline.Period,boolean)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getPeriod(int, Timeline.Period)","url":"getPeriod(int,com.google.android.exoplayer2.Timeline.Period)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"getPeriod(int)"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getPeriodByUid(Object, Timeline.Period)","url":"getPeriodByUid(java.lang.Object,com.google.android.exoplayer2.Timeline.Period)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getPeriodByUid(Object, Timeline.Period)","url":"getPeriodByUid(java.lang.Object,com.google.android.exoplayer2.Timeline.Period)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getPeriodCount()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"getPeriodCount()"},{"p":"com.google.android.exoplayer2.source","c":"ForwardingTimeline","l":"getPeriodCount()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource.PlaceholderTimeline","l":"getPeriodCount()"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"getPeriodCount()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"getPeriodCount()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"getPeriodCount()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"getPeriodDurationMs(int)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"getPeriodDurationUs(int)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getPeriodPosition(Timeline.Window, Timeline.Period, int, long, long)","url":"getPeriodPosition(com.google.android.exoplayer2.Timeline.Window,com.google.android.exoplayer2.Timeline.Period,int,long,long)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getPeriodPosition(Timeline.Window, Timeline.Period, int, long)","url":"getPeriodPosition(com.google.android.exoplayer2.Timeline.Window,com.google.android.exoplayer2.Timeline.Period,int,long)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"getPixelCount()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"getPlaybackError()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getPlaybackError()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getPlaybackLooper()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getPlaybackLooper()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getPlaybackLooper()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getPlaybackParameters()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getPlaybackParameters()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"getPlaybackParameters()"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"getPlaybackParameters()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"getPlaybackParameters()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"getPlaybackParameters()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"getPlaybackParameters()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getPlaybackParameters()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getPlaybackParameters()"},{"p":"com.google.android.exoplayer2.util","c":"MediaClock","l":"getPlaybackParameters()"},{"p":"com.google.android.exoplayer2.util","c":"StandaloneMediaClock","l":"getPlaybackParameters()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getPlaybackSpeed()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"getPlaybackSpeed()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getPlaybackState()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getPlaybackState()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getPlaybackState()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getPlaybackState()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getPlaybackStateAtTime(long)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getPlaybackStateDurationMs(@com.google.android.exoplayer2.analytics.PlaybackStats.PlaybackState int)","url":"getPlaybackStateDurationMs(@com.google.android.exoplayer2.analytics.PlaybackStats.PlaybackStateint)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"getPlaybackStats()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getPlaybackSuppressionReason()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getPlaybackSuppressionReason()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getPlaybackSuppressionReason()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getPlaybackSuppressionReason()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"getPlayer()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getPlayer()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"getPlayer()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getPlayer()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getPlayerError()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getPlayerError()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getPlayerError()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getPlayerError()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getPlayerState()"},{"p":"com.google.android.exoplayer2.util","c":"DebugTextViewHelper","l":"getPlayerStateString()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getPlaylist()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getPlaylistMetadata()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"getPlaylistSnapshot(Uri, boolean)","url":"getPlaylistSnapshot(android.net.Uri,boolean)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"getPlaylistSnapshot(Uri, boolean)","url":"getPlaylistSnapshot(android.net.Uri,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getPlayoutDurationForMediaDuration(long, float)","url":"getPlayoutDurationForMediaDuration(long,float)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getPlayWhenReady()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getPlayWhenReady()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getPlayWhenReady()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getPlayWhenReady()"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"getPosition()"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"getPosition()"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"getPosition()"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisBitArray","l":"getPosition()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"getPosition()"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"InputReaderAdapterV30","l":"getPosition()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"getPosition()"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getPosition()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"getPosition()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"getPosition()"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getPositionAnchor()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"getPositionInFirstPeriodMs()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"getPositionInFirstPeriodUs()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getPositionInWindowMs()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getPositionInWindowUs()"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"getPositionMs()"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"getPositionUs()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"getPositionUs()"},{"p":"com.google.android.exoplayer2.util","c":"MediaClock","l":"getPositionUs()"},{"p":"com.google.android.exoplayer2.util","c":"StandaloneMediaClock","l":"getPositionUs()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSource","l":"getPreferredQueueSize(long, List)","url":"getPreferredQueueSize(long,java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"getPreferredQueueSize(long, List)","url":"getPreferredQueueSize(long,java.util.List)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource","l":"getPreferredQueueSize(long, List)","url":"getPreferredQueueSize(long,java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource","l":"getPreferredQueueSize(long, List)","url":"getPreferredQueueSize(long,java.util.List)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"getPreferredUpdateDelay()"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar","l":"getPreferredUpdateDelay()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"getPreparePositionOverrideUs()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"getPreparePositionUs()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase","l":"getPresentationTimeOffsetUs()"},{"p":"com.google.android.exoplayer2.audio","c":"OpusUtil","l":"getPreSkipSamples(List)","url":"getPreSkipSamples(java.util.List)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder","l":"getPreviousIndex(int)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.DefaultShuffleOrder","l":"getPreviousIndex(int)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.UnshuffledShuffleOrder","l":"getPreviousIndex(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeShuffleOrder","l":"getPreviousIndex(int)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getPreviousMediaItemIndex()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"getPreviousWindowIndex()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getPreviousWindowIndex()"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getPreviousWindowIndex(int, int, boolean)","url":"getPreviousWindowIndex(int,int,boolean)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getPreviousWindowIndex(int, int, boolean)","url":"getPreviousWindowIndex(int,int,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"ForwardingTimeline","l":"getPreviousWindowIndex(int, int, boolean)","url":"getPreviousWindowIndex(int,int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"getPreviousWindowIndex(int, int, boolean)","url":"getPreviousWindowIndex(int,int,boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"getProfileLevels()"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer","l":"getProgress(ProgressHolder)","url":"getProgress(com.google.android.exoplayer2.transformer.ProgressHolder)"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"getPropertyByteArray(String)","url":"getPropertyByteArray(java.lang.String)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"getPropertyByteArray(String)","url":"getPropertyByteArray(java.lang.String)"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"getPropertyByteArray(String)","url":"getPropertyByteArray(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"getPropertyByteArray(String)","url":"getPropertyByteArray(java.lang.String)"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"getPropertyString(String)","url":"getPropertyString(java.lang.String)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"getPropertyString(String)","url":"getPropertyString(java.lang.String)"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"getPropertyString(String)","url":"getPropertyString(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"getPropertyString(String)","url":"getPropertyString(java.lang.String)"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"getProvisionRequest()"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"getProvisionRequest()"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"getProvisionRequest()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"getProvisionRequest()"},{"p":"com.google.android.exoplayer2.database","c":"DatabaseProvider","l":"getReadableDatabase()"},{"p":"com.google.android.exoplayer2.database","c":"DefaultDatabaseProvider","l":"getReadableDatabase()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"getReadIndex()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"getReadingPositionUs()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"getReadingPositionUs()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"getReadingPositionUs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getRebufferRate()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getRebufferTimeRatio()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm.LicenseServer","l":"getReceivedSchemeDatas()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadata","l":"getRedirectedUri(ContentMetadata)","url":"getRedirectedUri(com.google.android.exoplayer2.upstream.cache.ContentMetadata)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"getReferenceCount()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CachedRegionTracker","l":"getRegionEndTimeMs(long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadataMutations","l":"getRemovedValues()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"getRendererCapabilities(RenderersFactory)","url":"getRendererCapabilities(com.google.android.exoplayer2.RenderersFactory)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getRendererCount()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getRendererCount()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getRendererCount()"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"getRendererCount()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"getRendererDisabled(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"getRendererException()"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"getRendererName(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"getRenderers()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"getRenderersFactory()"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"getRendererSupport(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getRendererType(int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getRendererType(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getRendererType(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"getRendererType(int)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getRepeatMode()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getRepeatMode()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getRepeatMode()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getRepeatMode()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getRepeatMode()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"getRepeatToggleModes()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"getRepeatToggleModes()"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher","l":"getRequestPath(RecordedRequest)","url":"getRequestPath(okhttp3.mockwebserver.RecordedRequest)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyRequest","l":"getRequestType()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"getRequirements()"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"getRequirements()"},{"p":"com.google.android.exoplayer2.scheduler","c":"RequirementsWatcher","l":"getRequirements()"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout","l":"getResizeMode()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getResizeMode()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getResizeMode()"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"getResponseCode()"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"getResponseCode()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"getResponseCode()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource","l":"getResponseCode()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"getResponseHeaders_isEmptyWhileNotOpen()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"getResponseHeaders_resourceNotFound_isEmptyWhileNotOpen()"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSource","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSource","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.upstream","c":"PriorityDataSource","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.upstream","c":"ResolvingDataSource","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.upstream","c":"StatsDataSource","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.upstream","c":"TeeDataSource","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesCipherDataSource","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"getResult()"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy","l":"getRetryDelayMsFor(int, long, IOException, int)","url":"getRetryDelayMsFor(int,long,java.io.IOException,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultLoadErrorHandlingPolicy","l":"getRetryDelayMsFor(LoadErrorHandlingPolicy.LoadErrorInfo)","url":"getRetryDelayMsFor(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.LoadErrorInfo)"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy","l":"getRetryDelayMsFor(LoadErrorHandlingPolicy.LoadErrorInfo)","url":"getRetryDelayMsFor(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.LoadErrorInfo)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"getRewindIncrementMs()"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"getRubyPosition()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource.AdLoadException","l":"getRuntimeExceptionForUnexpected()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"getSampleCount()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"getSampleCryptoData(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"getSampleData(int)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"getSampleDescriptionEncryptionBox(int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsReader","l":"getSampleDurationUs()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"getSampleFlags(int)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BundledChunkExtractor","l":"getSampleFormats()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkExtractor","l":"getSampleFormats()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaParserChunkExtractor","l":"getSampleFormats()"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"getSampleFormats()"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"getSampleNumber(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"getSampleTimesUs()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"getSampleTimeUs(int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"getScheduler()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"getSchemeUuid()"},{"p":"com.google.android.exoplayer2.drm","c":"ErrorStateDrmSession","l":"getSchemeUuid()"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"getSeekMap()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getSeekParameters()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getSeekParameters()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getSeekParameters()"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.BinarySearchSeekMap","l":"getSeekPoints(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"ChunkIndex","l":"getSeekPoints(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"ConstantBitrateSeekMap","l":"getSeekPoints(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacSeekTableSeekMap","l":"getSeekPoints(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"IndexSeekMap","l":"getSeekPoints(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap","l":"getSeekPoints(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap.Unseekable","l":"getSeekPoints(long)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"getSeekPoints(long)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"getSeekPoints(long)"},{"p":"com.google.android.exoplayer2.audio","c":"OpusUtil","l":"getSeekPreRollSamples(List)","url":"getSeekPreRollSamples(java.util.List)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getSeekTimeRatio()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationHolder","l":"getSegmentCount()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashSegmentIndex","l":"getSegmentCount(long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashWrappingSegmentIndex","l":"getSegmentCount(long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"getSegmentCount(long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.MultiSegmentBase","l":"getSegmentCount(long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SegmentList","l":"getSegmentCount(long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SegmentTemplate","l":"getSegmentCount(long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.MultiSegmentBase","l":"getSegmentDurationUs(long, long)","url":"getSegmentDurationUs(long,long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationHolder","l":"getSegmentEndTimeUs(long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashSegmentIndex","l":"getSegmentNum(long, long)","url":"getSegmentNum(long,long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashWrappingSegmentIndex","l":"getSegmentNum(long, long)","url":"getSegmentNum(long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"getSegmentNum(long, long)","url":"getSegmentNum(long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.MultiSegmentBase","l":"getSegmentNum(long, long)","url":"getSegmentNum(long,long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationHolder","l":"getSegmentNum(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData","l":"getSegments()"},{"p":"com.google.android.exoplayer2.source.dash.offline","c":"DashDownloader","l":"getSegments(DataSource, DashManifest, boolean)","url":"getSegments(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.source.dash.manifest.DashManifest,boolean)"},{"p":"com.google.android.exoplayer2.source.hls.offline","c":"HlsDownloader","l":"getSegments(DataSource, HlsPlaylist, boolean)","url":"getSegments(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.source.hls.playlist.HlsPlaylist,boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"SegmentDownloader","l":"getSegments(DataSource, M, boolean)","url":"getSegments(com.google.android.exoplayer2.upstream.DataSource,M,boolean)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.offline","c":"SsDownloader","l":"getSegments(DataSource, SsManifest, boolean)","url":"getSegments(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest,boolean)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationHolder","l":"getSegmentStartTimeUs(long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.MultiSegmentBase","l":"getSegmentTimeUs(long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashSegmentIndex","l":"getSegmentUrl(long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashWrappingSegmentIndex","l":"getSegmentUrl(long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationHolder","l":"getSegmentUrl(long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"getSegmentUrl(long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.MultiSegmentBase","l":"getSegmentUrl(Representation, long)","url":"getSegmentUrl(com.google.android.exoplayer2.source.dash.manifest.Representation,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SegmentList","l":"getSegmentUrl(Representation, long)","url":"getSegmentUrl(com.google.android.exoplayer2.source.dash.manifest.Representation,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SegmentTemplate","l":"getSegmentUrl(Representation, long)","url":"getSegmentUrl(com.google.android.exoplayer2.source.dash.manifest.Representation,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"getSelectedFormat()"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"getSelectedFormat()"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"getSelectedFormat()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"getSelectedIndex()"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"getSelectedIndex()"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"getSelectedIndex()"},{"p":"com.google.android.exoplayer2.trackselection","c":"FixedTrackSelection","l":"getSelectedIndex()"},{"p":"com.google.android.exoplayer2.trackselection","c":"RandomTrackSelection","l":"getSelectedIndex()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"getSelectedIndexInTrackGroup()"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"getSelectedIndexInTrackGroup()"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"getSelectedIndexInTrackGroup()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"getSelectionData()"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"getSelectionData()"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"getSelectionData()"},{"p":"com.google.android.exoplayer2.trackselection","c":"FixedTrackSelection","l":"getSelectionData()"},{"p":"com.google.android.exoplayer2.trackselection","c":"RandomTrackSelection","l":"getSelectionData()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"getSelectionOverride(int, TrackGroupArray)","url":"getSelectionOverride(int,com.google.android.exoplayer2.source.TrackGroupArray)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"getSelectionReason()"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"getSelectionReason()"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"getSelectionReason()"},{"p":"com.google.android.exoplayer2.trackselection","c":"FixedTrackSelection","l":"getSelectionReason()"},{"p":"com.google.android.exoplayer2.trackselection","c":"RandomTrackSelection","l":"getSelectionReason()"},{"p":"com.google.android.exoplayer2.testutil","c":"HttpDataSourceTestEnv","l":"getServedResources()"},{"p":"com.google.android.exoplayer2.analytics","c":"DefaultPlaybackSessionManager","l":"getSessionForMediaPeriodId(Timeline, MediaSource.MediaPeriodId)","url":"getSessionForMediaPeriodId(com.google.android.exoplayer2.Timeline,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackSessionManager","l":"getSessionForMediaPeriodId(Timeline, MediaSource.MediaPeriodId)","url":"getSessionForMediaPeriodId(com.google.android.exoplayer2.Timeline,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"getShowShuffleButton()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"getShowShuffleButton()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"getShowSubtitleButton()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"getShowTimeoutMs()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"getShowTimeoutMs()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"getShowVrButton()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"getShowVrButton()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getShuffleMode()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getShuffleModeEnabled()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getShuffleModeEnabled()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getShuffleModeEnabled()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getShuffleModeEnabled()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"getSingletonInstance(Context)","url":"getSingletonInstance(android.content.Context)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"getSinkFormatSupport(Format)","url":"getSinkFormatSupport(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"getSize()"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getSize()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"getSkipCount(long, boolean)","url":"getSkipCount(long,boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"getSkippedFrames()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink.AudioProcessorChain","l":"getSkippedOutputFrameCount()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink.DefaultAudioProcessorChain","l":"getSkippedOutputFrameCount()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioComponent","l":"getSkipSilenceEnabled()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getSkipSilenceEnabled()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"getSkipSilenceEnabled()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"getSkipSilenceEnabled()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"getSkipSilenceEnabled()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.RequestProperties","l":"getSnapshot()"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"getSourceException()"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"getSpecificityScore(String, String, Set, String)","url":"getSpecificityScore(java.lang.String,java.lang.String,java.util.Set,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"StarRating","l":"getStarRating()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveDataSet","l":"getStartTime(int)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"getStartTimeUs(int)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"getState()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"getState()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"getState()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"getState()"},{"p":"com.google.android.exoplayer2.drm","c":"ErrorStateDrmSession","l":"getState()"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyStatus","l":"getStatusCode()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"getStream()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"getStream()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"getStream()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"getStreamFormats()"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"getStreamKeys(List)","url":"getStreamKeys(java.util.List)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"getStreamKeys(List)","url":"getStreamKeys(java.util.List)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacDecoder","l":"getStreamMetadata()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getStreamTypeForAudioUsage(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"getString(Context, String)","url":"getString(android.content.Context,java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"getStringForHttpMethod(int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getStringForTime(StringBuilder, Formatter, long)","url":"getStringForTime(java.lang.StringBuilder,java.util.Formatter,long)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"getStyle()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"getSubFrame(int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterTocFrame","l":"getSubFrame(int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"getSubFrameCount()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterTocFrame","l":"getSubFrameCount()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getSubtitleView()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getSubtitleView()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.PlaybackPreparer","l":"getSupportedPrepareActions()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.QueueNavigator","l":"getSupportedQueueNavigatorActions(Player)","url":"getSupportedQueueNavigatorActions(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueNavigator","l":"getSupportedQueueNavigatorActions(Player)","url":"getSupportedQueueNavigatorActions(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ext.workmanager","c":"WorkManagerScheduler","l":"getSupportedRequirements(Requirements)","url":"getSupportedRequirements(com.google.android.exoplayer2.scheduler.Requirements)"},{"p":"com.google.android.exoplayer2.scheduler","c":"PlatformScheduler","l":"getSupportedRequirements(Requirements)","url":"getSupportedRequirements(com.google.android.exoplayer2.scheduler.Requirements)"},{"p":"com.google.android.exoplayer2.scheduler","c":"Scheduler","l":"getSupportedRequirements(Requirements)","url":"getSupportedRequirements(com.google.android.exoplayer2.scheduler.Requirements)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"getSupportedTypes()"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceFactory","l":"getSupportedTypes()"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"getSupportedTypes()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"getSupportedTypes()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"getSupportedTypes()"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.Factory","l":"getSupportedTypes()"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"getSupportedTypes()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"getSurface()"},{"p":"com.google.android.exoplayer2.util","c":"EGLSurfaceTexture","l":"getSurfaceTexture()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getSystemLanguageCodes()"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource","l":"getTag()"},{"p":"com.google.android.exoplayer2.source","c":"LoopingMediaSource","l":"getTag()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource","l":"getTag()"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"getTag()"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"getTag()"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource","l":"getTag()"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource","l":"getTag()"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource","l":"getTag()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource","l":"getTag()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource","l":"getTag()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource","l":"getTag()"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource","l":"getTag()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"getTag()"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"getTarget()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock.HandlerMessage","l":"getTarget()"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper.Message","l":"getTarget()"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl","l":"getTargetLiveOffsetUs()"},{"p":"com.google.android.exoplayer2","c":"LivePlaybackSpeedControl","l":"getTargetLiveOffsetUs()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"getTestResources()"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getText()"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getTextAlignment()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getTextComponent()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getTextComponent()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getTextComponent()"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"getTextMediaMimeType(String)","url":"getTextMediaMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getTextSize()"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getTextSizeType()"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"getThrowableString(Throwable)","url":"getThrowableString(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"getTimeline()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource","l":"getTimeline()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"getTimeline()"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getTimelineByChildIndex(int)"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"getTimestampOffsetUs()"},{"p":"com.google.android.exoplayer2.upstream","c":"BandwidthMeter","l":"getTimeToFirstByteEstimateUs()"},{"p":"com.google.android.exoplayer2.upstream","c":"TimeToFirstByteEstimator","l":"getTimeToFirstByteEstimateUs()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashSegmentIndex","l":"getTimeUs(long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashWrappingSegmentIndex","l":"getTimeUs(long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"getTimeUs(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"ConstantBitrateSeekMap","l":"getTimeUsAtPosition(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"DecoderCountersUtil","l":"getTotalBufferCount(DecoderCounters)","url":"getTotalBufferCount(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getTotalBufferedDuration()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getTotalBufferedDuration()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getTotalBufferedDuration()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getTotalBufferedDuration()"},{"p":"com.google.android.exoplayer2.upstream","c":"Allocator","l":"getTotalBytesAllocated()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultAllocator","l":"getTotalBytesAllocated()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getTotalElapsedTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getTotalJoinTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getTotalPausedTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getTotalPlayAndWaitTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getTotalPlayTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getTotalRebufferTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getTotalSeekTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getTotalWaitTimeMs()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"getTrackGroup()"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"getTrackGroup()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelection","l":"getTrackGroup()"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"getTrackGroups()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"getTrackGroups()"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"getTrackGroups()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"getTrackGroups()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"getTrackGroups()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"getTrackGroups()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"getTrackGroups(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"getTrackGroups(int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.TrackIdGenerator","l":"getTrackId()"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTrackNameProvider","l":"getTrackName(Format)","url":"getTrackName(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackNameProvider","l":"getTrackName(Format)","url":"getTrackName(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ContainerMediaChunk","l":"getTrackOutputProvider(BaseMediaChunkOutput)","url":"getTrackOutputProvider(com.google.android.exoplayer2.source.chunk.BaseMediaChunkOutput)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"getTrackSelections(int, int)","url":"getTrackSelections(int,int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getTrackSelector()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getTrackSelector()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getTrackSelector()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"getTrackSelector()"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"getTrackSupport(int, int, int)","url":"getTrackSupport(int,int,int)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"getTrackType()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"getTrackType()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"getTrackType()"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"getTrackType()"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"getTrackType(String)","url":"getTrackType(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"getTrackTypeOfCodec(String)","url":"getTrackTypeOfCodec(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getTrackTypeString(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"BandwidthMeter","l":"getTransferListener()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"getTransferListener()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"getTransferListenerDataSource()"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"getTunnelingSupport(int)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"getType()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"getType()"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"getType()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelection","l":"getType()"},{"p":"com.google.android.exoplayer2.audio","c":"WavUtil","l":"getTypeForPcmEncoding(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"getTypeSupport(int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"getUid()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"getUid()"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getUidOfPeriod(int)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getUidOfPeriod(int)"},{"p":"com.google.android.exoplayer2.source","c":"ForwardingTimeline","l":"getUidOfPeriod(int)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource.PlaceholderTimeline","l":"getUidOfPeriod(int)"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"getUidOfPeriod(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"getUidOfPeriod(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"getUnexpectedException()"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil","l":"getUniforms(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"getUnmappedTrackGroups()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"getUpstreamFormat()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"getUpstreamPriorityTaskManager()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"getUri_resourceNotFound_returnsNullIfNotOpened()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"getUri_returnsNonNullValueOnlyWhileOpen()"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.ext.rtmp","c":"RtmpDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"getUri()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.TestResource","l":"getUri()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"AssetDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"ByteArrayDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"ContentDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSchemeDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"DummyDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"PriorityDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"RawResourceDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"ResolvingDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"StatsDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"TeeDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"UdpDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesCipherDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveDataSet","l":"getUri(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getUseArtwork()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getUseArtwork()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getUseController()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getUseController()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"getUseLazyPreparation()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getUserAgent(Context, String)","url":"getUserAgent(android.content.Context,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getUtf8Bytes(String)","url":"getUtf8Bytes(java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegLibrary","l":"getVersion()"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusLibrary","l":"getVersion()"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxLibrary","l":"getVersion()"},{"p":"com.google.android.exoplayer2.database","c":"VersionTable","l":"getVersion(SQLiteDatabase, int, String)","url":"getVersion(android.database.sqlite.SQLiteDatabase,int,java.lang.String)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getVerticalType()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getVideoComponent()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getVideoComponent()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getVideoComponent()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getVideoDecoderCounters()"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderGLSurfaceView","l":"getVideoDecoderOutputBufferRenderer()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getVideoFormat()"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView","l":"getVideoFrameMetadataListener()"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"getVideoMediaMimeType(String)","url":"getVideoMediaMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"getVideoScalingMode()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getVideoScalingMode()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"getVideoSize()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getVideoSize()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getVideoSize()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getVideoSize()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getVideoSize()"},{"p":"com.google.android.exoplayer2.util","c":"DebugTextViewHelper","l":"getVideoString()"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView","l":"getVideoSurface()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getVideoSurfaceView()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getVideoSurfaceView()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioComponent","l":"getVolume()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getVolume()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getVolume()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getVolume()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getVolume()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getWaitTimeRatio()"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getWindow(int, Timeline.Window, boolean)","url":"getWindow(int,com.google.android.exoplayer2.Timeline.Window,boolean)"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getWindow(int, Timeline.Window, long)","url":"getWindow(int,com.google.android.exoplayer2.Timeline.Window,long)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getWindow(int, Timeline.Window, long)","url":"getWindow(int,com.google.android.exoplayer2.Timeline.Window,long)"},{"p":"com.google.android.exoplayer2.source","c":"ForwardingTimeline","l":"getWindow(int, Timeline.Window, long)","url":"getWindow(int,com.google.android.exoplayer2.Timeline.Window,long)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource.PlaceholderTimeline","l":"getWindow(int, Timeline.Window, long)","url":"getWindow(int,com.google.android.exoplayer2.Timeline.Window,long)"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"getWindow(int, Timeline.Window, long)","url":"getWindow(int,com.google.android.exoplayer2.Timeline.Window,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource.InitialTimeline","l":"getWindow(int, Timeline.Window, long)","url":"getWindow(int,com.google.android.exoplayer2.Timeline.Window,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"getWindow(int, Timeline.Window, long)","url":"getWindow(int,com.google.android.exoplayer2.Timeline.Window,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"NoUidTimeline","l":"getWindow(int, Timeline.Window, long)","url":"getWindow(int,com.google.android.exoplayer2.Timeline.Window,long)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getWindow(int, Timeline.Window)","url":"getWindow(int,com.google.android.exoplayer2.Timeline.Window)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getWindowColor()"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getWindowCount()"},{"p":"com.google.android.exoplayer2.source","c":"ForwardingTimeline","l":"getWindowCount()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource.PlaceholderTimeline","l":"getWindowCount()"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"getWindowCount()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"getWindowCount()"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"getWindowIndex()"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"getWindowIndexForChildWindowIndex(ConcatenatingMediaSource.MediaSourceHolder, int)","url":"getWindowIndexForChildWindowIndex(com.google.android.exoplayer2.source.ConcatenatingMediaSource.MediaSourceHolder,int)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"getWindowIndexForChildWindowIndex(T, int)","url":"getWindowIndexForChildWindowIndex(T,int)"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata.Entry","l":"getWrappedMetadataBytes()"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"getWrappedMetadataBytes()"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata.Entry","l":"getWrappedMetadataFormat()"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"getWrappedMetadataFormat()"},{"p":"com.google.android.exoplayer2.database","c":"DatabaseProvider","l":"getWritableDatabase()"},{"p":"com.google.android.exoplayer2.database","c":"DefaultDatabaseProvider","l":"getWritableDatabase()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"getWriteIndex()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunkOutput","l":"getWriteIndices()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayerLibraryInfo","l":"GL_ASSERTIONS_ENABLED"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"group"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection.Definition","l":"group"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"GROUP_INDEX_AUDIO"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"GROUP_INDEX_SUBTITLE"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"GROUP_INDEX_VARIANT"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry","l":"groupId"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Rendition","l":"groupId"},{"p":"com.google.android.exoplayer2.offline","c":"StreamKey","l":"groupIndex"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.SelectionOverride","l":"groupIndex"},{"p":"com.google.android.exoplayer2.ext.gvr","c":"GvrAudioProcessor","l":"GvrAudioProcessor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource","l":"GZIP_SUPPORT_DISABLED"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource","l":"GZIP_SUPPORT_ENABLED"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource","l":"GZIP_SUPPORT_FORCED"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"gzip(byte[])"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H262Reader","l":"H262Reader()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H263Reader","l":"H263Reader()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H264Reader","l":"H264Reader(SeiReader, boolean, boolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.ts.SeiReader,boolean,boolean)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H265Reader","l":"H265Reader(SeiReader)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.ts.SeiReader)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"handleBlockAddIDExtraData(MatroskaExtractor.Track, ExtractorInput, int)","url":"handleBlockAddIDExtraData(com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor.Track,com.google.android.exoplayer2.extractor.ExtractorInput,int)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"handleBlockAdditionalData(MatroskaExtractor.Track, int, ExtractorInput, int)","url":"handleBlockAdditionalData(com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor.Track,int,com.google.android.exoplayer2.extractor.ExtractorInput,int)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"handleBuffer(ByteBuffer, long, int)","url":"handleBuffer(java.nio.ByteBuffer,long,int)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"handleBuffer(ByteBuffer, long, int)","url":"handleBuffer(java.nio.ByteBuffer,long,int)"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"handleBuffer(ByteBuffer, long, int)","url":"handleBuffer(java.nio.ByteBuffer,long,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"CapturingAudioSink","l":"handleBuffer(ByteBuffer, long, int)","url":"handleBuffer(java.nio.ByteBuffer,long,int)"},{"p":"com.google.android.exoplayer2.audio","c":"TeeAudioProcessor.AudioBufferSink","l":"handleBuffer(ByteBuffer)","url":"handleBuffer(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.audio","c":"TeeAudioProcessor.WavFileAudioBufferSink","l":"handleBuffer(ByteBuffer)","url":"handleBuffer(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"handleDiscontinuity()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"handleDiscontinuity()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"handleDiscontinuity()"},{"p":"com.google.android.exoplayer2.testutil","c":"CapturingAudioSink","l":"handleDiscontinuity()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"handleInputBufferSupplementalData(DecoderInputBuffer)","url":"handleInputBufferSupplementalData(com.google.android.exoplayer2.decoder.DecoderInputBuffer)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"handleInputBufferSupplementalData(DecoderInputBuffer)","url":"handleInputBufferSupplementalData(com.google.android.exoplayer2.decoder.DecoderInputBuffer)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"handleMessage(int, Object)","url":"handleMessage(int,java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"handleMessage(int, Object)","url":"handleMessage(int,java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage.Target","l":"handleMessage(int, Object)","url":"handleMessage(int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"handleMessage(int, Object)","url":"handleMessage(int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"handleMessage(int, Object)","url":"handleMessage(int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.PlayerTarget","l":"handleMessage(int, Object)","url":"handleMessage(int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeVideoRenderer","l":"handleMessage(int, Object)","url":"handleMessage(int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"handleMessage(int, Object)","url":"handleMessage(int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"handleMessage(int, Object)","url":"handleMessage(int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.video.spherical","c":"CameraMotionRenderer","l":"handleMessage(int, Object)","url":"handleMessage(int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataRenderer","l":"handleMessage(Message)","url":"handleMessage(android.os.Message)"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler","l":"handleMessage(Message)","url":"handleMessage(android.os.Message)"},{"p":"com.google.android.exoplayer2.text","c":"TextRenderer","l":"handleMessage(Message)","url":"handleMessage(android.os.Message)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.PlayerTarget","l":"handleMessage(SimpleExoPlayer, int, Object)","url":"handleMessage(com.google.android.exoplayer2.SimpleExoPlayer,int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"handlePendingSeek(ExtractorInput, PositionHolder)","url":"handlePendingSeek(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"handlePrepareComplete(AdsMediaSource, int, int)","url":"handlePrepareComplete(com.google.android.exoplayer2.source.ads.AdsMediaSource,int,int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsLoader","l":"handlePrepareComplete(AdsMediaSource, int, int)","url":"handlePrepareComplete(com.google.android.exoplayer2.source.ads.AdsMediaSource,int,int)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"handlePrepareError(AdsMediaSource, int, int, IOException)","url":"handlePrepareError(com.google.android.exoplayer2.source.ads.AdsMediaSource,int,int,java.io.IOException)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsLoader","l":"handlePrepareError(AdsMediaSource, int, int, IOException)","url":"handlePrepareError(com.google.android.exoplayer2.source.ads.AdsMediaSource,int,int,java.io.IOException)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock.HandlerMessage","l":"HandlerMessage(long, FakeClock.ClockHandler, int, int, int, Object, Runnable)","url":"%3Cinit%3E(long,com.google.android.exoplayer2.testutil.FakeClock.ClockHandler,int,int,int,java.lang.Object,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"hardwareAccelerated"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasAbsoluteSizeSpanBetween(int, int)","url":"hasAbsoluteSizeSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasAlignmentSpanBetween(int, int)","url":"hasAlignmentSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"hasBackgroundColor()"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasBackgroundColorSpanBetween(int, int)","url":"hasBackgroundColorSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasBoldItalicSpanBetween(int, int)","url":"hasBoldItalicSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasBoldSpanBetween(int, int)","url":"hasBoldSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.CaptionCallback","l":"hasCaptions(Player)","url":"hasCaptions(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"hasData()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"hasDiscontinuitySequence"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"hasEndTag"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"hasFatalError()"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"hasFontColor()"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasForegroundColorSpanBetween(int, int)","url":"hasForegroundColorSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"GaplessInfoHolder","l":"hasGaplessInfo()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.SegmentBase","l":"hasGapTag"},{"p":"com.google.android.exoplayer2","c":"Format","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"HeartRating","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.AdsConfiguration","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.ClippingProperties","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.DrmConfiguration","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.LiveConfiguration","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.PlaybackProperties","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Subtitle","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"PercentageRating","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"PlaybackParameters","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"Player.Commands","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"RendererConfiguration","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"SeekParameters","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"StarRating","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"ThumbRating","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"hashCode()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"hashCode()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndException","l":"hashCode()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndFormat","l":"hashCode()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndPlaybackState","l":"hashCode()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes","l":"hashCode()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioCapabilities","l":"hashCode()"},{"p":"com.google.android.exoplayer2.audio","c":"AuxEffectInfo","l":"hashCode()"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"hashCode()"},{"p":"com.google.android.exoplayer2.device","c":"DeviceInfo","l":"hashCode()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"hashCode()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"hashCode()"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap.SeekPoints","l":"hashCode()"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekPoint","l":"hashCode()"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput.CryptoData","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"VorbisComment","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyInfo","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ApicFrame","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"BinaryFrame","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterTocFrame","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"CommentFrame","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"GeobFrame","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"InternalFrame","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"MlltFrame","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"PrivFrame","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"TextInformationFrame","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"UrlLinkFrame","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MdtaMetadataEntry","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MotionPhotoMetadata","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData.Segment","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SmtaMetadataEntry","l":"hashCode()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"hashCode()"},{"p":"com.google.android.exoplayer2.offline","c":"StreamKey","l":"hashCode()"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroup","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroupArray","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Descriptor","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ProgramInformation","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"RangedUri","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SegmentTimelineElement","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry.VariantInfo","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPayloadFormat","l":"hashCode()"},{"p":"com.google.android.exoplayer2.testutil","c":"DumpableFormat","l":"hashCode()"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection.AdaptationCheckpoint","l":"hashCode()"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"hashCode()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"hashCode()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.SelectionOverride","l":"hashCode()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionArray","l":"hashCode()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"hashCode()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"DefaultContentMetadata","l":"hashCode()"},{"p":"com.google.android.exoplayer2.util","c":"ExoFlags","l":"hashCode()"},{"p":"com.google.android.exoplayer2.video","c":"ColorInfo","l":"hashCode()"},{"p":"com.google.android.exoplayer2.video","c":"VideoSize","l":"hashCode()"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasHorizontalTextInVerticalContextSpanBetween(int, int)","url":"hasHorizontalTextInVerticalContextSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylist","l":"hasIndependentSegments"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasItalicSpanBetween(int, int)","url":"hasItalicSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"hasMessages(int)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"hasNext()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"hasNext()"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoAbsoluteSizeSpanBetween(int, int)","url":"hasNoAbsoluteSizeSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoAlignmentSpanBetween(int, int)","url":"hasNoAlignmentSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoBackgroundColorSpanBetween(int, int)","url":"hasNoBackgroundColorSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoForegroundColorSpanBetween(int, int)","url":"hasNoForegroundColorSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoHorizontalTextInVerticalContextSpanBetween(int, int)","url":"hasNoHorizontalTextInVerticalContextSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoRelativeSizeSpanBetween(int, int)","url":"hasNoRelativeSizeSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoRubySpanBetween(int, int)","url":"hasNoRubySpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoSpans()"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoStrikethroughSpanBetween(int, int)","url":"hasNoStrikethroughSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoStyleSpanBetween(int, int)","url":"hasNoStyleSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoTextEmphasisSpanBetween(int, int)","url":"hasNoTextEmphasisSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoTypefaceSpanBetween(int, int)","url":"hasNoTypefaceSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoUnderlineSpanBetween(int, int)","url":"hasNoUnderlineSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"hasPendingData()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"hasPendingData()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"hasPendingData()"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"hasPendingOutput()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"hasPlayedAdGroup(int)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"hasPositiveStartOffset"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"hasPrevious()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"hasPrevious()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"hasProgramDateTime"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"hasReadStreamToEnd()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"hasReadStreamToEnd()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"hasReadStreamToEnd()"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasRelativeSizeSpanBetween(int, int)","url":"hasRelativeSizeSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasRubySpanBetween(int, int)","url":"hasRubySpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"hasSelectionOverride(int, TrackGroupArray)","url":"hasSelectionOverride(int,com.google.android.exoplayer2.source.TrackGroupArray)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasStrikethroughSpanBetween(int, int)","url":"hasStrikethroughSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.decoder","c":"Buffer","l":"hasSupplementalData()"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasTextEmphasisSpanBetween(int, int)","url":"hasTextEmphasisSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionUtil","l":"hasTrackOfType(TrackSelectionArray, int)","url":"hasTrackOfType(com.google.android.exoplayer2.trackselection.TrackSelectionArray,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasTypefaceSpanBetween(int, int)","url":"hasTypefaceSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasUnderlineSpanBetween(int, int)","url":"hasUnderlineSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"hasUnplayedAds()"},{"p":"com.google.android.exoplayer2.video","c":"ColorInfo","l":"hdrStaticInfo"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util","l":"HEADER_SIZE_FOR_PARSER"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil.Header","l":"Header()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.InvalidResponseCodeException","l":"headerFields"},{"p":"com.google.android.exoplayer2","c":"HeartRating","l":"HeartRating()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"HeartRating","l":"HeartRating(boolean)","url":"%3Cinit%3E(boolean)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"height"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"height"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"height"},{"p":"com.google.android.exoplayer2.video","c":"AvcConfig","l":"height"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer.CodecMaxValues","l":"height"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"height"},{"p":"com.google.android.exoplayer2.video","c":"VideoSize","l":"height"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"hide()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"hide()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"hideController()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"hideController()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"hideImmediately()"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"hideScrubber(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"hideScrubber(long)"},{"p":"com.google.android.exoplayer2.source.hls.offline","c":"HlsDownloader","l":"HlsDownloader(MediaItem, CacheDataSource.Factory, Executor)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.source.hls.offline","c":"HlsDownloader","l":"HlsDownloader(MediaItem, CacheDataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.hls.offline","c":"HlsDownloader","l":"HlsDownloader(MediaItem, ParsingLoadable.Parser, CacheDataSource.Factory, Executor)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.upstream.ParsingLoadable.Parser,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.source.hls.offline","c":"HlsDownloader","l":"HlsDownloader(Uri, List, CacheDataSource.Factory, Executor)","url":"%3Cinit%3E(android.net.Uri,java.util.List,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.source.hls.offline","c":"HlsDownloader","l":"HlsDownloader(Uri, List, CacheDataSource.Factory)","url":"%3Cinit%3E(android.net.Uri,java.util.List,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"HlsMasterPlaylist(String, List, List, List, List, List, List, Format, List, boolean, Map, List)","url":"%3Cinit%3E(java.lang.String,java.util.List,java.util.List,java.util.List,java.util.List,java.util.List,java.util.List,com.google.android.exoplayer2.Format,java.util.List,boolean,java.util.Map,java.util.List)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"HlsMediaPeriod(HlsExtractorFactory, HlsPlaylistTracker, HlsDataSourceFactory, TransferListener, DrmSessionManager, DrmSessionEventListener.EventDispatcher, LoadErrorHandlingPolicy, MediaSourceEventListener.EventDispatcher, Allocator, CompositeSequenceableLoaderFactory, boolean, int, boolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.hls.HlsExtractorFactory,com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker,com.google.android.exoplayer2.source.hls.HlsDataSourceFactory,com.google.android.exoplayer2.upstream.TransferListener,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher,com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy,com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher,com.google.android.exoplayer2.upstream.Allocator,com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory,boolean,int,boolean)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"HlsMediaPlaylist(int, String, List, long, boolean, long, boolean, int, long, int, long, long, boolean, boolean, boolean, DrmInitData, List, List, HlsMediaPlaylist.ServerControl, Map)","url":"%3Cinit%3E(int,java.lang.String,java.util.List,long,boolean,long,boolean,int,long,int,long,long,boolean,boolean,boolean,com.google.android.exoplayer2.drm.DrmInitData,java.util.List,java.util.List,com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.ServerControl,java.util.Map)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylist","l":"HlsPlaylist(String, List, boolean)","url":"%3Cinit%3E(java.lang.String,java.util.List,boolean)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistParser","l":"HlsPlaylistParser()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistParser","l":"HlsPlaylistParser(HlsMasterPlaylist, HlsMediaPlaylist)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist,com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry","l":"HlsTrackMetadataEntry(String, String, List)","url":"%3Cinit%3E(java.lang.String,java.lang.String,java.util.List)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.ServerControl","l":"holdBackUs"},{"p":"com.google.android.exoplayer2.text.span","c":"HorizontalTextInVerticalContextSpan","l":"HorizontalTextInVerticalContextSpan()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity","l":"HostActivity()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"HTTP_METHOD_GET"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"HTTP_METHOD_HEAD"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"HTTP_METHOD_POST"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"httpBody"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.HttpDataSourceException","l":"HttpDataSourceException(DataSpec, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSpec,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.HttpDataSourceException","l":"HttpDataSourceException(IOException, DataSpec, int)","url":"%3Cinit%3E(java.io.IOException,com.google.android.exoplayer2.upstream.DataSpec,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.HttpDataSourceException","l":"HttpDataSourceException(String, DataSpec, int)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.upstream.DataSpec,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.HttpDataSourceException","l":"HttpDataSourceException(String, IOException, DataSpec, int)","url":"%3Cinit%3E(java.lang.String,java.io.IOException,com.google.android.exoplayer2.upstream.DataSpec,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"HttpDataSourceTestEnv","l":"HttpDataSourceTestEnv()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.drm","c":"HttpMediaDrmCallback","l":"HttpMediaDrmCallback(String, boolean, HttpDataSource.Factory)","url":"%3Cinit%3E(java.lang.String,boolean,com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.drm","c":"HttpMediaDrmCallback","l":"HttpMediaDrmCallback(String, HttpDataSource.Factory)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"httpMethod"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"httpRequestHeaders"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"i(String, String, Throwable)","url":"i(java.lang.String,java.lang.String,java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"i(String, String)","url":"i(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyDecoder","l":"IcyDecoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"IcyHeaders(int, String, String, String, boolean, int)","url":"%3Cinit%3E(int,java.lang.String,java.lang.String,java.lang.String,boolean,int)"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyInfo","l":"IcyInfo(byte[], String, String)","url":"%3Cinit%3E(byte[],java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"id"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"id"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"id"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"id"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"Id3Frame","l":"id"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"id"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"id"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"AdaptationSet","l":"id"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Descriptor","l":"id"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Period","l":"id"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"id"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ApicFrame","l":"ID"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"ID"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterTocFrame","l":"ID"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"CommentFrame","l":"ID"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"GeobFrame","l":"ID"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"InternalFrame","l":"ID"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"MlltFrame","l":"ID"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"PrivFrame","l":"ID"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"AdaptationSet","l":"ID_UNSET"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"EventStream","l":"id()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"Id3Decoder","l":"ID3_HEADER_LENGTH"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"ID3_SCHEME_ID_AOM"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"Id3Decoder","l":"ID3_TAG"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"Id3Decoder","l":"Id3Decoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"Id3Decoder","l":"Id3Decoder(Id3Decoder.FramePredicate)","url":"%3Cinit%3E(com.google.android.exoplayer2.metadata.id3.Id3Decoder.FramePredicate)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"Id3Frame","l":"Id3Frame(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.extractor","c":"Id3Peeker","l":"Id3Peeker()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Id3Reader","l":"Id3Reader()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"PrivateCommand","l":"identifier"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource.IllegalClippingException","l":"IllegalClippingException(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource.IllegalMergeException","l":"IllegalMergeException(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2","c":"IllegalSeekPositionException","l":"IllegalSeekPositionException(Timeline, int, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.Timeline,int,long)"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil","l":"iLog(int)"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"IMAGE_JPEG"},{"p":"com.google.android.exoplayer2.util","c":"NotificationUtil","l":"IMPORTANCE_DEFAULT"},{"p":"com.google.android.exoplayer2.util","c":"NotificationUtil","l":"IMPORTANCE_HIGH"},{"p":"com.google.android.exoplayer2.util","c":"NotificationUtil","l":"IMPORTANCE_LOW"},{"p":"com.google.android.exoplayer2.util","c":"NotificationUtil","l":"IMPORTANCE_MIN"},{"p":"com.google.android.exoplayer2.util","c":"NotificationUtil","l":"IMPORTANCE_NONE"},{"p":"com.google.android.exoplayer2.util","c":"NotificationUtil","l":"IMPORTANCE_UNSPECIFIED"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser.RepresentationInfo","l":"inbandEventStreams"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"inbandEventStreams"},{"p":"com.google.android.exoplayer2.decoder","c":"CryptoInfo","l":"increaseClearDataFirstSubSampleBy(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.DeviceComponent","l":"increaseDeviceVolume()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"increaseDeviceVolume()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"increaseDeviceVolume()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"increaseDeviceVolume()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"increaseDeviceVolume()"},{"p":"com.google.android.exoplayer2.testutil","c":"DumpableFormat","l":"index"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashSegmentIndex","l":"INDEX_UNBOUNDED"},{"p":"com.google.android.exoplayer2","c":"C","l":"INDEX_UNSET"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroup","l":"indexOf(Format)","url":"indexOf(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"indexOf(Format)","url":"indexOf(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"indexOf(Format)","url":"indexOf(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelection","l":"indexOf(Format)","url":"indexOf(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"indexOf(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"indexOf(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelection","l":"indexOf(int)"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroupArray","l":"indexOf(TrackGroup)","url":"indexOf(com.google.android.exoplayer2.source.TrackGroup)"},{"p":"com.google.android.exoplayer2.extractor","c":"IndexSeekMap","l":"IndexSeekMap(long[], long[], long)","url":"%3Cinit%3E(long[],long[],long)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"inferContentType(String)","url":"inferContentType(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"inferContentType(Uri, String)","url":"inferContentType(android.net.Uri,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"inferContentType(Uri)","url":"inferContentType(android.net.Uri)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"inferContentTypeForUriAndMimeType(Uri, String)","url":"inferContentTypeForUriAndMimeType(android.net.Uri,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"inferFileTypeFromMimeType(String)","url":"inferFileTypeFromMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"inferFileTypeFromResponseHeaders(Map>)","url":"inferFileTypeFromResponseHeaders(java.util.Map)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"inferFileTypeFromUri(Uri)","url":"inferFileTypeFromUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"inflate(ParsableByteArray, ParsableByteArray, Inflater)","url":"inflate(com.google.android.exoplayer2.util.ParsableByteArray,com.google.android.exoplayer2.util.ParsableByteArray,java.util.zip.Inflater)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectorResult","l":"info"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunk","l":"init(BaseMediaChunkOutput)","url":"init(com.google.android.exoplayer2.source.chunk.BaseMediaChunkOutput)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BundledChunkExtractor","l":"init(ChunkExtractor.TrackOutputProvider, long, long)","url":"init(com.google.android.exoplayer2.source.chunk.ChunkExtractor.TrackOutputProvider,long,long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkExtractor","l":"init(ChunkExtractor.TrackOutputProvider, long, long)","url":"init(com.google.android.exoplayer2.source.chunk.ChunkExtractor.TrackOutputProvider,long,long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaParserChunkExtractor","l":"init(ChunkExtractor.TrackOutputProvider, long, long)","url":"init(com.google.android.exoplayer2.source.chunk.ChunkExtractor.TrackOutputProvider,long,long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"InitializationChunk","l":"init(ChunkExtractor.TrackOutputProvider)","url":"init(com.google.android.exoplayer2.source.chunk.ChunkExtractor.TrackOutputProvider)"},{"p":"com.google.android.exoplayer2.source","c":"BundledExtractorsAdapter","l":"init(DataReader, Uri, Map>, long, long, ExtractorOutput)","url":"init(com.google.android.exoplayer2.upstream.DataReader,android.net.Uri,java.util.Map,long,long,com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.source","c":"MediaParserExtractorAdapter","l":"init(DataReader, Uri, Map>, long, long, ExtractorOutput)","url":"init(com.google.android.exoplayer2.upstream.DataReader,android.net.Uri,java.util.Map,long,long,com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaExtractor","l":"init(DataReader, Uri, Map>, long, long, ExtractorOutput)","url":"init(com.google.android.exoplayer2.upstream.DataReader,android.net.Uri,java.util.Map,long,long,com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor","c":"Extractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.amr","c":"AmrExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.flac","c":"FlacExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.flv","c":"FlvExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.jpeg","c":"JpegExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.ogg","c":"OggExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.rawcc","c":"RawCcExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Extractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Extractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.wav","c":"WavExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.source.hls","c":"BundledHlsMediaChunkExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaChunkExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.source.hls","c":"MediaParserHlsMediaChunkExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.source.hls","c":"WebvttExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.util","c":"EGLSurfaceTexture","l":"init(int)"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"init(long, int, ByteBuffer)","url":"init(long,int,java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleOutputBuffer","l":"init(long, int)","url":"init(long,int)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionView","l":"init(MappingTrackSelector.MappedTrackInfo, int, boolean, List, Comparator, TrackSelectionView.TrackSelectionListener)","url":"init(com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo,int,boolean,java.util.List,java.util.Comparator,com.google.android.exoplayer2.ui.TrackSelectionView.TrackSelectionListener)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PassthroughSectionPayloadReader","l":"init(TimestampAdjuster, ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"init(com.google.android.exoplayer2.util.TimestampAdjuster,com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PesReader","l":"init(TimestampAdjuster, ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"init(com.google.android.exoplayer2.util.TimestampAdjuster,com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"SectionPayloadReader","l":"init(TimestampAdjuster, ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"init(com.google.android.exoplayer2.util.TimestampAdjuster,com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"SectionReader","l":"init(TimestampAdjuster, ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"init(com.google.android.exoplayer2.util.TimestampAdjuster,com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader","l":"init(TimestampAdjuster, ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"init(com.google.android.exoplayer2.util.TimestampAdjuster,com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelector","l":"init(TrackSelector.InvalidationListener, BandwidthMeter)","url":"init(com.google.android.exoplayer2.trackselection.TrackSelector.InvalidationListener,com.google.android.exoplayer2.upstream.BandwidthMeter)"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"initForPrivateFrame(int, int)","url":"initForPrivateFrame(int,int)"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"initForYuvFrame(int, int, int, int, int)","url":"initForYuvFrame(int,int,int,int,int)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"INITIAL_DRM_REQUEST_RETRY_COUNT"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"initialAudioFormatBitrateCount"},{"p":"com.google.android.exoplayer2.source.chunk","c":"InitializationChunk","l":"InitializationChunk(DataSource, DataSpec, Format, int, Object, ChunkExtractor)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,com.google.android.exoplayer2.Format,int,java.lang.Object,com.google.android.exoplayer2.source.chunk.ChunkExtractor)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"initializationData"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.DvbSubtitleInfo","l":"initializationData"},{"p":"com.google.android.exoplayer2.video","c":"AvcConfig","l":"initializationData"},{"p":"com.google.android.exoplayer2.video","c":"HevcConfig","l":"initializationData"},{"p":"com.google.android.exoplayer2","c":"Format","l":"initializationDataEquals(Format)","url":"initializationDataEquals(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.InitializationException","l":"InitializationException(int, int, int, int, Format, boolean, Exception)","url":"%3Cinit%3E(int,int,int,int,com.google.android.exoplayer2.Format,boolean,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.SegmentBase","l":"initializationSegment"},{"p":"com.google.android.exoplayer2.util","c":"SntpClient","l":"initialize(Loader, SntpClient.InitializationCallback)","url":"initialize(com.google.android.exoplayer2.upstream.Loader,com.google.android.exoplayer2.util.SntpClient.InitializationCallback)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"initialSeek(int, long)","url":"initialSeek(int,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource.InitialTimeline","l":"InitialTimeline(Timeline)","url":"%3Cinit%3E(com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"initialVideoFormatBitrateCount"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"initialVideoFormatHeightCount"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"inputAudioFormat"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"inputBufferCount"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener.EventDispatcher","l":"inputFormatChanged(Format, DecoderReuseEvaluation)","url":"inputFormatChanged(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.decoder.DecoderReuseEvaluation)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener.EventDispatcher","l":"inputFormatChanged(Format, DecoderReuseEvaluation)","url":"inputFormatChanged(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.decoder.DecoderReuseEvaluation)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"InputReaderAdapterV30","l":"InputReaderAdapterV30()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer.CodecMaxValues","l":"inputSize"},{"p":"com.google.android.exoplayer2.upstream","c":"DummyDataSource","l":"INSTANCE"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer.InsufficientCapacityException","l":"InsufficientCapacityException(int, int)","url":"%3Cinit%3E(int,int)"},{"p":"com.google.android.exoplayer2.util","c":"IntArrayQueue","l":"IntArrayQueue()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"integerElement(int, long)","url":"integerElement(int,long)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"integerElement(int, long)","url":"integerElement(int,long)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"InternalFrame","l":"InternalFrame(String, String, String)","url":"%3Cinit%3E(java.lang.String,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelector","l":"invalidate()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"invalidate()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"invalidateForegroundNotification()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"invalidateMediaSessionMetadata()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"invalidateMediaSessionPlaybackState()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"invalidateMediaSessionQueue()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"invalidateUpstreamFormatAdjustment()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.InvalidContentTypeException","l":"InvalidContentTypeException(String, DataSpec)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.InvalidResponseCodeException","l":"InvalidResponseCodeException(int, Map>, DataSpec)","url":"%3Cinit%3E(int,java.util.Map,com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.InvalidResponseCodeException","l":"InvalidResponseCodeException(int, String, Map>, DataSpec, byte[])","url":"%3Cinit%3E(int,java.lang.String,java.util.Map,com.google.android.exoplayer2.upstream.DataSpec,byte[])"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.InvalidResponseCodeException","l":"InvalidResponseCodeException(int, String, Map>, DataSpec)","url":"%3Cinit%3E(int,java.lang.String,java.util.Map,com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.util","c":"ListenerSet.IterationFinishedEvent","l":"invoke(T, ExoFlags)","url":"invoke(T,com.google.android.exoplayer2.util.ExoFlags)"},{"p":"com.google.android.exoplayer2.util","c":"ListenerSet.Event","l":"invoke(T)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData.Segment","l":"isActionSegment()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor","l":"isActive()"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"isActive()"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"isActive()"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"isActive()"},{"p":"com.google.android.exoplayer2.ext.gvr","c":"GvrAudioProcessor","l":"isActive()"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"isAd()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"isAdInErrorState(int, int)","url":"isAdInErrorState(int,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsReader","l":"isAdtsSyncWord(int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"isAfterLast()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"isAnimationEnabled()"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"isAudio(String)","url":"isAudio(java.lang.String)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"isAudioChannelCountSupportedV21(int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"isAudioSampleRateSupportedV21(int)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Gav1Library","l":"isAvailable()"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegLibrary","l":"isAvailable()"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacLibrary","l":"isAvailable()"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusLibrary","l":"isAvailable()"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxLibrary","l":"isAvailable()"},{"p":"com.google.android.exoplayer2.util","c":"LibraryLoader","l":"isAvailable()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"isBeforeFirst()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"isBlacklisted(int, long)","url":"isBlacklisted(int,long)"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"isBlacklisted(int, long)","url":"isBlacklisted(int,long)"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"isBlacklisted(int, long)","url":"isBlacklisted(int,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheSpan","l":"isCached"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"isCached(String, long, long)","url":"isCached(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"isCached(String, long, long)","url":"isCached(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"isCacheFolderLocked(File)","url":"isCacheFolderLocked(java.io.File)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"isCanceled()"},{"p":"com.google.android.exoplayer2.util","c":"RunnableFutureTask","l":"isCancelled()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"isCastSessionAvailable()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceException","l":"isCausedByPositionOutOfRange(IOException)","url":"isCausedByPositionOutOfRange(java.io.IOException)"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"isChargingRequired()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"isClosed()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"isCodecSupported(Format)","url":"isCodecSupported(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"isCommandAvailable(int)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"isCommandAvailable(int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"isControllerFullyVisible()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"isControllerVisible()"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"isCryptoSchemeSupported(UUID)","url":"isCryptoSchemeSupported(java.util.UUID)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"isCurrentStreamFinal()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"isCurrentStreamFinal()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"isCurrentStreamFinal()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"isCurrentWindowDynamic()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"isCurrentWindowDynamic()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"isCurrentWindowLive()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"isCurrentWindowLive()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"isCurrentWindowSeekable()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"isCurrentWindowSeekable()"},{"p":"com.google.android.exoplayer2.decoder","c":"Buffer","l":"isDecodeOnly()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.DeviceComponent","l":"isDeviceMuted()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"isDeviceMuted()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"isDeviceMuted()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"isDeviceMuted()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"isDeviceMuted()"},{"p":"com.google.android.exoplayer2.util","c":"RunnableFutureTask","l":"isDone()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"isDynamic"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"isDynamic"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"isEmpty()"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroupArray","l":"isEmpty()"},{"p":"com.google.android.exoplayer2.util","c":"IntArrayQueue","l":"isEmpty()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"isEnabled"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"isEnabled()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"isEncodingHighResolutionPcm(int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"isEncodingLinearPcm(int)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"TrackEncryptionBox","l":"isEncrypted"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"isEncrypted()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"isEnded"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"isEnded()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"isEnded()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor","l":"isEnded()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"isEnded()"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"isEnded()"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"isEnded()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"isEnded()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"isEnded()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"isEnded()"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"isEnded()"},{"p":"com.google.android.exoplayer2.ext.gvr","c":"GvrAudioProcessor","l":"isEnded()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"isEnded()"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataRenderer","l":"isEnded()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunkIterator","l":"isEnded()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaChunkIterator","l":"isEnded()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"isEnded()"},{"p":"com.google.android.exoplayer2.text","c":"TextRenderer","l":"isEnded()"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"isEnded()"},{"p":"com.google.android.exoplayer2.video.spherical","c":"CameraMotionRenderer","l":"isEnded()"},{"p":"com.google.android.exoplayer2.decoder","c":"Buffer","l":"isEndOfStream()"},{"p":"com.google.android.exoplayer2.util","c":"XmlPullParserUtil","l":"isEndTag(XmlPullParser, String)","url":"isEndTag(org.xmlpull.v1.XmlPullParser,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"XmlPullParserUtil","l":"isEndTag(XmlPullParser)","url":"isEndTag(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectorResult","l":"isEquivalent(TrackSelectorResult, int)","url":"isEquivalent(com.google.android.exoplayer2.trackselection.TrackSelectorResult,int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectorResult","l":"isEquivalent(TrackSelectorResult)","url":"isEquivalent(com.google.android.exoplayer2.trackselection.TrackSelectorResult)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData.Segment","l":"isErrorSegment()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashSegmentIndex","l":"isExplicit()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashWrappingSegmentIndex","l":"isExplicit()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"isExplicit()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.MultiSegmentBase","l":"isExplicit()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SegmentList","l":"isExplicit()"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"isFastForwardEnabled()"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"isFastForwardEnabled()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"isFirst()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"isFlagSet(int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"isFormatSupported(Format)","url":"isFormatSupported(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPayloadFormat","l":"isFormatSupported(MediaDescription)","url":"isFormatSupported(com.google.android.exoplayer2.source.rtsp.MediaDescription)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"isFullyVisible()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"isHdr10PlusOutOfBandMetadataSupported()"},{"p":"com.google.android.exoplayer2","c":"HeartRating","l":"isHeart()"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxLibrary","l":"isHighBitDepthSupported()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheSpan","l":"isHoleSpan()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"isIdle()"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"isIdleRequired()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.Part","l":"isIndependent"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"isInitialized()"},{"p":"com.google.android.exoplayer2.util","c":"SntpClient","l":"isInitialized()"},{"p":"com.google.android.exoplayer2.decoder","c":"Buffer","l":"isKeyFrame()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"isLast()"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"isLastPeriod(int, Timeline.Period, Timeline.Window, int, boolean)","url":"isLastPeriod(int,com.google.android.exoplayer2.Timeline.Period,com.google.android.exoplayer2.Timeline.Window,int,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"isLastSampleQueued()"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"isLevel1Element(int)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"isLevel1Element(int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"isLinebreak(int)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"isLinethrough()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"isLive"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest","l":"isLive"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"isLive"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"isLive()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"isLive()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"isLive()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ContainerMediaChunk","l":"isLoadCompleted()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaChunk","l":"isLoadCompleted()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"SingleSampleMediaChunk","l":"isLoadCompleted()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaChunk","l":"isLoadCompleted()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"isLoading()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"isLoading()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"isLoading()"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"isLoading()"},{"p":"com.google.android.exoplayer2.source","c":"CompositeSequenceableLoader","l":"isLoading()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"isLoading()"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"isLoading()"},{"p":"com.google.android.exoplayer2.source","c":"SequenceableLoader","l":"isLoading()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"isLoading()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"isLoading()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"isLoading()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"isLoading()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"isLoading()"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"isLoading()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"isLoadingFinished()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"isLocalFileUri(Uri)","url":"isLocalFileUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"isMatroska(String)","url":"isMatroska(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil","l":"isNalUnitSei(String, byte)","url":"isNalUnitSei(java.lang.String,byte)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource.Factory","l":"isNetwork"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"isNetworkRequired()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"isNewerThan(HlsMediaPlaylist)","url":"isNewerThan(com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist)"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea608Decoder","l":"isNewSubtitleDataAvailable()"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea708Decoder","l":"isNewSubtitleDataAvailable()"},{"p":"com.google.android.exoplayer2","c":"C","l":"ISO88591_NAME"},{"p":"com.google.android.exoplayer2.util","c":"ConditionVariable","l":"isOpen()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource","l":"isOpened()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheSpan","l":"isOpenEnded()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterTocFrame","l":"isOrdered"},{"p":"com.google.android.exoplayer2.source.hls","c":"BundledHlsMediaChunkExtractor","l":"isPackedAudioExtractor()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaChunkExtractor","l":"isPackedAudioExtractor()"},{"p":"com.google.android.exoplayer2.source.hls","c":"MediaParserHlsMediaChunkExtractor","l":"isPackedAudioExtractor()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"isPlaceholder"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"isPlaceholder"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"isPlaceholder"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"isPlayable"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"isPlaying()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"isPlaying()"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"isPlaying()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"isPlayingAd()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"isPlayingAd()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"isPlayingAd()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"isPlayingAd()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.Part","l":"isPreload"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"isPrepared()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"isPrepared()"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil","l":"isProtectedContentExtensionSupported(Context)","url":"isProtectedContentExtensionSupported(android.content.Context)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"PsshAtomUtil","l":"isPsshAtom(byte[])"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"isPublic"},{"p":"com.google.android.exoplayer2","c":"HeartRating","l":"isRated()"},{"p":"com.google.android.exoplayer2","c":"PercentageRating","l":"isRated()"},{"p":"com.google.android.exoplayer2","c":"Rating","l":"isRated()"},{"p":"com.google.android.exoplayer2","c":"StarRating","l":"isRated()"},{"p":"com.google.android.exoplayer2","c":"ThumbRating","l":"isRated()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"isReady()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"isReady()"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"isReady()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"isReady()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"isReady()"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataRenderer","l":"isReady()"},{"p":"com.google.android.exoplayer2.source","c":"EmptySampleStream","l":"isReady()"},{"p":"com.google.android.exoplayer2.source","c":"SampleStream","l":"isReady()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"isReady()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream.EmbeddedSampleStream","l":"isReady()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"isReady()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"isReady()"},{"p":"com.google.android.exoplayer2.text","c":"TextRenderer","l":"isReady()"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"isReady()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"isReady()"},{"p":"com.google.android.exoplayer2.video.spherical","c":"CameraMotionRenderer","l":"isReady()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"isReady(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.InitializationException","l":"isRecoverable"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.WriteException","l":"isRecoverable"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectorResult","l":"isRendererEnabled(int)"},{"p":"com.google.android.exoplayer2.util","c":"RepeatModeUtil","l":"isRepeatModeEnabled(int, int)","url":"isRepeatModeEnabled(int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader.LoadErrorAction","l":"isRetry()"},{"p":"com.google.android.exoplayer2.source.hls","c":"BundledHlsMediaChunkExtractor","l":"isReusable()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaChunkExtractor","l":"isReusable()"},{"p":"com.google.android.exoplayer2.source.hls","c":"MediaParserHlsMediaChunkExtractor","l":"isReusable()"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"isRewindEnabled()"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"isRewindEnabled()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterTocFrame","l":"isRoot"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"isSeamlessAdaptationSupported(Format, Format, boolean)","url":"isSeamlessAdaptationSupported(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format,boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"isSeamlessAdaptationSupported(Format)","url":"isSeamlessAdaptationSupported(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.video","c":"DummySurface","l":"isSecureSupported(Context)","url":"isSecureSupported(android.content.Context)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"isSeekable"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"isSeekable"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.BinarySearchSeekMap","l":"isSeekable()"},{"p":"com.google.android.exoplayer2.extractor","c":"ChunkIndex","l":"isSeekable()"},{"p":"com.google.android.exoplayer2.extractor","c":"ConstantBitrateSeekMap","l":"isSeekable()"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacSeekTableSeekMap","l":"isSeekable()"},{"p":"com.google.android.exoplayer2.extractor","c":"IndexSeekMap","l":"isSeekable()"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap","l":"isSeekable()"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap.Unseekable","l":"isSeekable()"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"isSeekable()"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"isSeeking()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationHolder","l":"isSegmentAvailableAtFullNetworkSpeed(long, long)","url":"isSegmentAvailableAtFullNetworkSpeed(long,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData","l":"isSimulatingUnknownLength()"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"isSingleWindow()"},{"p":"com.google.android.exoplayer2.source","c":"LoopingMediaSource","l":"isSingleWindow()"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"isSingleWindow()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"isSingleWindow()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"isSnapshotValid(Uri)","url":"isSnapshotValid(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"isSnapshotValid(Uri)","url":"isSnapshotValid(android.net.Uri)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"isSourceReady()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsUtil","l":"isStartOfTsPacket(byte[], int, int, int)","url":"isStartOfTsPacket(byte[],int,int,int)"},{"p":"com.google.android.exoplayer2.util","c":"XmlPullParserUtil","l":"isStartTag(XmlPullParser, String)","url":"isStartTag(org.xmlpull.v1.XmlPullParser,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"XmlPullParserUtil","l":"isStartTag(XmlPullParser)","url":"isStartTag(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.util","c":"XmlPullParserUtil","l":"isStartTagIgnorePrefix(XmlPullParser, String)","url":"isStartTagIgnorePrefix(org.xmlpull.v1.XmlPullParser,java.lang.String)"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"isStorageNotLowRequired()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"isSupported(int, boolean)","url":"isSupported(int,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil","l":"isSurfacelessContextExtensionSupported()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoDecoderException","l":"isSurfaceValid"},{"p":"com.google.android.exoplayer2.audio","c":"DtsUtil","l":"isSyncWord(int)"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"isTerminalState()"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"isText(String)","url":"isText(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"ThumbRating","l":"isThumbsUp()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"isTv(Context)","url":"isTv(android.content.Context)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"isUnderline()"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"isUnmeteredNetworkRequired()"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"isVideo(String)","url":"isVideo(java.lang.String)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"isVideoSizeAndRateSupportedV21(int, int, double)","url":"isVideoSizeAndRateSupportedV21(int,int,double)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"isVisible()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"isVisible()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"isWaitingForRequirements()"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttParserUtil","l":"isWebvttHeaderLine(ParsableByteArray)","url":"isWebvttHeaderLine(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"isWindowColorSet()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.AudioTrackScore","l":"isWithinConstraints"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.TextTrackScore","l":"isWithinConstraints"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.VideoTrackScore","l":"isWithinMaxConstraints"},{"p":"com.google.android.exoplayer2.util","c":"CopyOnWriteMultiset","l":"iterator()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveDataSet.Iterator","l":"Iterator(FakeAdaptiveDataSet, int, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.testutil.FakeAdaptiveDataSet,int,int)"},{"p":"com.google.android.exoplayer2.decoder","c":"CryptoInfo","l":"iv"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"JPEG"},{"p":"com.google.android.exoplayer2.extractor.jpeg","c":"JpegExtractor","l":"JpegExtractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"jumpDrawablesToCurrentState()"},{"p":"com.google.android.exoplayer2.decoder","c":"CryptoInfo","l":"key"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"VorbisComment","l":"key"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MdtaMetadataEntry","l":"key"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"key"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheSpan","l":"key"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MdtaMetadataEntry","l":"KEY_ANDROID_CAPTURE_FPS"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"KEY_CONTENT_ID"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadata","l":"KEY_CONTENT_LENGTH"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadata","l":"KEY_CUSTOM_PREFIX"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"KEY_DOWNLOAD_REQUEST"},{"p":"com.google.android.exoplayer2.util","c":"MediaFormatUtil","l":"KEY_EXO_PCM_ENCODING"},{"p":"com.google.android.exoplayer2.util","c":"MediaFormatUtil","l":"KEY_EXO_PIXEL_WIDTH_HEIGHT_RATIO_FLOAT"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"KEY_FOREGROUND"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadata","l":"KEY_REDIRECTED_URI"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"KEY_REQUIREMENTS"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"KEY_STATUS_AVAILABLE"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"KEY_STATUS_KEY"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"KEY_STATUS_UNAVAILABLE"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"KEY_STOP_REASON"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"KEY_TYPE_OFFLINE"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"KEY_TYPE_RELEASE"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"KEY_TYPE_STREAMING"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyRequest","l":"KeyRequest(byte[], String, int)","url":"%3Cinit%3E(byte[],java.lang.String,int)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyRequest","l":"KeyRequest(byte[], String)","url":"%3Cinit%3E(byte[],java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"keySetId"},{"p":"com.google.android.exoplayer2.drm","c":"KeysExpiredException","l":"KeysExpiredException()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyStatus","l":"KeyStatus(int, byte[])","url":"%3Cinit%3E(int,byte[])"},{"p":"com.google.android.exoplayer2","c":"Format","l":"label"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Subtitle","l":"label"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ProgramInformation","l":"lang"},{"p":"com.google.android.exoplayer2","c":"Format","l":"language"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Subtitle","l":"language"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.DvbSubtitleInfo","l":"language"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.EsInfo","l":"language"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"CommentFrame","l":"language"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"language"},{"p":"com.google.android.exoplayer2","c":"C","l":"LANGUAGE_UNDETERMINED"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"lastFormat"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.RenditionReport","l":"lastMediaSequence"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.RenditionReport","l":"lastPartIndex"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"lastPeriodIndex"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheSpan","l":"lastTouchTimestamp"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"LatmReader","l":"LatmReader(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"ListenerSet","l":"lazyRelease(int, ListenerSet.Event)","url":"lazyRelease(int,com.google.android.exoplayer2.util.ListenerSet.Event)"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"LeanbackPlayerAdapter(Context, Player, int)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.Player,int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"LeastRecentlyUsedCacheEvictor","l":"LeastRecentlyUsedCacheEvictor(long)","url":"%3Cinit%3E(long)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"legacyKeepAvailableCodecInfosWithoutCodec()"},{"p":"com.google.android.exoplayer2.extractor","c":"ChunkIndex","l":"length"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.CommentHeader","l":"length"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroup","l":"length"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroupArray","l":"length"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"RangedUri","l":"length"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData.Segment","l":"length"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"length"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.SelectionOverride","l":"length"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionArray","l":"length"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectorResult","l":"length"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"length"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheSpan","l":"length"},{"p":"com.google.android.exoplayer2","c":"C","l":"LENGTH_UNSET"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata","l":"length()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"length()"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"length()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelection","l":"length()"},{"p":"com.google.android.exoplayer2.video","c":"DolbyVisionConfig","l":"level"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"levelIdc"},{"p":"com.google.android.exoplayer2.ext.flac","c":"LibflacAudioRenderer","l":"LibflacAudioRenderer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.flac","c":"LibflacAudioRenderer","l":"LibflacAudioRenderer(Handler, AudioRendererEventListener, AudioProcessor...)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioProcessor...)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"LibflacAudioRenderer","l":"LibflacAudioRenderer(Handler, AudioRendererEventListener, AudioSink)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioSink)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Libgav1VideoRenderer","l":"Libgav1VideoRenderer(long, Handler, VideoRendererEventListener, int, int, int, int)","url":"%3Cinit%3E(long,android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener,int,int,int,int)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Libgav1VideoRenderer","l":"Libgav1VideoRenderer(long, Handler, VideoRendererEventListener, int)","url":"%3Cinit%3E(long,android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener,int)"},{"p":"com.google.android.exoplayer2.ext.opus","c":"LibopusAudioRenderer","l":"LibopusAudioRenderer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.opus","c":"LibopusAudioRenderer","l":"LibopusAudioRenderer(Handler, AudioRendererEventListener, AudioProcessor...)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioProcessor...)"},{"p":"com.google.android.exoplayer2.ext.opus","c":"LibopusAudioRenderer","l":"LibopusAudioRenderer(Handler, AudioRendererEventListener, AudioSink)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioSink)"},{"p":"com.google.android.exoplayer2.util","c":"LibraryLoader","l":"LibraryLoader(String...)","url":"%3Cinit%3E(java.lang.String...)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"LibvpxVideoRenderer","l":"LibvpxVideoRenderer(long, Handler, VideoRendererEventListener, int, int, int, int)","url":"%3Cinit%3E(long,android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener,int,int,int,int)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"LibvpxVideoRenderer","l":"LibvpxVideoRenderer(long, Handler, VideoRendererEventListener, int)","url":"%3Cinit%3E(long,android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener,int)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"LibvpxVideoRenderer","l":"LibvpxVideoRenderer(long)","url":"%3Cinit%3E(long)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"licenseServerUrl"},{"p":"com.google.android.exoplayer2","c":"MediaItem.DrmConfiguration","l":"licenseUri"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"limit()"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"line"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"LINE_TYPE_FRACTION"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"LINE_TYPE_NUMBER"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"lineAnchor"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"linearSearch(int[], int)","url":"linearSearch(int[],int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"linearSearch(long[], long)","url":"linearSearch(long[],long)"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"lineType"},{"p":"com.google.android.exoplayer2.util","c":"ListenerSet","l":"ListenerSet(Looper, Clock, ListenerSet.IterationFinishedEvent)","url":"%3Cinit%3E(android.os.Looper,com.google.android.exoplayer2.util.Clock,com.google.android.exoplayer2.util.ListenerSet.IterationFinishedEvent)"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"liveConfiguration"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"liveConfiguration"},{"p":"com.google.android.exoplayer2","c":"MediaItem.LiveConfiguration","l":"LiveConfiguration(long, long, long, float, float)","url":"%3Cinit%3E(long,long,long,float,float)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper.LiveContentUnsupportedException","l":"LiveContentUnsupportedException()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ContainerMediaChunk","l":"load()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"DataChunk","l":"load()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"InitializationChunk","l":"load()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"SingleSampleMediaChunk","l":"load()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaChunk","l":"load()"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader.Loadable","l":"load()"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"load()"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"load(DataSource, ParsingLoadable.Parser, DataSpec, int)","url":"load(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.ParsingLoadable.Parser,com.google.android.exoplayer2.upstream.DataSpec,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"load(DataSource, ParsingLoadable.Parser, Uri, int)","url":"load(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.ParsingLoadable.Parser,android.net.Uri,int)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"loadCanceled(LoadEventInfo, int, int, Format, int, Object, long, long)","url":"loadCanceled(com.google.android.exoplayer2.source.LoadEventInfo,int,int,com.google.android.exoplayer2.Format,int,java.lang.Object,long,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"loadCanceled(LoadEventInfo, int)","url":"loadCanceled(com.google.android.exoplayer2.source.LoadEventInfo,int)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"loadCanceled(LoadEventInfo, MediaLoadData)","url":"loadCanceled(com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashUtil","l":"loadChunkIndex(DataSource, int, Representation)","url":"loadChunkIndex(com.google.android.exoplayer2.upstream.DataSource,int,com.google.android.exoplayer2.source.dash.manifest.Representation)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"loadCompleted(LoadEventInfo, int, int, Format, int, Object, long, long)","url":"loadCompleted(com.google.android.exoplayer2.source.LoadEventInfo,int,int,com.google.android.exoplayer2.Format,int,java.lang.Object,long,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"loadCompleted(LoadEventInfo, int)","url":"loadCompleted(com.google.android.exoplayer2.source.LoadEventInfo,int)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"loadCompleted(LoadEventInfo, MediaLoadData)","url":"loadCompleted(com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source","c":"LoadEventInfo","l":"loadDurationMs"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"Loader(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"loadError(LoadEventInfo, int, int, Format, int, Object, long, long, IOException, boolean)","url":"loadError(com.google.android.exoplayer2.source.LoadEventInfo,int,int,com.google.android.exoplayer2.Format,int,java.lang.Object,long,long,java.io.IOException,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"loadError(LoadEventInfo, int, IOException, boolean)","url":"loadError(com.google.android.exoplayer2.source.LoadEventInfo,int,java.io.IOException,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"loadError(LoadEventInfo, MediaLoadData, IOException, boolean)","url":"loadError(com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData,java.io.IOException,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy.LoadErrorInfo","l":"LoadErrorInfo(LoadEventInfo, MediaLoadData, IOException, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData,java.io.IOException,int)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeSequenceableLoader","l":"loaders"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy.LoadErrorInfo","l":"loadEventInfo"},{"p":"com.google.android.exoplayer2.source","c":"LoadEventInfo","l":"LoadEventInfo(long, DataSpec, long)","url":"%3Cinit%3E(long,com.google.android.exoplayer2.upstream.DataSpec,long)"},{"p":"com.google.android.exoplayer2.source","c":"LoadEventInfo","l":"LoadEventInfo(long, DataSpec, Uri, Map>, long, long, long)","url":"%3Cinit%3E(long,com.google.android.exoplayer2.upstream.DataSpec,android.net.Uri,java.util.Map,long,long,long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashUtil","l":"loadFormatWithDrmInitData(DataSource, Period)","url":"loadFormatWithDrmInitData(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.source.dash.manifest.Period)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"loadItem(MediaQueueItem, long)","url":"loadItem(com.google.android.gms.cast.MediaQueueItem,long)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"loadItems(MediaQueueItem[], int, long, int)","url":"loadItems(com.google.android.gms.cast.MediaQueueItem[],int,long,int)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashUtil","l":"loadManifest(DataSource, Uri)","url":"loadManifest(com.google.android.exoplayer2.upstream.DataSource,android.net.Uri)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashUtil","l":"loadSampleFormat(DataSource, int, Representation)","url":"loadSampleFormat(com.google.android.exoplayer2.upstream.DataSource,int,com.google.android.exoplayer2.source.dash.manifest.Representation)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"loadStarted(LoadEventInfo, int, int, Format, int, Object, long, long)","url":"loadStarted(com.google.android.exoplayer2.source.LoadEventInfo,int,int,com.google.android.exoplayer2.Format,int,java.lang.Object,long,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"loadStarted(LoadEventInfo, int)","url":"loadStarted(com.google.android.exoplayer2.source.LoadEventInfo,int)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"loadStarted(LoadEventInfo, MediaLoadData)","url":"loadStarted(com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source","c":"LoadEventInfo","l":"loadTaskId"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"loadTaskId"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"loadTaskId"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MdtaMetadataEntry","l":"localeIndicator"},{"p":"com.google.android.exoplayer2.drm","c":"LocalMediaDrmCallback","l":"LocalMediaDrmCallback(byte[])","url":"%3Cinit%3E(byte[])"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"location"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"LOG_LEVEL_ALL"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"LOG_LEVEL_ERROR"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"LOG_LEVEL_INFO"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"LOG_LEVEL_OFF"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"LOG_LEVEL_WARNING"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"logd(String)","url":"logd(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"loge(String)","url":"loge(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"logMetrics(DecoderCounters, DecoderCounters)","url":"logMetrics(com.google.android.exoplayer2.decoder.DecoderCounters,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.util","c":"LongArray","l":"LongArray()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.util","c":"LongArray","l":"LongArray(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest","l":"lookAheadCount"},{"p":"com.google.android.exoplayer2.source","c":"LoopingMediaSource","l":"LoopingMediaSource(MediaSource, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaSource,int)"},{"p":"com.google.android.exoplayer2.source","c":"LoopingMediaSource","l":"LoopingMediaSource(MediaSource)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest","l":"majorVersion"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"manifest"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"MANUFACTURER"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.Mode","l":"mapping"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector","l":"MappingTrackSelector()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.text.span","c":"TextEmphasisSpan","l":"MARK_FILL_FILLED"},{"p":"com.google.android.exoplayer2.text.span","c":"TextEmphasisSpan","l":"MARK_FILL_OPEN"},{"p":"com.google.android.exoplayer2.text.span","c":"TextEmphasisSpan","l":"MARK_FILL_UNKNOWN"},{"p":"com.google.android.exoplayer2.text.span","c":"TextEmphasisSpan","l":"MARK_SHAPE_CIRCLE"},{"p":"com.google.android.exoplayer2.text.span","c":"TextEmphasisSpan","l":"MARK_SHAPE_DOT"},{"p":"com.google.android.exoplayer2.text.span","c":"TextEmphasisSpan","l":"MARK_SHAPE_NONE"},{"p":"com.google.android.exoplayer2.text.span","c":"TextEmphasisSpan","l":"MARK_SHAPE_SESAME"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"markAsProcessed(boolean)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"marker"},{"p":"com.google.android.exoplayer2.text.span","c":"TextEmphasisSpan","l":"markFill"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"markSeekOperationFinished(boolean, long)","url":"markSeekOperationFinished(boolean,long)"},{"p":"com.google.android.exoplayer2.text.span","c":"TextEmphasisSpan","l":"markShape"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"MaskingMediaPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource","l":"MaskingMediaSource(MediaSource, boolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaSource,boolean)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsManifest","l":"masterPlaylist"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"matches(UUID)","url":"matches(java.util.UUID)"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusLibrary","l":"matchesExpectedExoMediaCryptoType(Class)","url":"matchesExpectedExoMediaCryptoType(java.lang.Class)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxLibrary","l":"matchesExpectedExoMediaCryptoType(Class)","url":"matchesExpectedExoMediaCryptoType(java.lang.Class)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"MATROSKA"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"MatroskaExtractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"MatroskaExtractor(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY"},{"p":"com.google.android.exoplayer2.util","c":"FlacConstants","l":"MAX_FRAME_HEADER_SIZE"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil","l":"MAX_FRAME_SIZE_BYTES"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"MAX_PITCH"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"MAX_PLAYBACK_SPEED"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"MAX_PLAYING_TIME_DISCREPANCY_MS"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util","l":"MAX_RATE_BYTES_PER_SECOND"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil","l":"MAX_RATE_BYTES_PER_SECOND"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"MAX_SEQUENCE_NUMBER"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"MAX_SIZE"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"MAX_SUPPORTED_INSTANCES_UNKNOWN"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"MAX_WINDOWS_FOR_MULTI_WINDOW_TIME_BAR"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"MAX_WINDOWS_FOR_MULTI_WINDOW_TIME_BAR"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"maxAudioBitrate"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"maxAudioChannelCount"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"maxBlockSizeSamples"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"maxConsecutiveDroppedBufferCount"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"maxFrameSize"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecUtil","l":"maxH264DecodableFrameSize()"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"maxHeight"},{"p":"com.google.android.exoplayer2","c":"Format","l":"maxInputSize"},{"p":"com.google.android.exoplayer2","c":"MediaItem.LiveConfiguration","l":"maxOffsetMs"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ServiceDescriptionElement","l":"maxOffsetMs"},{"p":"com.google.android.exoplayer2","c":"MediaItem.LiveConfiguration","l":"maxPlaybackSpeed"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ServiceDescriptionElement","l":"maxPlaybackSpeed"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"maxRebufferTimeMs"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"maxVideoBitrate"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"maxVideoFrameRate"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"maxVideoHeight"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"maxVideoWidth"},{"p":"com.google.android.exoplayer2.device","c":"DeviceInfo","l":"maxVolume"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"maxWidth"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"maybeDropBuffersToKeyframe(long, boolean)","url":"maybeDropBuffersToKeyframe(long,boolean)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"maybeDropBuffersToKeyframe(long)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"maybeInitCodecOrBypass()"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler.PlayerTrackEmsgHandler","l":"maybeRefreshManifestBeforeLoadingNextChunk(long)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"maybeRequestReadExternalStoragePermission(Activity, MediaItem...)","url":"maybeRequestReadExternalStoragePermission(android.app.Activity,com.google.android.exoplayer2.MediaItem...)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"maybeRequestReadExternalStoragePermission(Activity, Uri...)","url":"maybeRequestReadExternalStoragePermission(android.app.Activity,android.net.Uri...)"},{"p":"com.google.android.exoplayer2.util","c":"MediaFormatUtil","l":"maybeSetByteBuffer(MediaFormat, String, byte[])","url":"maybeSetByteBuffer(android.media.MediaFormat,java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.util","c":"MediaFormatUtil","l":"maybeSetColorInfo(MediaFormat, ColorInfo)","url":"maybeSetColorInfo(android.media.MediaFormat,com.google.android.exoplayer2.video.ColorInfo)"},{"p":"com.google.android.exoplayer2.util","c":"MediaFormatUtil","l":"maybeSetFloat(MediaFormat, String, float)","url":"maybeSetFloat(android.media.MediaFormat,java.lang.String,float)"},{"p":"com.google.android.exoplayer2.util","c":"MediaFormatUtil","l":"maybeSetInteger(MediaFormat, String, int)","url":"maybeSetInteger(android.media.MediaFormat,java.lang.String,int)"},{"p":"com.google.android.exoplayer2.util","c":"MediaFormatUtil","l":"maybeSetString(MediaFormat, String, String)","url":"maybeSetString(android.media.MediaFormat,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"maybeSkipTag(XmlPullParser)","url":"maybeSkipTag(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.source","c":"EmptySampleStream","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.source","c":"SampleStream","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream.EmbeddedSampleStream","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSource","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.upstream","c":"LoaderErrorThrower","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.upstream","c":"LoaderErrorThrower.Dummy","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"maybeThrowError(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"LoaderErrorThrower","l":"maybeThrowError(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"LoaderErrorThrower.Dummy","l":"maybeThrowError(int)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"maybeThrowPlaylistRefreshError(Uri)","url":"maybeThrowPlaylistRefreshError(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"maybeThrowPlaylistRefreshError(Uri)","url":"maybeThrowPlaylistRefreshError(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"maybeThrowPrepareError()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"maybeThrowPrepareError()"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"maybeThrowPrepareError()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"maybeThrowPrepareError()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"maybeThrowPrepareError()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"maybeThrowPrepareError()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"maybeThrowPrimaryPlaylistRefreshError()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"maybeThrowPrimaryPlaylistRefreshError()"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"maybeThrowStreamError()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"maybeThrowStreamError()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"maybeThrowStreamError()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MdtaMetadataEntry","l":"MdtaMetadataEntry(String, byte[], int, int)","url":"%3Cinit%3E(java.lang.String,byte[],int,int)"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource","l":"MEDIA_ID"},{"p":"com.google.android.exoplayer2","c":"Player","l":"MEDIA_ITEM_TRANSITION_REASON_AUTO"},{"p":"com.google.android.exoplayer2","c":"Player","l":"MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"MEDIA_ITEM_TRANSITION_REASON_REPEAT"},{"p":"com.google.android.exoplayer2","c":"Player","l":"MEDIA_ITEM_TRANSITION_REASON_SEEK"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaChunk","l":"MediaChunk(DataSource, DataSpec, Format, int, Object, long, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,com.google.android.exoplayer2.Format,int,java.lang.Object,long,long,long)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"MediaCodecAudioRenderer(Context, MediaCodecAdapter.Factory, MediaCodecSelector, boolean, Handler, AudioRendererEventListener, AudioSink)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.mediacodec.MediaCodecAdapter.Factory,com.google.android.exoplayer2.mediacodec.MediaCodecSelector,boolean,android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioSink)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"MediaCodecAudioRenderer(Context, MediaCodecSelector, boolean, Handler, AudioRendererEventListener, AudioSink)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.mediacodec.MediaCodecSelector,boolean,android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioSink)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"MediaCodecAudioRenderer(Context, MediaCodecSelector, Handler, AudioRendererEventListener, AudioCapabilities, AudioProcessor...)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.mediacodec.MediaCodecSelector,android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioCapabilities,com.google.android.exoplayer2.audio.AudioProcessor...)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"MediaCodecAudioRenderer(Context, MediaCodecSelector, Handler, AudioRendererEventListener, AudioSink)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.mediacodec.MediaCodecSelector,android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioSink)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"MediaCodecAudioRenderer(Context, MediaCodecSelector, Handler, AudioRendererEventListener)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.mediacodec.MediaCodecSelector,android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"MediaCodecAudioRenderer(Context, MediaCodecSelector)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.mediacodec.MediaCodecSelector)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecDecoderException","l":"MediaCodecDecoderException(Throwable, MediaCodecInfo)","url":"%3Cinit%3E(java.lang.Throwable,com.google.android.exoplayer2.mediacodec.MediaCodecInfo)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"MediaCodecRenderer(int, MediaCodecAdapter.Factory, MediaCodecSelector, boolean, float)","url":"%3Cinit%3E(int,com.google.android.exoplayer2.mediacodec.MediaCodecAdapter.Factory,com.google.android.exoplayer2.mediacodec.MediaCodecSelector,boolean,float)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoDecoderException","l":"MediaCodecVideoDecoderException(Throwable, MediaCodecInfo, Surface)","url":"%3Cinit%3E(java.lang.Throwable,com.google.android.exoplayer2.mediacodec.MediaCodecInfo,android.view.Surface)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"MediaCodecVideoRenderer(Context, MediaCodecAdapter.Factory, MediaCodecSelector, long, boolean, Handler, VideoRendererEventListener, int)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.mediacodec.MediaCodecAdapter.Factory,com.google.android.exoplayer2.mediacodec.MediaCodecSelector,long,boolean,android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener,int)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"MediaCodecVideoRenderer(Context, MediaCodecSelector, long, boolean, Handler, VideoRendererEventListener, int)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.mediacodec.MediaCodecSelector,long,boolean,android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener,int)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"MediaCodecVideoRenderer(Context, MediaCodecSelector, long, Handler, VideoRendererEventListener, int)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.mediacodec.MediaCodecSelector,long,android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener,int)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"MediaCodecVideoRenderer(Context, MediaCodecSelector, long)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.mediacodec.MediaCodecSelector,long)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"MediaCodecVideoRenderer(Context, MediaCodecSelector)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.mediacodec.MediaCodecSelector)"},{"p":"com.google.android.exoplayer2.drm","c":"MediaDrmCallbackException","l":"MediaDrmCallbackException(DataSpec, Uri, Map>, long, Throwable)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSpec,android.net.Uri,java.util.Map,long,java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.source","c":"MediaLoadData","l":"mediaEndTimeMs"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter.Configuration","l":"mediaFormat"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"mediaId"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor.MediaIdEqualityChecker","l":"MediaIdEqualityChecker()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.MediaIdMediaItemProvider","l":"MediaIdMediaItemProvider()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"mediaItem"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"mediaItem"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy.LoadErrorInfo","l":"mediaLoadData"},{"p":"com.google.android.exoplayer2.source","c":"MediaLoadData","l":"MediaLoadData(int, int, Format, int, Object, long, long)","url":"%3Cinit%3E(int,int,com.google.android.exoplayer2.Format,int,java.lang.Object,long,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaLoadData","l":"MediaLoadData(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"mediaMetadata"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaParserChunkExtractor","l":"MediaParserChunkExtractor(int, Format, List)","url":"%3Cinit%3E(int,com.google.android.exoplayer2.Format,java.util.List)"},{"p":"com.google.android.exoplayer2.source","c":"MediaParserExtractorAdapter","l":"MediaParserExtractorAdapter()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.hls","c":"MediaParserHlsMediaChunkExtractor","l":"MediaParserHlsMediaChunkExtractor(MediaParser, OutputConsumerAdapterV30, Format, boolean, ImmutableList, int)","url":"%3Cinit%3E(android.media.MediaParser,com.google.android.exoplayer2.source.mediaparser.OutputConsumerAdapterV30,com.google.android.exoplayer2.Format,boolean,com.google.common.collect.ImmutableList,int)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"mediaPeriod"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"mediaPeriodId"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"mediaPeriodId"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener.EventDispatcher","l":"mediaPeriodId"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"mediaPeriodId"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"MediaPeriodId(MediaPeriodId)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource.MediaPeriodId","l":"MediaPeriodId(MediaPeriodId)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"MediaPeriodId(Object, int, int, long)","url":"%3Cinit%3E(java.lang.Object,int,int,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource.MediaPeriodId","l":"MediaPeriodId(Object, int, int, long)","url":"%3Cinit%3E(java.lang.Object,int,int,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"MediaPeriodId(Object, long, int)","url":"%3Cinit%3E(java.lang.Object,long,int)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource.MediaPeriodId","l":"MediaPeriodId(Object, long, int)","url":"%3Cinit%3E(java.lang.Object,long,int)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"MediaPeriodId(Object, long)","url":"%3Cinit%3E(java.lang.Object,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource.MediaPeriodId","l":"MediaPeriodId(Object, long)","url":"%3Cinit%3E(java.lang.Object,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"MediaPeriodId(Object)","url":"%3Cinit%3E(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource.MediaPeriodId","l":"MediaPeriodId(Object)","url":"%3Cinit%3E(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsManifest","l":"mediaPlaylist"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"mediaPlaylistUrls"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"mediaSequence"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"mediaSession"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"MediaSessionConnector(MediaSessionCompat)","url":"%3Cinit%3E(android.support.v4.media.session.MediaSessionCompat)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"MediaSourceTestRunner(MediaSource, Allocator)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaSource,com.google.android.exoplayer2.upstream.Allocator)"},{"p":"com.google.android.exoplayer2.source","c":"MediaLoadData","l":"mediaStartTimeMs"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"mediaTimeHistory"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"mediaUri"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"merge(DecoderCounters)","url":"merge(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"merge(DrmInitData)","url":"merge(com.google.android.exoplayer2.drm.DrmInitData)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"merge(PlaybackStats...)","url":"merge(com.google.android.exoplayer2.analytics.PlaybackStats...)"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"MergingMediaSource(boolean, boolean, CompositeSequenceableLoaderFactory, MediaSource...)","url":"%3Cinit%3E(boolean,boolean,com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory,com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"MergingMediaSource(boolean, boolean, MediaSource...)","url":"%3Cinit%3E(boolean,boolean,com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"MergingMediaSource(boolean, MediaSource...)","url":"%3Cinit%3E(boolean,com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"MergingMediaSource(MediaSource...)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"messageData"},{"p":"com.google.android.exoplayer2","c":"Format","l":"metadata"},{"p":"com.google.android.exoplayer2.util","c":"FlacConstants","l":"METADATA_BLOCK_HEADER_SIZE"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource","l":"METADATA_TYPE_EMSG"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource","l":"METADATA_TYPE_ID3"},{"p":"com.google.android.exoplayer2.util","c":"FlacConstants","l":"METADATA_TYPE_PICTURE"},{"p":"com.google.android.exoplayer2.util","c":"FlacConstants","l":"METADATA_TYPE_SEEK_TABLE"},{"p":"com.google.android.exoplayer2.util","c":"FlacConstants","l":"METADATA_TYPE_STREAM_INFO"},{"p":"com.google.android.exoplayer2.util","c":"FlacConstants","l":"METADATA_TYPE_VORBIS_COMMENT"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata","l":"Metadata(List)","url":"%3Cinit%3E(java.util.List)"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata","l":"Metadata(Metadata.Entry...)","url":"%3Cinit%3E(com.google.android.exoplayer2.metadata.Metadata.Entry...)"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataInputBuffer","l":"MetadataInputBuffer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"metadataInterval"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataRenderer","l":"MetadataRenderer(MetadataOutput, Looper, MetadataDecoderFactory)","url":"%3Cinit%3E(com.google.android.exoplayer2.metadata.MetadataOutput,android.os.Looper,com.google.android.exoplayer2.metadata.MetadataDecoderFactory)"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataRenderer","l":"MetadataRenderer(MetadataOutput, Looper)","url":"%3Cinit%3E(com.google.android.exoplayer2.metadata.MetadataOutput,android.os.Looper)"},{"p":"com.google.android.exoplayer2","c":"C","l":"MICROS_PER_SECOND"},{"p":"com.google.android.exoplayer2","c":"C","l":"MILLIS_PER_SECOND"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"MlltFrame","l":"millisecondsBetweenReference"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"MlltFrame","l":"millisecondsDeviations"},{"p":"com.google.android.exoplayer2","c":"MediaItem.PlaybackProperties","l":"mimeType"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Subtitle","l":"mimeType"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util.SyncFrameInfo","l":"mimeType"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil.Header","l":"mimeType"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"mimeType"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"mimeType"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer.DecoderInitializationException","l":"mimeType"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"mimeType"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ApicFrame","l":"mimeType"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"GeobFrame","l":"mimeType"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"mimeType"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea608Decoder","l":"MIN_DATA_CHANNEL_TIMEOUT_MS"},{"p":"com.google.android.exoplayer2.util","c":"FlacConstants","l":"MIN_FRAME_HEADER_SIZE"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"MIN_HEADER_SIZE"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"MIN_PITCH"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"MIN_PLAYBACK_SPEED"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"MIN_SEQUENCE_NUMBER"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"minBlockSizeSamples"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"minBufferTimeMs"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"minFrameSize"},{"p":"com.google.android.exoplayer2","c":"MediaItem.LiveConfiguration","l":"minOffsetMs"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ServiceDescriptionElement","l":"minOffsetMs"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest","l":"minorVersion"},{"p":"com.google.android.exoplayer2","c":"MediaItem.LiveConfiguration","l":"minPlaybackSpeed"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ServiceDescriptionElement","l":"minPlaybackSpeed"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"minUpdatePeriodMs"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"minValue(SparseLongArray)","url":"minValue(android.util.SparseLongArray)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"minVideoBitrate"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"minVideoFrameRate"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"minVideoHeight"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"minVideoWidth"},{"p":"com.google.android.exoplayer2.device","c":"DeviceInfo","l":"minVolume"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifestParser.MissingFieldException","l":"MissingFieldException(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"MlltFrame","l":"MlltFrame(int, int, int, int[], int[])","url":"%3Cinit%3E(int,int,int,int[],int[])"},{"p":"com.google.android.exoplayer2.decoder","c":"CryptoInfo","l":"mode"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"mode"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"MODE_DOWNLOAD"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"MODE_HLS"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"MODE_MULTI_PMT"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"MODE_PLAYBACK"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"MODE_QUERY"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"MODE_RELEASE"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"MODE_SINGLE_PMT"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.Mode","l":"Mode(boolean, int, int, int)","url":"%3Cinit%3E(boolean,int,int,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"MODEL"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"modifyTrack(Track)","url":"modifyTrack(com.google.android.exoplayer2.extractor.mp4.Track)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ProgramInformation","l":"moreInformationURL"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MotionPhotoMetadata","l":"MotionPhotoMetadata(long, long, long, long, long)","url":"%3Cinit%3E(long,long,long,long,long)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor.QueueDataAdapter","l":"move(int, int)","url":"move(int,int)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"moveItem(int, int)","url":"moveItem(int,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"moveItems(List, int, int, int)","url":"moveItems(java.util.List,int,int,int)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"moveMediaItem(int, int)","url":"moveMediaItem(int,int)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"moveMediaItem(int, int)","url":"moveMediaItem(int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"moveMediaItem(int, int)","url":"moveMediaItem(int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.MoveMediaItem","l":"MoveMediaItem(String, int, int)","url":"%3Cinit%3E(java.lang.String,int,int)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"moveMediaItems(int, int, int)","url":"moveMediaItems(int,int,int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"moveMediaItems(int, int, int)","url":"moveMediaItems(int,int,int)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"moveMediaItems(int, int, int)","url":"moveMediaItems(int,int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"moveMediaItems(int, int, int)","url":"moveMediaItems(int,int,int)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"moveMediaSource(int, int, Handler, Runnable)","url":"moveMediaSource(int,int,android.os.Handler,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"moveMediaSource(int, int)","url":"moveMediaSource(int,int)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"movePlaylistItem(int, int)","url":"movePlaylistItem(int,int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"moveToFirst()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"moveToLast()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"moveToNext()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"moveToPosition(int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"moveToPrevious()"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"movieTimescale"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"MP3"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"Mp3Extractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"Mp3Extractor(int, long)","url":"%3Cinit%3E(int,long)"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"Mp3Extractor(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"MP4"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"Mp4Extractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"Mp4Extractor(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"Mp4WebvttDecoder","l":"Mp4WebvttDecoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"MpegAudioReader","l":"MpegAudioReader()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"MpegAudioReader","l":"MpegAudioReader(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"MlltFrame","l":"mpegFramesBetweenReference"},{"p":"com.google.android.exoplayer2","c":"C","l":"MSG_CUSTOM_BASE"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"MSG_CUSTOM_BASE"},{"p":"com.google.android.exoplayer2","c":"C","l":"MSG_SET_AUDIO_ATTRIBUTES"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"MSG_SET_AUDIO_ATTRIBUTES"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"MSG_SET_AUDIO_SESSION_ID"},{"p":"com.google.android.exoplayer2","c":"C","l":"MSG_SET_AUX_EFFECT_INFO"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"MSG_SET_AUX_EFFECT_INFO"},{"p":"com.google.android.exoplayer2","c":"C","l":"MSG_SET_CAMERA_MOTION_LISTENER"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"MSG_SET_CAMERA_MOTION_LISTENER"},{"p":"com.google.android.exoplayer2","c":"C","l":"MSG_SET_SCALING_MODE"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"MSG_SET_SCALING_MODE"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"MSG_SET_SKIP_SILENCE_ENABLED"},{"p":"com.google.android.exoplayer2","c":"C","l":"MSG_SET_SURFACE"},{"p":"com.google.android.exoplayer2","c":"C","l":"MSG_SET_VIDEO_FRAME_METADATA_LISTENER"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"MSG_SET_VIDEO_FRAME_METADATA_LISTENER"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"MSG_SET_VIDEO_OUTPUT"},{"p":"com.google.android.exoplayer2","c":"C","l":"MSG_SET_VOLUME"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"MSG_SET_VOLUME"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"MSG_SET_WAKEUP_LISTENER"},{"p":"com.google.android.exoplayer2","c":"C","l":"msToUs(long)"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"multiRowAlignment"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.MultiSegmentBase","l":"MultiSegmentBase(RangedUri, long, long, long, long, List, long, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.dash.manifest.RangedUri,long,long,long,long,java.util.List,long,long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"MultiSegmentRepresentation(long, Format, String, SegmentBase.MultiSegmentBase, List)","url":"%3Cinit%3E(long,com.google.android.exoplayer2.Format,java.lang.String,com.google.android.exoplayer2.source.dash.manifest.SegmentBase.MultiSegmentBase,java.util.List)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.DrmConfiguration","l":"multiSession"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"muxedAudioFormat"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"muxedCaptionFormats"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil","l":"NAL_START_CODE"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"nalUnitLengthFieldLength"},{"p":"com.google.android.exoplayer2.video","c":"AvcConfig","l":"nalUnitLengthFieldLength"},{"p":"com.google.android.exoplayer2.video","c":"HevcConfig","l":"nalUnitLengthFieldLength"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"name"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"name"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry","l":"name"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Rendition","l":"name"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"name"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil.Attribute","l":"name"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil.Uniform","l":"name"},{"p":"com.google.android.exoplayer2","c":"C","l":"NANOS_PER_SECOND"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"NETWORK"},{"p":"com.google.android.exoplayer2","c":"C","l":"NETWORK_TYPE_2G"},{"p":"com.google.android.exoplayer2","c":"C","l":"NETWORK_TYPE_3G"},{"p":"com.google.android.exoplayer2","c":"C","l":"NETWORK_TYPE_4G"},{"p":"com.google.android.exoplayer2","c":"C","l":"NETWORK_TYPE_5G_NSA"},{"p":"com.google.android.exoplayer2","c":"C","l":"NETWORK_TYPE_5G_SA"},{"p":"com.google.android.exoplayer2","c":"C","l":"NETWORK_TYPE_CELLULAR_UNKNOWN"},{"p":"com.google.android.exoplayer2","c":"C","l":"NETWORK_TYPE_ETHERNET"},{"p":"com.google.android.exoplayer2","c":"C","l":"NETWORK_TYPE_OFFLINE"},{"p":"com.google.android.exoplayer2","c":"C","l":"NETWORK_TYPE_OTHER"},{"p":"com.google.android.exoplayer2","c":"C","l":"NETWORK_TYPE_UNKNOWN"},{"p":"com.google.android.exoplayer2","c":"C","l":"NETWORK_TYPE_WIFI"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"NETWORK_UNMETERED"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet","l":"newData(String)","url":"newData(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet","l":"newData(Uri)","url":"newData(android.net.Uri)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet","l":"newDefaultData()"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"newFormat"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"newInitializationChunk(DefaultDashChunkSource.RepresentationHolder, DataSource, Format, int, Object, RangedUri, RangedUri)","url":"newInitializationChunk(com.google.android.exoplayer2.source.dash.DefaultDashChunkSource.RepresentationHolder,com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.Format,int,java.lang.Object,com.google.android.exoplayer2.source.dash.manifest.RangedUri,com.google.android.exoplayer2.source.dash.manifest.RangedUri)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.SingleSegmentRepresentation","l":"newInstance(long, Format, String, long, long, long, long, List, String, long)","url":"newInstance(long,com.google.android.exoplayer2.Format,java.lang.String,long,long,long,long,java.util.List,java.lang.String,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"newInstance(long, Format, String, SegmentBase, List, String)","url":"newInstance(long,com.google.android.exoplayer2.Format,java.lang.String,com.google.android.exoplayer2.source.dash.manifest.SegmentBase,java.util.List,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"newInstance(long, Format, String, SegmentBase, List)","url":"newInstance(long,com.google.android.exoplayer2.Format,java.lang.String,com.google.android.exoplayer2.source.dash.manifest.SegmentBase,java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"newInstance(long, Format, String, SegmentBase)","url":"newInstance(long,com.google.android.exoplayer2.Format,java.lang.String,com.google.android.exoplayer2.source.dash.manifest.SegmentBase)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"newInstance(String, String, String, MediaCodecInfo.CodecCapabilities, boolean, boolean, boolean, boolean, boolean)","url":"newInstance(java.lang.String,java.lang.String,java.lang.String,android.media.MediaCodecInfo.CodecCapabilities,boolean,boolean,boolean,boolean,boolean)"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"newInstance(UUID)","url":"newInstance(java.util.UUID)"},{"p":"com.google.android.exoplayer2.video","c":"DummySurface","l":"newInstanceV17(Context, boolean)","url":"newInstanceV17(android.content.Context,boolean)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"newMediaChunk(DefaultDashChunkSource.RepresentationHolder, DataSource, int, Format, int, Object, long, int, long, long)","url":"newMediaChunk(com.google.android.exoplayer2.source.dash.DefaultDashChunkSource.RepresentationHolder,com.google.android.exoplayer2.upstream.DataSource,int,com.google.android.exoplayer2.Format,int,java.lang.Object,long,int,long,long)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"newNoDataInstance()"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler","l":"newPlayerTrackEmsgHandler()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"newSingleThreadExecutor(String)","url":"newSingleThreadExecutor(java.lang.String)"},{"p":"com.google.android.exoplayer2.drm","c":"OfflineLicenseHelper","l":"newWidevineInstance(String, boolean, HttpDataSource.Factory, DrmSessionEventListener.EventDispatcher)","url":"newWidevineInstance(java.lang.String,boolean,com.google.android.exoplayer2.upstream.HttpDataSource.Factory,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2.drm","c":"OfflineLicenseHelper","l":"newWidevineInstance(String, boolean, HttpDataSource.Factory, Map, DrmSessionEventListener.EventDispatcher)","url":"newWidevineInstance(java.lang.String,boolean,com.google.android.exoplayer2.upstream.HttpDataSource.Factory,java.util.Map,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2.drm","c":"OfflineLicenseHelper","l":"newWidevineInstance(String, HttpDataSource.Factory, DrmSessionEventListener.EventDispatcher)","url":"newWidevineInstance(java.lang.String,com.google.android.exoplayer2.upstream.HttpDataSource.Factory,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2","c":"SeekParameters","l":"NEXT_SYNC"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"next()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"next()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunkIterator","l":"next()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaChunkIterator","l":"next()"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"nextAdGroupIndex"},{"p":"com.google.android.exoplayer2.audio","c":"AuxEffectInfo","l":"NO_AUX_EFFECT_ID"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"Id3Decoder","l":"NO_FRAMES_PREDICATE"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.TimestampSearchResult","l":"NO_TIMESTAMP_IN_RANGE_RESULT"},{"p":"com.google.android.exoplayer2","c":"Format","l":"NO_VALUE"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"NONE"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"nonFatalErrorCount"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"nonFatalErrorHistory"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"NoOpCacheEvictor","l":"NoOpCacheEvictor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"normalizeLanguageCode(String)","url":"normalizeLanguageCode(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"normalizeMimeType(String)","url":"normalizeMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"normalizeUndeterminedLanguageToNull(String)","url":"normalizeUndeterminedLanguageToNull(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"NoSampleRenderer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CachedRegionTracker","l":"NOT_CACHED"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"NOT_IN_LOOKUP_TABLE"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor.AudioFormat","l":"NOT_SET"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl","l":"notifyRebuffer()"},{"p":"com.google.android.exoplayer2","c":"LivePlaybackSpeedControl","l":"notifyRebuffer()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"notifySeekStarted()"},{"p":"com.google.android.exoplayer2.testutil","c":"NoUidTimeline","l":"NoUidTimeline(Timeline)","url":"%3Cinit%3E(com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"nullSafeArrayAppend(T[], T)","url":"nullSafeArrayAppend(T[],T)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"nullSafeArrayConcatenation(T[], T[])","url":"nullSafeArrayConcatenation(T[],T[])"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"nullSafeArrayCopy(T[], int)","url":"nullSafeArrayCopy(T[],int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"nullSafeArrayCopyOfRange(T[], int, int)","url":"nullSafeArrayCopyOfRange(T[],int,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"nullSafeListToArray(List, T[])","url":"nullSafeListToArray(java.util.List,T[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorOutput","l":"numberOfTracks"},{"p":"com.google.android.exoplayer2.decoder","c":"CryptoInfo","l":"numBytesOfClearData"},{"p":"com.google.android.exoplayer2.decoder","c":"CryptoInfo","l":"numBytesOfEncryptedData"},{"p":"com.google.android.exoplayer2.decoder","c":"CryptoInfo","l":"numSubSamples"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"obtainMessage(int, int, int, Object)","url":"obtainMessage(int,int,int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"obtainMessage(int, int, int)","url":"obtainMessage(int,int,int)"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"obtainMessage(int, Object)","url":"obtainMessage(int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"obtainMessage(int)"},{"p":"com.google.android.exoplayer2.drm","c":"OfflineLicenseHelper","l":"OfflineLicenseHelper(DefaultDrmSessionManager, DrmSessionEventListener.EventDispatcher)","url":"%3Cinit%3E(com.google.android.exoplayer2.drm.DefaultDrmSessionManager,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2.drm","c":"OfflineLicenseHelper","l":"OfflineLicenseHelper(UUID, ExoMediaDrm.Provider, MediaDrmCallback, Map, DrmSessionEventListener.EventDispatcher)","url":"%3Cinit%3E(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm.Provider,com.google.android.exoplayer2.drm.MediaDrmCallback,java.util.Map,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"OFFLOAD_MODE_DISABLED"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"OFFLOAD_MODE_ENABLED_GAPLESS_NOT_REQUIRED"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"OFFLOAD_MODE_ENABLED_GAPLESS_REQUIRED"},{"p":"com.google.android.exoplayer2.upstream","c":"Allocation","l":"offset"},{"p":"com.google.android.exoplayer2","c":"Format","l":"OFFSET_SAMPLE_RELATIVE"},{"p":"com.google.android.exoplayer2.extractor","c":"ChunkIndex","l":"offsets"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"OGG"},{"p":"com.google.android.exoplayer2.extractor.ogg","c":"OggExtractor","l":"OggExtractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"OkHttpDataSource(Call.Factory, String, CacheControl, HttpDataSource.RequestProperties)","url":"%3Cinit%3E(okhttp3.Call.Factory,java.lang.String,okhttp3.CacheControl,com.google.android.exoplayer2.upstream.HttpDataSource.RequestProperties)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"OkHttpDataSource(Call.Factory, String)","url":"%3Cinit%3E(okhttp3.Call.Factory,java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"OkHttpDataSource(Call.Factory)","url":"%3Cinit%3E(okhttp3.Call.Factory)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSourceFactory","l":"OkHttpDataSourceFactory(Call.Factory, String, CacheControl)","url":"%3Cinit%3E(okhttp3.Call.Factory,java.lang.String,okhttp3.CacheControl)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSourceFactory","l":"OkHttpDataSourceFactory(Call.Factory, String, TransferListener, CacheControl)","url":"%3Cinit%3E(okhttp3.Call.Factory,java.lang.String,com.google.android.exoplayer2.upstream.TransferListener,okhttp3.CacheControl)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSourceFactory","l":"OkHttpDataSourceFactory(Call.Factory, String, TransferListener)","url":"%3Cinit%3E(okhttp3.Call.Factory,java.lang.String,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSourceFactory","l":"OkHttpDataSourceFactory(Call.Factory, String)","url":"%3Cinit%3E(okhttp3.Call.Factory,java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSourceFactory","l":"OkHttpDataSourceFactory(Call.Factory)","url":"%3Cinit%3E(okhttp3.Call.Factory)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"oldFormat"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Callback","l":"onActionScheduleFinished()"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"onActionScheduleFinished()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsLoader.EventListener","l":"onAdClicked()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.QueueEditor","l":"onAddQueueItem(Player, MediaDescriptionCompat, int)","url":"onAddQueueItem(com.google.android.exoplayer2.Player,android.support.v4.media.MediaDescriptionCompat,int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor","l":"onAddQueueItem(Player, MediaDescriptionCompat, int)","url":"onAddQueueItem(com.google.android.exoplayer2.Player,android.support.v4.media.MediaDescriptionCompat,int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.QueueEditor","l":"onAddQueueItem(Player, MediaDescriptionCompat)","url":"onAddQueueItem(com.google.android.exoplayer2.Player,android.support.v4.media.MediaDescriptionCompat)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor","l":"onAddQueueItem(Player, MediaDescriptionCompat)","url":"onAddQueueItem(com.google.android.exoplayer2.Player,android.support.v4.media.MediaDescriptionCompat)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsLoader.EventListener","l":"onAdLoadError(AdsMediaSource.AdLoadException, DataSpec)","url":"onAdLoadError(com.google.android.exoplayer2.source.ads.AdsMediaSource.AdLoadException,com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackSessionManager.Listener","l":"onAdPlaybackStarted(AnalyticsListener.EventTime, String, String)","url":"onAdPlaybackStarted(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"onAdPlaybackStarted(AnalyticsListener.EventTime, String, String)","url":"onAdPlaybackStarted(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsLoader.EventListener","l":"onAdPlaybackState(AdPlaybackState)","url":"onAdPlaybackState(com.google.android.exoplayer2.source.ads.AdPlaybackState)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsLoader.EventListener","l":"onAdTapped()"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout.AspectRatioListener","l":"onAspectRatioUpdated(float, float, boolean)","url":"onAspectRatioUpdated(float,float,boolean)"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"onAttachedToHost(PlaybackGlueHost)","url":"onAttachedToHost(androidx.leanback.media.PlaybackGlueHost)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"onAttachedToWindow()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"onAttachedToWindow()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioAttributesChanged(AnalyticsListener.EventTime, AudioAttributes)","url":"onAudioAttributesChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.audio.AudioAttributes)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onAudioAttributesChanged(AnalyticsListener.EventTime, AudioAttributes)","url":"onAudioAttributesChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.audio.AudioAttributes)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onAudioAttributesChanged(AudioAttributes)","url":"onAudioAttributesChanged(com.google.android.exoplayer2.audio.AudioAttributes)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onAudioAttributesChanged(AudioAttributes)","url":"onAudioAttributesChanged(com.google.android.exoplayer2.audio.AudioAttributes)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioListener","l":"onAudioAttributesChanged(AudioAttributes)","url":"onAudioAttributesChanged(com.google.android.exoplayer2.audio.AudioAttributes)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioCapabilitiesReceiver.Listener","l":"onAudioCapabilitiesChanged(AudioCapabilities)","url":"onAudioCapabilitiesChanged(com.google.android.exoplayer2.audio.AudioCapabilities)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioCodecError(AnalyticsListener.EventTime, Exception)","url":"onAudioCodecError(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onAudioCodecError(Exception)","url":"onAudioCodecError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener","l":"onAudioCodecError(Exception)","url":"onAudioCodecError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioDecoderInitialized(AnalyticsListener.EventTime, String, long, long)","url":"onAudioDecoderInitialized(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioDecoderInitialized(AnalyticsListener.EventTime, String, long)","url":"onAudioDecoderInitialized(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String,long)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onAudioDecoderInitialized(AnalyticsListener.EventTime, String, long)","url":"onAudioDecoderInitialized(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onAudioDecoderInitialized(String, long, long)","url":"onAudioDecoderInitialized(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener","l":"onAudioDecoderInitialized(String, long, long)","url":"onAudioDecoderInitialized(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioDecoderReleased(AnalyticsListener.EventTime, String)","url":"onAudioDecoderReleased(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onAudioDecoderReleased(AnalyticsListener.EventTime, String)","url":"onAudioDecoderReleased(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onAudioDecoderReleased(String)","url":"onAudioDecoderReleased(java.lang.String)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener","l":"onAudioDecoderReleased(String)","url":"onAudioDecoderReleased(java.lang.String)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioDisabled(AnalyticsListener.EventTime, DecoderCounters)","url":"onAudioDisabled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"onAudioDisabled(AnalyticsListener.EventTime, DecoderCounters)","url":"onAudioDisabled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onAudioDisabled(AnalyticsListener.EventTime, DecoderCounters)","url":"onAudioDisabled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onAudioDisabled(DecoderCounters)","url":"onAudioDisabled(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener","l":"onAudioDisabled(DecoderCounters)","url":"onAudioDisabled(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioEnabled(AnalyticsListener.EventTime, DecoderCounters)","url":"onAudioEnabled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onAudioEnabled(AnalyticsListener.EventTime, DecoderCounters)","url":"onAudioEnabled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onAudioEnabled(DecoderCounters)","url":"onAudioEnabled(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener","l":"onAudioEnabled(DecoderCounters)","url":"onAudioEnabled(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioInputFormatChanged(AnalyticsListener.EventTime, Format, DecoderReuseEvaluation)","url":"onAudioInputFormatChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.decoder.DecoderReuseEvaluation)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onAudioInputFormatChanged(AnalyticsListener.EventTime, Format, DecoderReuseEvaluation)","url":"onAudioInputFormatChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.decoder.DecoderReuseEvaluation)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioInputFormatChanged(AnalyticsListener.EventTime, Format)","url":"onAudioInputFormatChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onAudioInputFormatChanged(Format, DecoderReuseEvaluation)","url":"onAudioInputFormatChanged(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.decoder.DecoderReuseEvaluation)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener","l":"onAudioInputFormatChanged(Format, DecoderReuseEvaluation)","url":"onAudioInputFormatChanged(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.decoder.DecoderReuseEvaluation)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener","l":"onAudioInputFormatChanged(Format)","url":"onAudioInputFormatChanged(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioPositionAdvancing(AnalyticsListener.EventTime, long)","url":"onAudioPositionAdvancing(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onAudioPositionAdvancing(long)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener","l":"onAudioPositionAdvancing(long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioSessionIdChanged(AnalyticsListener.EventTime, int)","url":"onAudioSessionIdChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onAudioSessionIdChanged(AnalyticsListener.EventTime, int)","url":"onAudioSessionIdChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onAudioSessionIdChanged(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onAudioSessionIdChanged(int)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioListener","l":"onAudioSessionIdChanged(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioSinkError(AnalyticsListener.EventTime, Exception)","url":"onAudioSinkError(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onAudioSinkError(Exception)","url":"onAudioSinkError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener","l":"onAudioSinkError(Exception)","url":"onAudioSinkError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.Listener","l":"onAudioSinkError(Exception)","url":"onAudioSinkError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioUnderrun(AnalyticsListener.EventTime, int, long, long)","url":"onAudioUnderrun(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,long,long)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onAudioUnderrun(AnalyticsListener.EventTime, int, long, long)","url":"onAudioUnderrun(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,long,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onAudioUnderrun(int, long, long)","url":"onAudioUnderrun(int,long,long)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener","l":"onAudioUnderrun(int, long, long)","url":"onAudioUnderrun(int,long,long)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onAvailableCommandsChanged(Player.Commands)","url":"onAvailableCommandsChanged(com.google.android.exoplayer2.Player.Commands)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onAvailableCommandsChanged(Player.Commands)","url":"onAvailableCommandsChanged(com.google.android.exoplayer2.Player.Commands)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onBandwidthEstimate(AnalyticsListener.EventTime, int, long, long)","url":"onBandwidthEstimate(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,long,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"onBandwidthEstimate(AnalyticsListener.EventTime, int, long, long)","url":"onBandwidthEstimate(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,long,long)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onBandwidthEstimate(AnalyticsListener.EventTime, int, long, long)","url":"onBandwidthEstimate(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,long,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onBandwidthSample(int, long, long)","url":"onBandwidthSample(int,long,long)"},{"p":"com.google.android.exoplayer2.upstream","c":"BandwidthMeter.EventListener","l":"onBandwidthSample(int, long, long)","url":"onBandwidthSample(int,long,long)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"onBind(Intent)","url":"onBind(android.content.Intent)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.BitmapCallback","l":"onBitmap(Bitmap)","url":"onBitmap(android.graphics.Bitmap)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.FakeTransferListener","l":"onBytesTransferred(DataSource, DataSpec, boolean, int)","url":"onBytesTransferred(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"onBytesTransferred(DataSource, DataSpec, boolean, int)","url":"onBytesTransferred(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"TransferListener","l":"onBytesTransferred(DataSource, DataSpec, boolean, int)","url":"onBytesTransferred(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean,int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.EventListener","l":"onCachedBytesRead(long, long)","url":"onCachedBytesRead(long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.EventListener","l":"onCacheIgnored(int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheEvictor","l":"onCacheInitialized()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"LeastRecentlyUsedCacheEvictor","l":"onCacheInitialized()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"NoOpCacheEvictor","l":"onCacheInitialized()"},{"p":"com.google.android.exoplayer2.video.spherical","c":"CameraMotionListener","l":"onCameraMotion(long, float[])","url":"onCameraMotion(long,float[])"},{"p":"com.google.android.exoplayer2.video.spherical","c":"CameraMotionListener","l":"onCameraMotionReset()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"SessionAvailabilityListener","l":"onCastSessionAvailable()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"SessionAvailabilityListener","l":"onCastSessionUnavailable()"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"onChildSourceInfoRefreshed(ConcatenatingMediaSource.MediaSourceHolder, MediaSource, Timeline)","url":"onChildSourceInfoRefreshed(com.google.android.exoplayer2.source.ConcatenatingMediaSource.MediaSourceHolder,com.google.android.exoplayer2.source.MediaSource,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"onChildSourceInfoRefreshed(Integer, MediaSource, Timeline)","url":"onChildSourceInfoRefreshed(java.lang.Integer,com.google.android.exoplayer2.source.MediaSource,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource","l":"onChildSourceInfoRefreshed(MediaSource.MediaPeriodId, MediaSource, Timeline)","url":"onChildSourceInfoRefreshed(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.MediaSource,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"onChildSourceInfoRefreshed(T, MediaSource, Timeline)","url":"onChildSourceInfoRefreshed(T,com.google.android.exoplayer2.source.MediaSource,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource","l":"onChildSourceInfoRefreshed(Void, MediaSource, Timeline)","url":"onChildSourceInfoRefreshed(java.lang.Void,com.google.android.exoplayer2.source.MediaSource,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.source","c":"LoopingMediaSource","l":"onChildSourceInfoRefreshed(Void, MediaSource, Timeline)","url":"onChildSourceInfoRefreshed(java.lang.Void,com.google.android.exoplayer2.source.MediaSource,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource","l":"onChildSourceInfoRefreshed(Void, MediaSource, Timeline)","url":"onChildSourceInfoRefreshed(java.lang.Void,com.google.android.exoplayer2.source.MediaSource,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSource","l":"onChunkLoadCompleted(Chunk)","url":"onChunkLoadCompleted(com.google.android.exoplayer2.source.chunk.Chunk)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"onChunkLoadCompleted(Chunk)","url":"onChunkLoadCompleted(com.google.android.exoplayer2.source.chunk.Chunk)"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler.PlayerTrackEmsgHandler","l":"onChunkLoadCompleted(Chunk)","url":"onChunkLoadCompleted(com.google.android.exoplayer2.source.chunk.Chunk)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource","l":"onChunkLoadCompleted(Chunk)","url":"onChunkLoadCompleted(com.google.android.exoplayer2.source.chunk.Chunk)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource","l":"onChunkLoadCompleted(Chunk)","url":"onChunkLoadCompleted(com.google.android.exoplayer2.source.chunk.Chunk)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSource","l":"onChunkLoadError(Chunk, boolean, Exception, long)","url":"onChunkLoadError(com.google.android.exoplayer2.source.chunk.Chunk,boolean,java.lang.Exception,long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"onChunkLoadError(Chunk, boolean, Exception, long)","url":"onChunkLoadError(com.google.android.exoplayer2.source.chunk.Chunk,boolean,java.lang.Exception,long)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource","l":"onChunkLoadError(Chunk, boolean, Exception, long)","url":"onChunkLoadError(com.google.android.exoplayer2.source.chunk.Chunk,boolean,java.lang.Exception,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource","l":"onChunkLoadError(Chunk, boolean, Exception, long)","url":"onChunkLoadError(com.google.android.exoplayer2.source.chunk.Chunk,boolean,java.lang.Exception,long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler.PlayerTrackEmsgHandler","l":"onChunkLoadError(Chunk)","url":"onChunkLoadError(com.google.android.exoplayer2.source.chunk.Chunk)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource","l":"onClosed()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onCodecError(Exception)","url":"onCodecError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onCodecError(Exception)","url":"onCodecError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onCodecError(Exception)","url":"onCodecError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onCodecInitialized(String, long, long)","url":"onCodecInitialized(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onCodecInitialized(String, long, long)","url":"onCodecInitialized(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onCodecInitialized(String, long, long)","url":"onCodecInitialized(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onCodecReleased(String)","url":"onCodecReleased(java.lang.String)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onCodecReleased(String)","url":"onCodecReleased(java.lang.String)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onCodecReleased(String)","url":"onCodecReleased(java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.CommandReceiver","l":"onCommand(Player, ControlDispatcher, String, Bundle, ResultReceiver)","url":"onCommand(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ControlDispatcher,java.lang.String,android.os.Bundle,android.os.ResultReceiver)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor","l":"onCommand(Player, ControlDispatcher, String, Bundle, ResultReceiver)","url":"onCommand(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ControlDispatcher,java.lang.String,android.os.Bundle,android.os.ResultReceiver)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueNavigator","l":"onCommand(Player, ControlDispatcher, String, Bundle, ResultReceiver)","url":"onCommand(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ControlDispatcher,java.lang.String,android.os.Bundle,android.os.ResultReceiver)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.AllowedCommandProvider","l":"onCommandRequest(MediaSession, MediaSession.ControllerInfo, SessionCommand)","url":"onCommandRequest(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo,androidx.media2.session.SessionCommand)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.DefaultAllowedCommandProvider","l":"onCommandRequest(MediaSession, MediaSession.ControllerInfo, SessionCommand)","url":"onCommandRequest(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo,androidx.media2.session.SessionCommand)"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"onConfigure(AudioProcessor.AudioFormat)","url":"onConfigure(com.google.android.exoplayer2.audio.AudioProcessor.AudioFormat)"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"onConfigure(AudioProcessor.AudioFormat)","url":"onConfigure(com.google.android.exoplayer2.audio.AudioProcessor.AudioFormat)"},{"p":"com.google.android.exoplayer2.audio","c":"TeeAudioProcessor","l":"onConfigure(AudioProcessor.AudioFormat)","url":"onConfigure(com.google.android.exoplayer2.audio.AudioProcessor.AudioFormat)"},{"p":"com.google.android.exoplayer2.robolectric","c":"RandomizedMp3Decoder","l":"onConfigured(MediaFormat, Surface, MediaCrypto, int)","url":"onConfigured(android.media.MediaFormat,android.view.Surface,android.media.MediaCrypto,int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"onContentAspectRatioChanged(AspectRatioFrameLayout, float)","url":"onContentAspectRatioChanged(com.google.android.exoplayer2.ui.AspectRatioFrameLayout,float)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"onContentAspectRatioChanged(AspectRatioFrameLayout, float)","url":"onContentAspectRatioChanged(com.google.android.exoplayer2.ui.AspectRatioFrameLayout,float)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"onContinueLoadingRequested(ChunkSampleStream)","url":"onContinueLoadingRequested(com.google.android.exoplayer2.source.chunk.ChunkSampleStream)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"onContinueLoadingRequested(HlsSampleStreamWrapper)","url":"onContinueLoadingRequested(com.google.android.exoplayer2.source.hls.HlsSampleStreamWrapper)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"onContinueLoadingRequested(MediaPeriod)","url":"onContinueLoadingRequested(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"onContinueLoadingRequested(MediaPeriod)","url":"onContinueLoadingRequested(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source","c":"SequenceableLoader.Callback","l":"onContinueLoadingRequested(T)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"onCreate()"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity","l":"onCreate(Bundle)","url":"onCreate(android.os.Bundle)"},{"p":"com.google.android.exoplayer2.database","c":"ExoDatabaseProvider","l":"onCreate(SQLiteDatabase)","url":"onCreate(android.database.sqlite.SQLiteDatabase)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.MediaIdMediaItemProvider","l":"onCreateMediaItem(MediaSession, MediaSession.ControllerInfo, String)","url":"onCreateMediaItem(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo,java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.MediaItemProvider","l":"onCreateMediaItem(MediaSession, MediaSession.ControllerInfo, String)","url":"onCreateMediaItem(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onCues(List)","url":"onCues(java.util.List)"},{"p":"com.google.android.exoplayer2.text","c":"TextOutput","l":"onCues(List)","url":"onCues(java.util.List)"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"onCues(List)","url":"onCues(java.util.List)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.QueueNavigator","l":"onCurrentWindowIndexChanged(Player)","url":"onCurrentWindowIndexChanged(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueNavigator","l":"onCurrentWindowIndexChanged(Player)","url":"onCurrentWindowIndexChanged(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.CustomActionProvider","l":"onCustomAction(Player, ControlDispatcher, String, Bundle)","url":"onCustomAction(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ControlDispatcher,java.lang.String,android.os.Bundle)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"RepeatModeActionProvider","l":"onCustomAction(Player, ControlDispatcher, String, Bundle)","url":"onCustomAction(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ControlDispatcher,java.lang.String,android.os.Bundle)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.CustomActionReceiver","l":"onCustomAction(Player, String, Intent)","url":"onCustomAction(com.google.android.exoplayer2.Player,java.lang.String,android.content.Intent)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.CustomCommandProvider","l":"onCustomCommand(MediaSession, MediaSession.ControllerInfo, SessionCommand, Bundle)","url":"onCustomCommand(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo,androidx.media2.session.SessionCommand,android.os.Bundle)"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler.PlayerEmsgCallback","l":"onDashManifestPublishTimeExpired(long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler.PlayerEmsgCallback","l":"onDashManifestRefreshRequested()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource","l":"onDataRead(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDecoderDisabled(AnalyticsListener.EventTime, int, DecoderCounters)","url":"onDecoderDisabled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDecoderEnabled(AnalyticsListener.EventTime, int, DecoderCounters)","url":"onDecoderEnabled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDecoderInitialized(AnalyticsListener.EventTime, int, String, long)","url":"onDecoderInitialized(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,java.lang.String,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDecoderInputFormatChanged(AnalyticsListener.EventTime, int, Format)","url":"onDecoderInputFormatChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"onDestroy()"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"onDetachedFromHost()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"onDetachedFromWindow()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"onDetachedFromWindow()"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView","l":"onDetachedFromWindow()"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onDeviceInfoChanged(DeviceInfo)","url":"onDeviceInfoChanged(com.google.android.exoplayer2.device.DeviceInfo)"},{"p":"com.google.android.exoplayer2.device","c":"DeviceListener","l":"onDeviceInfoChanged(DeviceInfo)","url":"onDeviceInfoChanged(com.google.android.exoplayer2.device.DeviceInfo)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onDeviceVolumeChanged(int, boolean)","url":"onDeviceVolumeChanged(int,boolean)"},{"p":"com.google.android.exoplayer2.device","c":"DeviceListener","l":"onDeviceVolumeChanged(int, boolean)","url":"onDeviceVolumeChanged(int,boolean)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAudioRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeVideoRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.text","c":"TextRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.video","c":"VideoFrameReleaseHelper","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.video.spherical","c":"CameraMotionRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.DisconnectedCallback","l":"onDisconnected(MediaSession, MediaSession.ControllerInfo)","url":"onDisconnected(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo)"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"onDiscontinuity()"},{"p":"com.google.android.exoplayer2.database","c":"ExoDatabaseProvider","l":"onDowngrade(SQLiteDatabase, int, int)","url":"onDowngrade(android.database.sqlite.SQLiteDatabase,int,int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"onDownloadChanged(Download)","url":"onDownloadChanged(com.google.android.exoplayer2.offline.Download)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager.Listener","l":"onDownloadChanged(DownloadManager, Download, Exception)","url":"onDownloadChanged(com.google.android.exoplayer2.offline.DownloadManager,com.google.android.exoplayer2.offline.Download,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestDownloadManagerListener","l":"onDownloadChanged(DownloadManager, Download, Exception)","url":"onDownloadChanged(com.google.android.exoplayer2.offline.DownloadManager,com.google.android.exoplayer2.offline.Download,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"onDownloadRemoved(Download)","url":"onDownloadRemoved(com.google.android.exoplayer2.offline.Download)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager.Listener","l":"onDownloadRemoved(DownloadManager, Download)","url":"onDownloadRemoved(com.google.android.exoplayer2.offline.DownloadManager,com.google.android.exoplayer2.offline.Download)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestDownloadManagerListener","l":"onDownloadRemoved(DownloadManager, Download)","url":"onDownloadRemoved(com.google.android.exoplayer2.offline.DownloadManager,com.google.android.exoplayer2.offline.Download)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager.Listener","l":"onDownloadsPausedChanged(DownloadManager, boolean)","url":"onDownloadsPausedChanged(com.google.android.exoplayer2.offline.DownloadManager,boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDownstreamFormatChanged(AnalyticsListener.EventTime, MediaLoadData)","url":"onDownstreamFormatChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"onDownstreamFormatChanged(AnalyticsListener.EventTime, MediaLoadData)","url":"onDownstreamFormatChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onDownstreamFormatChanged(AnalyticsListener.EventTime, MediaLoadData)","url":"onDownstreamFormatChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onDownstreamFormatChanged(int, MediaSource.MediaPeriodId, MediaLoadData)","url":"onDownstreamFormatChanged(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener","l":"onDownstreamFormatChanged(int, MediaSource.MediaPeriodId, MediaLoadData)","url":"onDownstreamFormatChanged(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"onDraw(Canvas)","url":"onDraw(android.graphics.Canvas)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDrmKeysLoaded(AnalyticsListener.EventTime)","url":"onDrmKeysLoaded(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onDrmKeysLoaded(AnalyticsListener.EventTime)","url":"onDrmKeysLoaded(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onDrmKeysLoaded(int, MediaSource.MediaPeriodId)","url":"onDrmKeysLoaded(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener","l":"onDrmKeysLoaded(int, MediaSource.MediaPeriodId)","url":"onDrmKeysLoaded(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDrmKeysRemoved(AnalyticsListener.EventTime)","url":"onDrmKeysRemoved(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onDrmKeysRemoved(AnalyticsListener.EventTime)","url":"onDrmKeysRemoved(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onDrmKeysRemoved(int, MediaSource.MediaPeriodId)","url":"onDrmKeysRemoved(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener","l":"onDrmKeysRemoved(int, MediaSource.MediaPeriodId)","url":"onDrmKeysRemoved(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDrmKeysRestored(AnalyticsListener.EventTime)","url":"onDrmKeysRestored(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onDrmKeysRestored(AnalyticsListener.EventTime)","url":"onDrmKeysRestored(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onDrmKeysRestored(int, MediaSource.MediaPeriodId)","url":"onDrmKeysRestored(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener","l":"onDrmKeysRestored(int, MediaSource.MediaPeriodId)","url":"onDrmKeysRestored(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDrmSessionAcquired(AnalyticsListener.EventTime, int)","url":"onDrmSessionAcquired(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onDrmSessionAcquired(AnalyticsListener.EventTime, int)","url":"onDrmSessionAcquired(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDrmSessionAcquired(AnalyticsListener.EventTime)","url":"onDrmSessionAcquired(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onDrmSessionAcquired(int, MediaSource.MediaPeriodId, int)","url":"onDrmSessionAcquired(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,int)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener","l":"onDrmSessionAcquired(int, MediaSource.MediaPeriodId, int)","url":"onDrmSessionAcquired(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,int)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener","l":"onDrmSessionAcquired(int, MediaSource.MediaPeriodId)","url":"onDrmSessionAcquired(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDrmSessionManagerError(AnalyticsListener.EventTime, Exception)","url":"onDrmSessionManagerError(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"onDrmSessionManagerError(AnalyticsListener.EventTime, Exception)","url":"onDrmSessionManagerError(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onDrmSessionManagerError(AnalyticsListener.EventTime, Exception)","url":"onDrmSessionManagerError(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onDrmSessionManagerError(int, MediaSource.MediaPeriodId, Exception)","url":"onDrmSessionManagerError(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener","l":"onDrmSessionManagerError(int, MediaSource.MediaPeriodId, Exception)","url":"onDrmSessionManagerError(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDrmSessionReleased(AnalyticsListener.EventTime)","url":"onDrmSessionReleased(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onDrmSessionReleased(AnalyticsListener.EventTime)","url":"onDrmSessionReleased(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onDrmSessionReleased(int, MediaSource.MediaPeriodId)","url":"onDrmSessionReleased(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener","l":"onDrmSessionReleased(int, MediaSource.MediaPeriodId)","url":"onDrmSessionReleased(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onDroppedFrames(int, long)","url":"onDroppedFrames(int,long)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener","l":"onDroppedFrames(int, long)","url":"onDroppedFrames(int,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDroppedVideoFrames(AnalyticsListener.EventTime, int, long)","url":"onDroppedVideoFrames(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"onDroppedVideoFrames(AnalyticsListener.EventTime, int, long)","url":"onDroppedVideoFrames(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,long)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onDroppedVideoFrames(AnalyticsListener.EventTime, int, long)","url":"onDroppedVideoFrames(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream.FakeSampleStreamItem","l":"oneByteSample(long, int)","url":"oneByteSample(long,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream.FakeSampleStreamItem","l":"oneByteSample(long)"},{"p":"com.google.android.exoplayer2.video","c":"VideoFrameReleaseHelper","l":"onEnabled()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"onEnabled(boolean, boolean)","url":"onEnabled(boolean,boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"onEnabled(boolean, boolean)","url":"onEnabled(boolean,boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onEnabled(boolean, boolean)","url":"onEnabled(boolean,boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onEnabled(boolean, boolean)","url":"onEnabled(boolean,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAudioRenderer","l":"onEnabled(boolean, boolean)","url":"onEnabled(boolean,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeVideoRenderer","l":"onEnabled(boolean, boolean)","url":"onEnabled(boolean,boolean)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"onEnabled(boolean, boolean)","url":"onEnabled(boolean,boolean)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onEnabled(boolean, boolean)","url":"onEnabled(boolean,boolean)"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"onEnabled(boolean)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.OnEventListener","l":"onEvent(ExoMediaDrm, byte[], int, int, byte[])","url":"onEvent(com.google.android.exoplayer2.drm.ExoMediaDrm,byte[],int,int,byte[])"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onEvents(Player, AnalyticsListener.Events)","url":"onEvents(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.analytics.AnalyticsListener.Events)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"onEvents(Player, AnalyticsListener.Events)","url":"onEvents(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.analytics.AnalyticsListener.Events)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"onEvents(Player, AnalyticsListener.Events)","url":"onEvents(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.analytics.AnalyticsListener.Events)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onEvents(Player, Player.Events)","url":"onEvents(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.Player.Events)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onEvents(Player, Player.Events)","url":"onEvents(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.Player.Events)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioOffloadListener","l":"onExperimentalOffloadSchedulingEnabledChanged(boolean)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioOffloadListener","l":"onExperimentalSleepingForOffloadChanged(boolean)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.OnExpirationUpdateListener","l":"onExpirationUpdate(ExoMediaDrm, byte[], long)","url":"onExpirationUpdate(com.google.android.exoplayer2.drm.ExoMediaDrm,byte[],long)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"onFinished()"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity.HostedTest","l":"onFinished()"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"onFlush()"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"onFlush()"},{"p":"com.google.android.exoplayer2.audio","c":"TeeAudioProcessor","l":"onFlush()"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"onFocusChanged(boolean, int, Rect)","url":"onFocusChanged(boolean,int,android.graphics.Rect)"},{"p":"com.google.android.exoplayer2.video","c":"VideoFrameReleaseHelper","l":"onFormatChanged(float)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAudioRenderer","l":"onFormatChanged(Format)","url":"onFormatChanged(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"onFormatChanged(Format)","url":"onFormatChanged(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeVideoRenderer","l":"onFormatChanged(Format)","url":"onFormatChanged(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.util","c":"EGLSurfaceTexture.TextureImageListener","l":"onFrameAvailable()"},{"p":"com.google.android.exoplayer2.util","c":"EGLSurfaceTexture","l":"onFrameAvailable(SurfaceTexture)","url":"onFrameAvailable(android.graphics.SurfaceTexture)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter.OnFrameRenderedListener","l":"onFrameRendered(MediaCodecAdapter, long, long)","url":"onFrameRendered(com.google.android.exoplayer2.mediacodec.MediaCodecAdapter,long,long)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView.OnFullScreenModeChangedListener","l":"onFullScreenModeChanged(boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager.Listener","l":"onIdle(DownloadManager)","url":"onIdle(com.google.android.exoplayer2.offline.DownloadManager)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestDownloadManagerListener","l":"onIdle(DownloadManager)","url":"onIdle(com.google.android.exoplayer2.offline.DownloadManager)"},{"p":"com.google.android.exoplayer2.util","c":"SntpClient.InitializationCallback","l":"onInitializationFailed(IOException)","url":"onInitializationFailed(java.io.IOException)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"onInitializeAccessibilityEvent(AccessibilityEvent)","url":"onInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)","url":"onInitializeAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo)"},{"p":"com.google.android.exoplayer2.util","c":"SntpClient.InitializationCallback","l":"onInitialized()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager.Listener","l":"onInitialized(DownloadManager)","url":"onInitialized(com.google.android.exoplayer2.offline.DownloadManager)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestDownloadManagerListener","l":"onInitialized(DownloadManager)","url":"onInitialized(com.google.android.exoplayer2.offline.DownloadManager)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onInputFormatChanged(FormatHolder)","url":"onInputFormatChanged(com.google.android.exoplayer2.FormatHolder)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onInputFormatChanged(FormatHolder)","url":"onInputFormatChanged(com.google.android.exoplayer2.FormatHolder)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"onInputFormatChanged(FormatHolder)","url":"onInputFormatChanged(com.google.android.exoplayer2.FormatHolder)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onInputFormatChanged(FormatHolder)","url":"onInputFormatChanged(com.google.android.exoplayer2.FormatHolder)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onIsLoadingChanged(AnalyticsListener.EventTime, boolean)","url":"onIsLoadingChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onIsLoadingChanged(AnalyticsListener.EventTime, boolean)","url":"onIsLoadingChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,boolean)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onIsLoadingChanged(boolean)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onIsLoadingChanged(boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onIsLoadingChanged(boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onIsPlayingChanged(AnalyticsListener.EventTime, boolean)","url":"onIsPlayingChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onIsPlayingChanged(AnalyticsListener.EventTime, boolean)","url":"onIsPlayingChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,boolean)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onIsPlayingChanged(boolean)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onIsPlayingChanged(boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onIsPlayingChanged(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"onKeyDown(int, KeyEvent)","url":"onKeyDown(int,android.view.KeyEvent)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.OnKeyStatusChangeListener","l":"onKeyStatusChange(ExoMediaDrm, byte[], List, boolean)","url":"onKeyStatusChange(com.google.android.exoplayer2.drm.ExoMediaDrm,byte[],java.util.List,boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"onLayout(boolean, int, int, int, int)","url":"onLayout(boolean,int,int,int,int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"onLayout(boolean, int, int, int, int)","url":"onLayout(boolean,int,int,int,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onLoadCanceled(AnalyticsListener.EventTime, LoadEventInfo, MediaLoadData)","url":"onLoadCanceled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onLoadCanceled(AnalyticsListener.EventTime, LoadEventInfo, MediaLoadData)","url":"onLoadCanceled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"onLoadCanceled(Chunk, long, long, boolean)","url":"onLoadCanceled(com.google.android.exoplayer2.source.chunk.Chunk,long,long,boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onLoadCanceled(int, MediaSource.MediaPeriodId, LoadEventInfo, MediaLoadData)","url":"onLoadCanceled(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener","l":"onLoadCanceled(int, MediaSource.MediaPeriodId, LoadEventInfo, MediaLoadData)","url":"onLoadCanceled(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"onLoadCanceled(ParsingLoadable, long, long, boolean)","url":"onLoadCanceled(com.google.android.exoplayer2.upstream.ParsingLoadable,long,long,boolean)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource","l":"onLoadCanceled(ParsingLoadable, long, long, boolean)","url":"onLoadCanceled(com.google.android.exoplayer2.upstream.ParsingLoadable,long,long,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader.Callback","l":"onLoadCanceled(T, long, long, boolean)","url":"onLoadCanceled(T,long,long,boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onLoadCompleted(AnalyticsListener.EventTime, LoadEventInfo, MediaLoadData)","url":"onLoadCompleted(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onLoadCompleted(AnalyticsListener.EventTime, LoadEventInfo, MediaLoadData)","url":"onLoadCompleted(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"onLoadCompleted(Chunk, long, long)","url":"onLoadCompleted(com.google.android.exoplayer2.source.chunk.Chunk,long,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onLoadCompleted(int, MediaSource.MediaPeriodId, LoadEventInfo, MediaLoadData)","url":"onLoadCompleted(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener","l":"onLoadCompleted(int, MediaSource.MediaPeriodId, LoadEventInfo, MediaLoadData)","url":"onLoadCompleted(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"onLoadCompleted(ParsingLoadable, long, long)","url":"onLoadCompleted(com.google.android.exoplayer2.upstream.ParsingLoadable,long,long)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource","l":"onLoadCompleted(ParsingLoadable, long, long)","url":"onLoadCompleted(com.google.android.exoplayer2.upstream.ParsingLoadable,long,long)"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader.Callback","l":"onLoadCompleted(T, long, long)","url":"onLoadCompleted(T,long,long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"onLoaderReleased()"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader.ReleaseCallback","l":"onLoaderReleased()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onLoadError(AnalyticsListener.EventTime, LoadEventInfo, MediaLoadData, IOException, boolean)","url":"onLoadError(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData,java.io.IOException,boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"onLoadError(AnalyticsListener.EventTime, LoadEventInfo, MediaLoadData, IOException, boolean)","url":"onLoadError(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData,java.io.IOException,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onLoadError(AnalyticsListener.EventTime, LoadEventInfo, MediaLoadData, IOException, boolean)","url":"onLoadError(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData,java.io.IOException,boolean)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"onLoadError(Chunk, long, long, IOException, int)","url":"onLoadError(com.google.android.exoplayer2.source.chunk.Chunk,long,long,java.io.IOException,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onLoadError(int, MediaSource.MediaPeriodId, LoadEventInfo, MediaLoadData, IOException, boolean)","url":"onLoadError(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData,java.io.IOException,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener","l":"onLoadError(int, MediaSource.MediaPeriodId, LoadEventInfo, MediaLoadData, IOException, boolean)","url":"onLoadError(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData,java.io.IOException,boolean)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"onLoadError(ParsingLoadable, long, long, IOException, int)","url":"onLoadError(com.google.android.exoplayer2.upstream.ParsingLoadable,long,long,java.io.IOException,int)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource","l":"onLoadError(ParsingLoadable, long, long, IOException, int)","url":"onLoadError(com.google.android.exoplayer2.upstream.ParsingLoadable,long,long,java.io.IOException,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader.Callback","l":"onLoadError(T, long, long, IOException, int)","url":"onLoadError(T,long,long,java.io.IOException,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onLoadingChanged(AnalyticsListener.EventTime, boolean)","url":"onLoadingChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,boolean)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onLoadingChanged(boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onLoadStarted(AnalyticsListener.EventTime, LoadEventInfo, MediaLoadData)","url":"onLoadStarted(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onLoadStarted(AnalyticsListener.EventTime, LoadEventInfo, MediaLoadData)","url":"onLoadStarted(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onLoadStarted(int, MediaSource.MediaPeriodId, LoadEventInfo, MediaLoadData)","url":"onLoadStarted(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener","l":"onLoadStarted(int, MediaSource.MediaPeriodId, LoadEventInfo, MediaLoadData)","url":"onLoadStarted(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy","l":"onLoadTaskConcluded(long)"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout","l":"onMeasure(int, int)","url":"onMeasure(int,int)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"onMeasure(int, int)","url":"onMeasure(int,int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.MediaButtonEventHandler","l":"onMediaButtonEvent(Player, ControlDispatcher, Intent)","url":"onMediaButtonEvent(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ControlDispatcher,android.content.Intent)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onMediaItemTransition(AnalyticsListener.EventTime, MediaItem, int)","url":"onMediaItemTransition(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.MediaItem,int)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onMediaItemTransition(AnalyticsListener.EventTime, MediaItem, int)","url":"onMediaItemTransition(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.MediaItem,int)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onMediaItemTransition(MediaItem, int)","url":"onMediaItemTransition(com.google.android.exoplayer2.MediaItem,int)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onMediaItemTransition(MediaItem, int)","url":"onMediaItemTransition(com.google.android.exoplayer2.MediaItem,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onMediaItemTransition(MediaItem, int)","url":"onMediaItemTransition(com.google.android.exoplayer2.MediaItem,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"onMediaItemTransition(MediaItem, int)","url":"onMediaItemTransition(com.google.android.exoplayer2.MediaItem,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onMediaMetadataChanged(AnalyticsListener.EventTime, MediaMetadata)","url":"onMediaMetadataChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.MediaMetadata)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onMediaMetadataChanged(MediaMetadata)","url":"onMediaMetadataChanged(com.google.android.exoplayer2.MediaMetadata)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onMediaMetadataChanged(MediaMetadata)","url":"onMediaMetadataChanged(com.google.android.exoplayer2.MediaMetadata)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onMediaMetadataChanged(MediaMetadata)","url":"onMediaMetadataChanged(com.google.android.exoplayer2.MediaMetadata)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.PlayerTarget.Callback","l":"onMessageArrived()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onMetadata(AnalyticsListener.EventTime, Metadata)","url":"onMetadata(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onMetadata(AnalyticsListener.EventTime, Metadata)","url":"onMetadata(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onMetadata(Metadata)","url":"onMetadata(com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onMetadata(Metadata)","url":"onMetadata(com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataOutput","l":"onMetadata(Metadata)","url":"onMetadata(com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2.util","c":"NetworkTypeObserver.Listener","l":"onNetworkTypeChanged(int)"},{"p":"com.google.android.exoplayer2.video","c":"VideoFrameReleaseHelper","l":"onNextFrame(long)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.NotificationListener","l":"onNotificationCancelled(int, boolean)","url":"onNotificationCancelled(int,boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.NotificationListener","l":"onNotificationPosted(int, Notification, boolean)","url":"onNotificationPosted(int,android.app.Notification,boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.Listener","l":"onOffloadBufferEmptying()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.Listener","l":"onOffloadBufferFull(long)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onOutputFormatChanged(Format, MediaFormat)","url":"onOutputFormatChanged(com.google.android.exoplayer2.Format,android.media.MediaFormat)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onOutputFormatChanged(Format, MediaFormat)","url":"onOutputFormatChanged(com.google.android.exoplayer2.Format,android.media.MediaFormat)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onOutputFormatChanged(Format, MediaFormat)","url":"onOutputFormatChanged(com.google.android.exoplayer2.Format,android.media.MediaFormat)"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity","l":"onPause()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"onPause()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"onPause()"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView","l":"onPause()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onPlaybackParametersChanged(AnalyticsListener.EventTime, PlaybackParameters)","url":"onPlaybackParametersChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onPlaybackParametersChanged(AnalyticsListener.EventTime, PlaybackParameters)","url":"onPlaybackParametersChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onPlaybackParametersChanged(PlaybackParameters)","url":"onPlaybackParametersChanged(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onPlaybackParametersChanged(PlaybackParameters)","url":"onPlaybackParametersChanged(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onPlaybackParametersChanged(PlaybackParameters)","url":"onPlaybackParametersChanged(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"onPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"onPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"onPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"onPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2.video","c":"VideoFrameReleaseHelper","l":"onPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onPlaybackStateChanged(AnalyticsListener.EventTime, int)","url":"onPlaybackStateChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onPlaybackStateChanged(AnalyticsListener.EventTime, int)","url":"onPlaybackStateChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onPlaybackStateChanged(int)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onPlaybackStateChanged(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onPlaybackStateChanged(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"onPlaybackStateChanged(int)"},{"p":"com.google.android.exoplayer2.util","c":"DebugTextViewHelper","l":"onPlaybackStateChanged(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener.Callback","l":"onPlaybackStatsReady(AnalyticsListener.EventTime, PlaybackStats)","url":"onPlaybackStatsReady(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.analytics.PlaybackStats)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onPlaybackSuppressionReasonChanged(AnalyticsListener.EventTime, int)","url":"onPlaybackSuppressionReasonChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onPlaybackSuppressionReasonChanged(AnalyticsListener.EventTime, int)","url":"onPlaybackSuppressionReasonChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onPlaybackSuppressionReasonChanged(int)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onPlaybackSuppressionReasonChanged(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onPlaybackSuppressionReasonChanged(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onPlayerError(AnalyticsListener.EventTime, ExoPlaybackException)","url":"onPlayerError(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.ExoPlaybackException)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onPlayerError(AnalyticsListener.EventTime, ExoPlaybackException)","url":"onPlayerError(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.ExoPlaybackException)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onPlayerError(ExoPlaybackException)","url":"onPlayerError(com.google.android.exoplayer2.ExoPlaybackException)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onPlayerError(ExoPlaybackException)","url":"onPlayerError(com.google.android.exoplayer2.ExoPlaybackException)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onPlayerError(ExoPlaybackException)","url":"onPlayerError(com.google.android.exoplayer2.ExoPlaybackException)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"onPlayerError(ExoPlaybackException)","url":"onPlayerError(com.google.android.exoplayer2.ExoPlaybackException)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"onPlayerErrorInternal(ExoPlaybackException)","url":"onPlayerErrorInternal(com.google.android.exoplayer2.ExoPlaybackException)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onPlayerReleased(AnalyticsListener.EventTime)","url":"onPlayerReleased(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onPlayerStateChanged(AnalyticsListener.EventTime, boolean, int)","url":"onPlayerStateChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,boolean,int)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onPlayerStateChanged(boolean, int)","url":"onPlayerStateChanged(boolean,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onPlayerStateChanged(boolean, int)","url":"onPlayerStateChanged(boolean,int)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"onPlaylistChanged()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker.PlaylistEventListener","l":"onPlaylistChanged()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"onPlaylistError(Uri, long)","url":"onPlaylistError(android.net.Uri,long)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker.PlaylistEventListener","l":"onPlaylistError(Uri, long)","url":"onPlaylistError(android.net.Uri,long)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"onPlaylistRefreshRequired(Uri)","url":"onPlaylistRefreshRequired(android.net.Uri)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onPlayWhenReadyChanged(AnalyticsListener.EventTime, boolean, int)","url":"onPlayWhenReadyChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,boolean,int)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onPlayWhenReadyChanged(AnalyticsListener.EventTime, boolean, int)","url":"onPlayWhenReadyChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,boolean,int)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onPlayWhenReadyChanged(boolean, int)","url":"onPlayWhenReadyChanged(boolean,int)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onPlayWhenReadyChanged(boolean, int)","url":"onPlayWhenReadyChanged(boolean,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onPlayWhenReadyChanged(boolean, int)","url":"onPlayWhenReadyChanged(boolean,int)"},{"p":"com.google.android.exoplayer2.util","c":"DebugTextViewHelper","l":"onPlayWhenReadyChanged(boolean, int)","url":"onPlayWhenReadyChanged(boolean,int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"onPlayWhenReadyChanged(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.Listener","l":"onPositionAdvancing(long)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.Listener","l":"onPositionDiscontinuity()"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"onPositionDiscontinuity()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onPositionDiscontinuity()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onPositionDiscontinuity(AnalyticsListener.EventTime, int)","url":"onPositionDiscontinuity(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onPositionDiscontinuity(AnalyticsListener.EventTime, Player.PositionInfo, Player.PositionInfo, int)","url":"onPositionDiscontinuity(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.Player.PositionInfo,com.google.android.exoplayer2.Player.PositionInfo,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"onPositionDiscontinuity(AnalyticsListener.EventTime, Player.PositionInfo, Player.PositionInfo, int)","url":"onPositionDiscontinuity(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.Player.PositionInfo,com.google.android.exoplayer2.Player.PositionInfo,int)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onPositionDiscontinuity(AnalyticsListener.EventTime, Player.PositionInfo, Player.PositionInfo, int)","url":"onPositionDiscontinuity(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.Player.PositionInfo,com.google.android.exoplayer2.Player.PositionInfo,int)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onPositionDiscontinuity(int)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onPositionDiscontinuity(Player.PositionInfo, Player.PositionInfo, int)","url":"onPositionDiscontinuity(com.google.android.exoplayer2.Player.PositionInfo,com.google.android.exoplayer2.Player.PositionInfo,int)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onPositionDiscontinuity(Player.PositionInfo, Player.PositionInfo, int)","url":"onPositionDiscontinuity(com.google.android.exoplayer2.Player.PositionInfo,com.google.android.exoplayer2.Player.PositionInfo,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onPositionDiscontinuity(Player.PositionInfo, Player.PositionInfo, int)","url":"onPositionDiscontinuity(com.google.android.exoplayer2.Player.PositionInfo,com.google.android.exoplayer2.Player.PositionInfo,int)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"onPositionDiscontinuity(Player.PositionInfo, Player.PositionInfo, int)","url":"onPositionDiscontinuity(com.google.android.exoplayer2.Player.PositionInfo,com.google.android.exoplayer2.Player.PositionInfo,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"onPositionDiscontinuity(Player.PositionInfo, Player.PositionInfo, int)","url":"onPositionDiscontinuity(com.google.android.exoplayer2.Player.PositionInfo,com.google.android.exoplayer2.Player.PositionInfo,int)"},{"p":"com.google.android.exoplayer2.util","c":"DebugTextViewHelper","l":"onPositionDiscontinuity(Player.PositionInfo, Player.PositionInfo, int)","url":"onPositionDiscontinuity(com.google.android.exoplayer2.Player.PositionInfo,com.google.android.exoplayer2.Player.PositionInfo,int)"},{"p":"com.google.android.exoplayer2.video","c":"VideoFrameReleaseHelper","l":"onPositionReset()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"onPositionReset(long, boolean)","url":"onPositionReset(long,boolean)"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"onPositionReset(long, boolean)","url":"onPositionReset(long,boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"onPositionReset(long, boolean)","url":"onPositionReset(long,boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onPositionReset(long, boolean)","url":"onPositionReset(long,boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onPositionReset(long, boolean)","url":"onPositionReset(long,boolean)"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataRenderer","l":"onPositionReset(long, boolean)","url":"onPositionReset(long,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"onPositionReset(long, boolean)","url":"onPositionReset(long,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeVideoRenderer","l":"onPositionReset(long, boolean)","url":"onPositionReset(long,boolean)"},{"p":"com.google.android.exoplayer2.text","c":"TextRenderer","l":"onPositionReset(long, boolean)","url":"onPositionReset(long,boolean)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"onPositionReset(long, boolean)","url":"onPositionReset(long,boolean)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onPositionReset(long, boolean)","url":"onPositionReset(long,boolean)"},{"p":"com.google.android.exoplayer2.video.spherical","c":"CameraMotionRenderer","l":"onPositionReset(long, boolean)","url":"onPositionReset(long,boolean)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.PostConnectCallback","l":"onPostConnect(MediaSession, MediaSession.ControllerInfo)","url":"onPostConnect(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.PlaybackPreparer","l":"onPrepare(boolean)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod.PrepareListener","l":"onPrepareComplete(MediaSource.MediaPeriodId)","url":"onPrepareComplete(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"onPrepared()"},{"p":"com.google.android.exoplayer2","c":"LoadControl","l":"onPrepared()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"onPrepared()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper.Callback","l":"onPrepared(DownloadHelper)","url":"onPrepared(com.google.android.exoplayer2.offline.DownloadHelper)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"onPrepared(MediaPeriod)","url":"onPrepared(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"onPrepared(MediaPeriod)","url":"onPrepared(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod.Callback","l":"onPrepared(MediaPeriod)","url":"onPrepared(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper.Callback","l":"onPrepareError(DownloadHelper, IOException)","url":"onPrepareError(com.google.android.exoplayer2.offline.DownloadHelper,java.io.IOException)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod.PrepareListener","l":"onPrepareError(MediaSource.MediaPeriodId, IOException)","url":"onPrepareError(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,java.io.IOException)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.PlaybackPreparer","l":"onPrepareFromMediaId(String, boolean, Bundle)","url":"onPrepareFromMediaId(java.lang.String,boolean,android.os.Bundle)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.PlaybackPreparer","l":"onPrepareFromSearch(String, boolean, Bundle)","url":"onPrepareFromSearch(java.lang.String,boolean,android.os.Bundle)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.PlaybackPreparer","l":"onPrepareFromUri(Uri, boolean, Bundle)","url":"onPrepareFromUri(android.net.Uri,boolean,android.os.Bundle)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource","l":"onPrimaryPlaylistRefreshed(HlsMediaPlaylist)","url":"onPrimaryPlaylistRefreshed(com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker.PrimaryPlaylistListener","l":"onPrimaryPlaylistRefreshed(HlsMediaPlaylist)","url":"onPrimaryPlaylistRefreshed(com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onProcessedOutputBuffer(long)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"onProcessedOutputBuffer(long)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onProcessedOutputBuffer(long)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onProcessedStreamChange()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onProcessedStreamChange()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onProcessedStreamChange()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onProcessedTunneledBuffer(long)"},{"p":"com.google.android.exoplayer2.offline","c":"Downloader.ProgressListener","l":"onProgress(long, long, float)","url":"onProgress(long,long,float)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheWriter.ProgressListener","l":"onProgress(long, long, long)","url":"onProgress(long,long,long)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView.ProgressUpdateListener","l":"onProgressUpdate(long, long)","url":"onProgressUpdate(long,long)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView.ProgressUpdateListener","l":"onProgressUpdate(long, long)","url":"onProgressUpdate(long,long)"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"onQueueEndOfStream()"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"onQueueEndOfStream()"},{"p":"com.google.android.exoplayer2.audio","c":"TeeAudioProcessor","l":"onQueueEndOfStream()"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"onQueueInputBuffer(DecoderInputBuffer)","url":"onQueueInputBuffer(com.google.android.exoplayer2.decoder.DecoderInputBuffer)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onQueueInputBuffer(DecoderInputBuffer)","url":"onQueueInputBuffer(com.google.android.exoplayer2.decoder.DecoderInputBuffer)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onQueueInputBuffer(DecoderInputBuffer)","url":"onQueueInputBuffer(com.google.android.exoplayer2.decoder.DecoderInputBuffer)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onQueueInputBuffer(DecoderInputBuffer)","url":"onQueueInputBuffer(com.google.android.exoplayer2.decoder.DecoderInputBuffer)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"onQueueInputBuffer(VideoDecoderInputBuffer)","url":"onQueueInputBuffer(com.google.android.exoplayer2.video.VideoDecoderInputBuffer)"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"onRebuffer()"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","c":"RtpAc3Reader","l":"onReceivingFirstPacket(long, int)","url":"onReceivingFirstPacket(long,int)"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","c":"RtpPayloadReader","l":"onReceivingFirstPacket(long, int)","url":"onReceivingFirstPacket(long,int)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"onReleased()"},{"p":"com.google.android.exoplayer2","c":"LoadControl","l":"onReleased()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.QueueEditor","l":"onRemoveQueueItem(Player, MediaDescriptionCompat)","url":"onRemoveQueueItem(com.google.android.exoplayer2.Player,android.support.v4.media.MediaDescriptionCompat)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor","l":"onRemoveQueueItem(Player, MediaDescriptionCompat)","url":"onRemoveQueueItem(com.google.android.exoplayer2.Player,android.support.v4.media.MediaDescriptionCompat)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onRenderedFirstFrame()"},{"p":"com.google.android.exoplayer2.video","c":"VideoListener","l":"onRenderedFirstFrame()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onRenderedFirstFrame(AnalyticsListener.EventTime, Object, long)","url":"onRenderedFirstFrame(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.Object,long)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onRenderedFirstFrame(AnalyticsListener.EventTime, Object, long)","url":"onRenderedFirstFrame(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.Object,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onRenderedFirstFrame(Object, long)","url":"onRenderedFirstFrame(java.lang.Object,long)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener","l":"onRenderedFirstFrame(Object, long)","url":"onRenderedFirstFrame(java.lang.Object,long)"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"onRendererOffsetChanged(long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onRepeatModeChanged(AnalyticsListener.EventTime, int)","url":"onRepeatModeChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onRepeatModeChanged(AnalyticsListener.EventTime, int)","url":"onRepeatModeChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onRepeatModeChanged(int)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onRepeatModeChanged(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onRepeatModeChanged(int)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"onRepeatModeChanged(int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager.Listener","l":"onRequirementsStateChanged(DownloadManager, Requirements, int)","url":"onRequirementsStateChanged(com.google.android.exoplayer2.offline.DownloadManager,com.google.android.exoplayer2.scheduler.Requirements,int)"},{"p":"com.google.android.exoplayer2.scheduler","c":"RequirementsWatcher.Listener","l":"onRequirementsStateChanged(RequirementsWatcher, int)","url":"onRequirementsStateChanged(com.google.android.exoplayer2.scheduler.RequirementsWatcher,int)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"onReset()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"onReset()"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"onReset()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onReset()"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"onReset()"},{"p":"com.google.android.exoplayer2.audio","c":"TeeAudioProcessor","l":"onReset()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onReset()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onReset()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"onResume()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"onResume()"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView","l":"onResume()"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"onRtlPropertiesChanged(int)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"onSampleCompleted(int, long, int, int, int, MediaCodec.CryptoInfo)","url":"onSampleCompleted(int,long,int,int,int,android.media.MediaCodec.CryptoInfo)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"onSampleDataFound(int, MediaParser.InputReader)","url":"onSampleDataFound(int,android.media.MediaParser.InputReader)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream.ReleaseCallback","l":"onSampleStreamReleased(ChunkSampleStream)","url":"onSampleStreamReleased(com.google.android.exoplayer2.source.chunk.ChunkSampleStream)"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar.OnScrubListener","l":"onScrubMove(TimeBar, long)","url":"onScrubMove(com.google.android.exoplayer2.ui.TimeBar,long)"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar.OnScrubListener","l":"onScrubStart(TimeBar, long)","url":"onScrubStart(com.google.android.exoplayer2.ui.TimeBar,long)"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar.OnScrubListener","l":"onScrubStop(TimeBar, long, boolean)","url":"onScrubStop(com.google.android.exoplayer2.ui.TimeBar,long,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.TimestampSeeker","l":"onSeekFinished()"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"onSeekMapFound(MediaParser.SeekMap)","url":"onSeekMapFound(android.media.MediaParser.SeekMap)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"onSeekOperationFinished(boolean, long)","url":"onSeekOperationFinished(boolean,long)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onSeekProcessed()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onSeekProcessed()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onSeekProcessed(AnalyticsListener.EventTime)","url":"onSeekProcessed(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onSeekStarted(AnalyticsListener.EventTime)","url":"onSeekStarted(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector","l":"onSelectionActivated(Object)","url":"onSelectionActivated(java.lang.Object)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelector","l":"onSelectionActivated(Object)","url":"onSelectionActivated(java.lang.Object)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackSessionManager.Listener","l":"onSessionActive(AnalyticsListener.EventTime, String)","url":"onSessionActive(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"onSessionActive(AnalyticsListener.EventTime, String)","url":"onSessionActive(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackSessionManager.Listener","l":"onSessionCreated(AnalyticsListener.EventTime, String)","url":"onSessionCreated(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"onSessionCreated(AnalyticsListener.EventTime, String)","url":"onSessionCreated(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackSessionManager.Listener","l":"onSessionFinished(AnalyticsListener.EventTime, String, boolean)","url":"onSessionFinished(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"onSessionFinished(AnalyticsListener.EventTime, String, boolean)","url":"onSessionFinished(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.CaptionCallback","l":"onSetCaptioningEnabled(Player, boolean)","url":"onSetCaptioningEnabled(com.google.android.exoplayer2.Player,boolean)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.RatingCallback","l":"onSetRating(MediaSession, MediaSession.ControllerInfo, String, Rating)","url":"onSetRating(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo,java.lang.String,androidx.media2.common.Rating)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.RatingCallback","l":"onSetRating(Player, RatingCompat, Bundle)","url":"onSetRating(com.google.android.exoplayer2.Player,android.support.v4.media.RatingCompat,android.os.Bundle)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.RatingCallback","l":"onSetRating(Player, RatingCompat)","url":"onSetRating(com.google.android.exoplayer2.Player,android.support.v4.media.RatingCompat)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onShuffleModeChanged(AnalyticsListener.EventTime, boolean)","url":"onShuffleModeChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onShuffleModeChanged(AnalyticsListener.EventTime, boolean)","url":"onShuffleModeChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,boolean)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onShuffleModeEnabledChanged(boolean)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onShuffleModeEnabledChanged(boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onShuffleModeEnabledChanged(boolean)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"onShuffleModeEnabledChanged(boolean)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.SkipCallback","l":"onSkipBackward(MediaSession, MediaSession.ControllerInfo)","url":"onSkipBackward(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.SkipCallback","l":"onSkipForward(MediaSession, MediaSession.ControllerInfo)","url":"onSkipForward(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onSkipSilenceEnabledChanged(AnalyticsListener.EventTime, boolean)","url":"onSkipSilenceEnabledChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onSkipSilenceEnabledChanged(AnalyticsListener.EventTime, boolean)","url":"onSkipSilenceEnabledChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,boolean)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onSkipSilenceEnabledChanged(boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onSkipSilenceEnabledChanged(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioListener","l":"onSkipSilenceEnabledChanged(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener","l":"onSkipSilenceEnabledChanged(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.Listener","l":"onSkipSilenceEnabledChanged(boolean)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.QueueNavigator","l":"onSkipToNext(Player, ControlDispatcher)","url":"onSkipToNext(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ControlDispatcher)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueNavigator","l":"onSkipToNext(Player, ControlDispatcher)","url":"onSkipToNext(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ControlDispatcher)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.QueueNavigator","l":"onSkipToPrevious(Player, ControlDispatcher)","url":"onSkipToPrevious(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ControlDispatcher)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueNavigator","l":"onSkipToPrevious(Player, ControlDispatcher)","url":"onSkipToPrevious(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ControlDispatcher)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.QueueNavigator","l":"onSkipToQueueItem(Player, ControlDispatcher, long)","url":"onSkipToQueueItem(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ControlDispatcher,long)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueNavigator","l":"onSkipToQueueItem(Player, ControlDispatcher, long)","url":"onSkipToQueueItem(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ControlDispatcher,long)"},{"p":"com.google.android.exoplayer2","c":"Renderer.WakeupListener","l":"onSleep(long)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource","l":"onSourceInfoRefreshed(long, boolean, boolean)","url":"onSourceInfoRefreshed(long,boolean,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource.MediaSourceCaller","l":"onSourceInfoRefreshed(MediaSource, Timeline)","url":"onSourceInfoRefreshed(com.google.android.exoplayer2.source.MediaSource,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache.Listener","l":"onSpanAdded(Cache, CacheSpan)","url":"onSpanAdded(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CachedRegionTracker","l":"onSpanAdded(Cache, CacheSpan)","url":"onSpanAdded(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"LeastRecentlyUsedCacheEvictor","l":"onSpanAdded(Cache, CacheSpan)","url":"onSpanAdded(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"NoOpCacheEvictor","l":"onSpanAdded(Cache, CacheSpan)","url":"onSpanAdded(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache.Listener","l":"onSpanRemoved(Cache, CacheSpan)","url":"onSpanRemoved(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CachedRegionTracker","l":"onSpanRemoved(Cache, CacheSpan)","url":"onSpanRemoved(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"LeastRecentlyUsedCacheEvictor","l":"onSpanRemoved(Cache, CacheSpan)","url":"onSpanRemoved(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"NoOpCacheEvictor","l":"onSpanRemoved(Cache, CacheSpan)","url":"onSpanRemoved(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache.Listener","l":"onSpanTouched(Cache, CacheSpan, CacheSpan)","url":"onSpanTouched(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.cache.CacheSpan,com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CachedRegionTracker","l":"onSpanTouched(Cache, CacheSpan, CacheSpan)","url":"onSpanTouched(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.cache.CacheSpan,com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"LeastRecentlyUsedCacheEvictor","l":"onSpanTouched(Cache, CacheSpan, CacheSpan)","url":"onSpanTouched(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.cache.CacheSpan,com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"NoOpCacheEvictor","l":"onSpanTouched(Cache, CacheSpan, CacheSpan)","url":"onSpanTouched(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.cache.CacheSpan,com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity","l":"onStart()"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"onStart(HostActivity, Surface, FrameLayout)","url":"onStart(com.google.android.exoplayer2.testutil.HostActivity,android.view.Surface,android.widget.FrameLayout)"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity.HostedTest","l":"onStart(HostActivity, Surface, FrameLayout)","url":"onStart(com.google.android.exoplayer2.testutil.HostActivity,android.view.Surface,android.widget.FrameLayout)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"onStartCommand(Intent, int, int)","url":"onStartCommand(android.content.Intent,int,int)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"onStarted()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"onStarted()"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"onStarted()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onStarted()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onStarted()"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"onStarted()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onStarted()"},{"p":"com.google.android.exoplayer2.video","c":"VideoFrameReleaseHelper","l":"onStarted()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheEvictor","l":"onStartFile(Cache, String, long, long)","url":"onStartFile(com.google.android.exoplayer2.upstream.cache.Cache,java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"LeastRecentlyUsedCacheEvictor","l":"onStartFile(Cache, String, long, long)","url":"onStartFile(com.google.android.exoplayer2.upstream.cache.Cache,java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"NoOpCacheEvictor","l":"onStartFile(Cache, String, long, long)","url":"onStartFile(com.google.android.exoplayer2.upstream.cache.Cache,java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.scheduler","c":"PlatformScheduler.PlatformSchedulerService","l":"onStartJob(JobParameters)","url":"onStartJob(android.app.job.JobParameters)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onStaticMetadataChanged(AnalyticsListener.EventTime, List)","url":"onStaticMetadataChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.util.List)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onStaticMetadataChanged(AnalyticsListener.EventTime, List)","url":"onStaticMetadataChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.util.List)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onStaticMetadataChanged(List)","url":"onStaticMetadataChanged(java.util.List)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onStaticMetadataChanged(List)","url":"onStaticMetadataChanged(java.util.List)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onStaticMetadataChanged(List)","url":"onStaticMetadataChanged(java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity","l":"onStop()"},{"p":"com.google.android.exoplayer2.scheduler","c":"PlatformScheduler.PlatformSchedulerService","l":"onStopJob(JobParameters)","url":"onStopJob(android.app.job.JobParameters)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"onStopped()"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"onStopped()"},{"p":"com.google.android.exoplayer2","c":"LoadControl","l":"onStopped()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"onStopped()"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"onStopped()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onStopped()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onStopped()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeVideoRenderer","l":"onStopped()"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"onStopped()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onStopped()"},{"p":"com.google.android.exoplayer2.video","c":"VideoFrameReleaseHelper","l":"onStopped()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"onStreamChanged(Format[], long, long)","url":"onStreamChanged(com.google.android.exoplayer2.Format[],long,long)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onStreamChanged(Format[], long, long)","url":"onStreamChanged(com.google.android.exoplayer2.Format[],long,long)"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataRenderer","l":"onStreamChanged(Format[], long, long)","url":"onStreamChanged(com.google.android.exoplayer2.Format[],long,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeVideoRenderer","l":"onStreamChanged(Format[], long, long)","url":"onStreamChanged(com.google.android.exoplayer2.Format[],long,long)"},{"p":"com.google.android.exoplayer2.text","c":"TextRenderer","l":"onStreamChanged(Format[], long, long)","url":"onStreamChanged(com.google.android.exoplayer2.Format[],long,long)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"onStreamChanged(Format[], long, long)","url":"onStreamChanged(com.google.android.exoplayer2.Format[],long,long)"},{"p":"com.google.android.exoplayer2.video.spherical","c":"CameraMotionRenderer","l":"onStreamChanged(Format[], long, long)","url":"onStreamChanged(com.google.android.exoplayer2.Format[],long,long)"},{"p":"com.google.android.exoplayer2.video","c":"VideoFrameReleaseHelper","l":"onSurfaceChanged(Surface)","url":"onSurfaceChanged(android.view.Surface)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onSurfaceSizeChanged(AnalyticsListener.EventTime, int, int)","url":"onSurfaceSizeChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,int)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onSurfaceSizeChanged(AnalyticsListener.EventTime, int, int)","url":"onSurfaceSizeChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,int)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onSurfaceSizeChanged(int, int)","url":"onSurfaceSizeChanged(int,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onSurfaceSizeChanged(int, int)","url":"onSurfaceSizeChanged(int,int)"},{"p":"com.google.android.exoplayer2.video","c":"VideoListener","l":"onSurfaceSizeChanged(int, int)","url":"onSurfaceSizeChanged(int,int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"onTaskRemoved(Intent)","url":"onTaskRemoved(android.content.Intent)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock","l":"onThreadBlocked()"},{"p":"com.google.android.exoplayer2.util","c":"Clock","l":"onThreadBlocked()"},{"p":"com.google.android.exoplayer2.util","c":"SystemClock","l":"onThreadBlocked()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onTimelineChanged(AnalyticsListener.EventTime, int)","url":"onTimelineChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onTimelineChanged(AnalyticsListener.EventTime, int)","url":"onTimelineChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.QueueNavigator","l":"onTimelineChanged(Player)","url":"onTimelineChanged(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueNavigator","l":"onTimelineChanged(Player)","url":"onTimelineChanged(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onTimelineChanged(Timeline, int)","url":"onTimelineChanged(com.google.android.exoplayer2.Timeline,int)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onTimelineChanged(Timeline, int)","url":"onTimelineChanged(com.google.android.exoplayer2.Timeline,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onTimelineChanged(Timeline, int)","url":"onTimelineChanged(com.google.android.exoplayer2.Timeline,int)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"onTimelineChanged(Timeline, int)","url":"onTimelineChanged(com.google.android.exoplayer2.Timeline,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"onTimelineChanged(Timeline, int)","url":"onTimelineChanged(com.google.android.exoplayer2.Timeline,int)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onTimelineChanged(Timeline, Object, int)","url":"onTimelineChanged(com.google.android.exoplayer2.Timeline,java.lang.Object,int)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"onTouchEvent(MotionEvent)","url":"onTouchEvent(android.view.MotionEvent)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"onTouchEvent(MotionEvent)","url":"onTouchEvent(android.view.MotionEvent)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"onTouchEvent(MotionEvent)","url":"onTouchEvent(android.view.MotionEvent)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"onTrackballEvent(MotionEvent)","url":"onTrackballEvent(android.view.MotionEvent)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"onTrackballEvent(MotionEvent)","url":"onTrackballEvent(android.view.MotionEvent)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"onTrackCountFound(int)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"onTrackDataFound(int, MediaParser.TrackData)","url":"onTrackDataFound(int,android.media.MediaParser.TrackData)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onTracksChanged(AnalyticsListener.EventTime, TrackGroupArray, TrackSelectionArray)","url":"onTracksChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.trackselection.TrackSelectionArray)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onTracksChanged(AnalyticsListener.EventTime, TrackGroupArray, TrackSelectionArray)","url":"onTracksChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.trackselection.TrackSelectionArray)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onTracksChanged(TrackGroupArray, TrackSelectionArray)","url":"onTracksChanged(com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.trackselection.TrackSelectionArray)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onTracksChanged(TrackGroupArray, TrackSelectionArray)","url":"onTracksChanged(com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.trackselection.TrackSelectionArray)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onTracksChanged(TrackGroupArray, TrackSelectionArray)","url":"onTracksChanged(com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.trackselection.TrackSelectionArray)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"onTracksChanged(TrackGroupArray, TrackSelectionArray)","url":"onTracksChanged(com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.trackselection.TrackSelectionArray)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionView.TrackSelectionListener","l":"onTrackSelectionChanged(boolean, List)","url":"onTrackSelectionChanged(boolean,java.util.List)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelector.InvalidationListener","l":"onTrackSelectionsInvalidated()"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder.DialogCallback","l":"onTracksSelected(boolean, List)","url":"onTracksSelected(boolean,java.util.List)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"onTracksSelected(Renderer[], TrackGroupArray, ExoTrackSelection[])","url":"onTracksSelected(com.google.android.exoplayer2.Renderer[],com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.trackselection.ExoTrackSelection[])"},{"p":"com.google.android.exoplayer2","c":"LoadControl","l":"onTracksSelected(Renderer[], TrackGroupArray, ExoTrackSelection[])","url":"onTracksSelected(com.google.android.exoplayer2.Renderer[],com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.trackselection.ExoTrackSelection[])"},{"p":"com.google.android.exoplayer2","c":"BundleListRetriever","l":"onTransact(int, Parcel, Parcel, int)","url":"onTransact(int,android.os.Parcel,android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.FakeTransferListener","l":"onTransferEnd(DataSource, DataSpec, boolean)","url":"onTransferEnd(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"onTransferEnd(DataSource, DataSpec, boolean)","url":"onTransferEnd(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"TransferListener","l":"onTransferEnd(DataSource, DataSpec, boolean)","url":"onTransferEnd(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.FakeTransferListener","l":"onTransferInitializing(DataSource, DataSpec, boolean)","url":"onTransferInitializing(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"onTransferInitializing(DataSource, DataSpec, boolean)","url":"onTransferInitializing(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"TransferListener","l":"onTransferInitializing(DataSource, DataSpec, boolean)","url":"onTransferInitializing(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"TimeToFirstByteEstimator","l":"onTransferInitializing(DataSpec)","url":"onTransferInitializing(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.FakeTransferListener","l":"onTransferStart(DataSource, DataSpec, boolean)","url":"onTransferStart(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"onTransferStart(DataSource, DataSpec, boolean)","url":"onTransferStart(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"TransferListener","l":"onTransferStart(DataSource, DataSpec, boolean)","url":"onTransferStart(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"TimeToFirstByteEstimator","l":"onTransferStart(DataSpec)","url":"onTransferStart(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer.Listener","l":"onTransformationCompleted(MediaItem)","url":"onTransformationCompleted(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer.Listener","l":"onTransformationError(MediaItem, Exception)","url":"onTransformationError(com.google.android.exoplayer2.MediaItem,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.source.hls","c":"BundledHlsMediaChunkExtractor","l":"onTruncatedSegmentParsed()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaChunkExtractor","l":"onTruncatedSegmentParsed()"},{"p":"com.google.android.exoplayer2.source.hls","c":"MediaParserHlsMediaChunkExtractor","l":"onTruncatedSegmentParsed()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.Listener","l":"onUnderrun(int, long, long)","url":"onUnderrun(int,long,long)"},{"p":"com.google.android.exoplayer2.database","c":"ExoDatabaseProvider","l":"onUpgrade(SQLiteDatabase, int, int)","url":"onUpgrade(android.database.sqlite.SQLiteDatabase,int,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onUpstreamDiscarded(AnalyticsListener.EventTime, MediaLoadData)","url":"onUpstreamDiscarded(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onUpstreamDiscarded(AnalyticsListener.EventTime, MediaLoadData)","url":"onUpstreamDiscarded(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onUpstreamDiscarded(int, MediaSource.MediaPeriodId, MediaLoadData)","url":"onUpstreamDiscarded(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener","l":"onUpstreamDiscarded(int, MediaSource.MediaPeriodId, MediaLoadData)","url":"onUpstreamDiscarded(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue.UpstreamFormatChangedListener","l":"onUpstreamFormatChanged(Format)","url":"onUpstreamFormatChanged(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onVideoCodecError(AnalyticsListener.EventTime, Exception)","url":"onVideoCodecError(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onVideoCodecError(Exception)","url":"onVideoCodecError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener","l":"onVideoCodecError(Exception)","url":"onVideoCodecError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onVideoDecoderInitialized(AnalyticsListener.EventTime, String, long, long)","url":"onVideoDecoderInitialized(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onVideoDecoderInitialized(AnalyticsListener.EventTime, String, long)","url":"onVideoDecoderInitialized(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String,long)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onVideoDecoderInitialized(AnalyticsListener.EventTime, String, long)","url":"onVideoDecoderInitialized(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onVideoDecoderInitialized(String, long, long)","url":"onVideoDecoderInitialized(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener","l":"onVideoDecoderInitialized(String, long, long)","url":"onVideoDecoderInitialized(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onVideoDecoderReleased(AnalyticsListener.EventTime, String)","url":"onVideoDecoderReleased(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onVideoDecoderReleased(AnalyticsListener.EventTime, String)","url":"onVideoDecoderReleased(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onVideoDecoderReleased(String)","url":"onVideoDecoderReleased(java.lang.String)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener","l":"onVideoDecoderReleased(String)","url":"onVideoDecoderReleased(java.lang.String)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onVideoDisabled(AnalyticsListener.EventTime, DecoderCounters)","url":"onVideoDisabled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"onVideoDisabled(AnalyticsListener.EventTime, DecoderCounters)","url":"onVideoDisabled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onVideoDisabled(AnalyticsListener.EventTime, DecoderCounters)","url":"onVideoDisabled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onVideoDisabled(DecoderCounters)","url":"onVideoDisabled(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener","l":"onVideoDisabled(DecoderCounters)","url":"onVideoDisabled(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onVideoEnabled(AnalyticsListener.EventTime, DecoderCounters)","url":"onVideoEnabled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onVideoEnabled(AnalyticsListener.EventTime, DecoderCounters)","url":"onVideoEnabled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onVideoEnabled(DecoderCounters)","url":"onVideoEnabled(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener","l":"onVideoEnabled(DecoderCounters)","url":"onVideoEnabled(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.video","c":"VideoFrameMetadataListener","l":"onVideoFrameAboutToBeRendered(long, long, Format, MediaFormat)","url":"onVideoFrameAboutToBeRendered(long,long,com.google.android.exoplayer2.Format,android.media.MediaFormat)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onVideoFrameProcessingOffset(AnalyticsListener.EventTime, long, int)","url":"onVideoFrameProcessingOffset(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,long,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onVideoFrameProcessingOffset(long, int)","url":"onVideoFrameProcessingOffset(long,int)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener","l":"onVideoFrameProcessingOffset(long, int)","url":"onVideoFrameProcessingOffset(long,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onVideoInputFormatChanged(AnalyticsListener.EventTime, Format, DecoderReuseEvaluation)","url":"onVideoInputFormatChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.decoder.DecoderReuseEvaluation)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onVideoInputFormatChanged(AnalyticsListener.EventTime, Format, DecoderReuseEvaluation)","url":"onVideoInputFormatChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.decoder.DecoderReuseEvaluation)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onVideoInputFormatChanged(AnalyticsListener.EventTime, Format)","url":"onVideoInputFormatChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onVideoInputFormatChanged(Format, DecoderReuseEvaluation)","url":"onVideoInputFormatChanged(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.decoder.DecoderReuseEvaluation)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener","l":"onVideoInputFormatChanged(Format, DecoderReuseEvaluation)","url":"onVideoInputFormatChanged(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.decoder.DecoderReuseEvaluation)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener","l":"onVideoInputFormatChanged(Format)","url":"onVideoInputFormatChanged(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onVideoSizeChanged(AnalyticsListener.EventTime, int, int, int, float)","url":"onVideoSizeChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,int,int,float)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onVideoSizeChanged(AnalyticsListener.EventTime, VideoSize)","url":"onVideoSizeChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.video.VideoSize)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"onVideoSizeChanged(AnalyticsListener.EventTime, VideoSize)","url":"onVideoSizeChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.video.VideoSize)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onVideoSizeChanged(AnalyticsListener.EventTime, VideoSize)","url":"onVideoSizeChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.video.VideoSize)"},{"p":"com.google.android.exoplayer2.video","c":"VideoListener","l":"onVideoSizeChanged(int, int, int, float)","url":"onVideoSizeChanged(int,int,int,float)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onVideoSizeChanged(VideoSize)","url":"onVideoSizeChanged(com.google.android.exoplayer2.video.VideoSize)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onVideoSizeChanged(VideoSize)","url":"onVideoSizeChanged(com.google.android.exoplayer2.video.VideoSize)"},{"p":"com.google.android.exoplayer2.video","c":"VideoListener","l":"onVideoSizeChanged(VideoSize)","url":"onVideoSizeChanged(com.google.android.exoplayer2.video.VideoSize)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener","l":"onVideoSizeChanged(VideoSize)","url":"onVideoSizeChanged(com.google.android.exoplayer2.video.VideoSize)"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView.VideoSurfaceListener","l":"onVideoSurfaceCreated(Surface)","url":"onVideoSurfaceCreated(android.view.Surface)"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView.VideoSurfaceListener","l":"onVideoSurfaceDestroyed(Surface)","url":"onVideoSurfaceDestroyed(android.view.Surface)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView.VisibilityListener","l":"onVisibilityChange(int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView.VisibilityListener","l":"onVisibilityChange(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onVolumeChanged(AnalyticsListener.EventTime, float)","url":"onVolumeChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,float)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onVolumeChanged(AnalyticsListener.EventTime, float)","url":"onVolumeChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,float)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onVolumeChanged(float)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onVolumeChanged(float)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioListener","l":"onVolumeChanged(float)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager.Listener","l":"onWaitingForRequirementsChanged(DownloadManager, boolean)","url":"onWaitingForRequirementsChanged(com.google.android.exoplayer2.offline.DownloadManager,boolean)"},{"p":"com.google.android.exoplayer2","c":"Renderer.WakeupListener","l":"onWakeup()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceInputStream","l":"open()"},{"p":"com.google.android.exoplayer2.util","c":"ConditionVariable","l":"open()"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.ext.rtmp","c":"RtmpDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.testutil","c":"FailOnCloseDataSink","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"AssetDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"ByteArrayDataSink","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"ByteArrayDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"ContentDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSchemeDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSink","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"DummyDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"PriorityDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"RawResourceDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"ResolvingDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"StatsDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"TeeDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"UdpDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesCipherDataSink","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesCipherDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.OpenException","l":"OpenException(IOException, DataSpec, int)","url":"%3Cinit%3E(java.io.IOException,com.google.android.exoplayer2.upstream.DataSpec,int)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.OpenException","l":"OpenException(String, DataSpec, int)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.upstream.DataSpec,int)"},{"p":"com.google.android.exoplayer2.util","c":"AtomicFile","l":"openRead()"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"openSession()"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"openSession()"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"openSession()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"openSession()"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusDecoder","l":"OpusDecoder(int, int, int, List, ExoMediaCrypto, boolean)","url":"%3Cinit%3E(int,int,int,java.util.List,com.google.android.exoplayer2.drm.ExoMediaCrypto,boolean)"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusLibrary","l":"opusGetVersion()"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusLibrary","l":"opusIsSecureDecodeSupported()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.OtherTrackScore","l":"OtherTrackScore(Format, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format,int)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"outOfNetworkIndicator"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.Event","l":"outOfNetworkIndicator"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"outputAudioFormat"},{"p":"com.google.android.exoplayer2.decoder","c":"OutputBuffer","l":"OutputBuffer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"OutputConsumerAdapterV30()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"OutputConsumerAdapterV30(Format, int, boolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format,int,boolean)"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusDecoder","l":"outputFloat"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"overallRating"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.TimestampSearchResult","l":"overestimatedResult(long, long)","url":"overestimatedResult(long,long)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"overridePreparePositionUs(long)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"PrivFrame","l":"owner"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Reader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Reader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsReader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DtsReader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DvbSubtitleReader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"ElementaryStreamReader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H262Reader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H263Reader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H264Reader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H265Reader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Id3Reader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"LatmReader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"MpegAudioReader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Reader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Reader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsReader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DtsReader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DvbSubtitleReader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"ElementaryStreamReader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H262Reader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H263Reader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H264Reader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H265Reader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Id3Reader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"LatmReader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"MpegAudioReader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"padding"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"MediaParserUtil","l":"PARAMETER_EAGERLY_EXPOSE_TRACK_TYPE"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"MediaParserUtil","l":"PARAMETER_EXPOSE_CAPTION_FORMATS"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"MediaParserUtil","l":"PARAMETER_EXPOSE_CHUNK_INDEX_AS_MEDIA_FORMAT"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"MediaParserUtil","l":"PARAMETER_EXPOSE_DUMMY_SEEK_MAP"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"MediaParserUtil","l":"PARAMETER_IGNORE_TIMESTAMP_OFFSET"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"MediaParserUtil","l":"PARAMETER_IN_BAND_CRYPTO_INFO"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"MediaParserUtil","l":"PARAMETER_INCLUDE_SUPPLEMENTAL_DATA"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"MediaParserUtil","l":"PARAMETER_OVERRIDE_IN_BAND_CAPTION_DECLARATIONS"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"ParametersBuilder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"ParametersBuilder(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream.EmbeddedSampleStream","l":"parent"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"ParsableBitArray()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"ParsableBitArray(byte[], int)","url":"%3Cinit%3E(byte[],int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"ParsableBitArray(byte[])","url":"%3Cinit%3E(byte[])"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"ParsableByteArray()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"ParsableByteArray(byte[], int)","url":"%3Cinit%3E(byte[],int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"ParsableByteArray(byte[])","url":"%3Cinit%3E(byte[])"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"ParsableByteArray(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableNalUnitBitArray","l":"ParsableNalUnitBitArray(byte[], int, int)","url":"%3Cinit%3E(byte[],int,int)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"parse(byte[], int)","url":"parse(byte[],int)"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"parse(Map>)","url":"parse(java.util.Map)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"parse(ParsableByteArray)","url":"parse(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.video","c":"AvcConfig","l":"parse(ParsableByteArray)","url":"parse(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.video","c":"DolbyVisionConfig","l":"parse(ParsableByteArray)","url":"parse(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.video","c":"HevcConfig","l":"parse(ParsableByteArray)","url":"parse(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.offline","c":"FilteringManifestParser","l":"parse(Uri, InputStream)","url":"parse(android.net.Uri,java.io.InputStream)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parse(Uri, InputStream)","url":"parse(android.net.Uri,java.io.InputStream)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistParser","l":"parse(Uri, InputStream)","url":"parse(android.net.Uri,java.io.InputStream)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifestParser","l":"parse(Uri, InputStream)","url":"parse(android.net.Uri,java.io.InputStream)"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable.Parser","l":"parse(Uri, InputStream)","url":"parse(android.net.Uri,java.io.InputStream)"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"parseAc3AnnexFFormat(ParsableByteArray, String, String, DrmInitData)","url":"parseAc3AnnexFFormat(com.google.android.exoplayer2.util.ParsableByteArray,java.lang.String,java.lang.String,com.google.android.exoplayer2.drm.DrmInitData)"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"parseAc3SyncframeAudioSampleCount(ByteBuffer)","url":"parseAc3SyncframeAudioSampleCount(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"parseAc3SyncframeInfo(ParsableBitArray)","url":"parseAc3SyncframeInfo(com.google.android.exoplayer2.util.ParsableBitArray)"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"parseAc3SyncframeSize(byte[])"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util","l":"parseAc4AnnexEFormat(ParsableByteArray, String, String, DrmInitData)","url":"parseAc4AnnexEFormat(com.google.android.exoplayer2.util.ParsableByteArray,java.lang.String,java.lang.String,com.google.android.exoplayer2.drm.DrmInitData)"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util","l":"parseAc4SyncframeAudioSampleCount(ByteBuffer)","url":"parseAc4SyncframeAudioSampleCount(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util","l":"parseAc4SyncframeInfo(ParsableBitArray)","url":"parseAc4SyncframeInfo(com.google.android.exoplayer2.util.ParsableBitArray)"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util","l":"parseAc4SyncframeSize(byte[], int)","url":"parseAc4SyncframeSize(byte[],int)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseAdaptationSet(XmlPullParser, String, SegmentBase, long, long, long, long, long)","url":"parseAdaptationSet(org.xmlpull.v1.XmlPullParser,java.lang.String,com.google.android.exoplayer2.source.dash.manifest.SegmentBase,long,long,long,long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseAdaptationSetChild(XmlPullParser)","url":"parseAdaptationSetChild(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.util","c":"CodecSpecificDataUtil","l":"parseAlacAudioSpecificConfig(byte[])"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseAudioChannelConfiguration(XmlPullParser)","url":"parseAudioChannelConfiguration(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"parseAudioSpecificConfig(byte[])"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"parseAudioSpecificConfig(ParsableBitArray, boolean)","url":"parseAudioSpecificConfig(com.google.android.exoplayer2.util.ParsableBitArray,boolean)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseAvailabilityTimeOffsetUs(XmlPullParser, long)","url":"parseAvailabilityTimeOffsetUs(org.xmlpull.v1.XmlPullParser,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseBaseUrl(XmlPullParser, String)","url":"parseBaseUrl(org.xmlpull.v1.XmlPullParser,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseCea608AccessibilityChannel(List)","url":"parseCea608AccessibilityChannel(java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseCea708AccessibilityChannel(List)","url":"parseCea708AccessibilityChannel(java.util.List)"},{"p":"com.google.android.exoplayer2.util","c":"CodecSpecificDataUtil","l":"parseCea708InitializationData(List)","url":"parseCea708InitializationData(java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseContentProtection(XmlPullParser)","url":"parseContentProtection(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseContentType(XmlPullParser)","url":"parseContentType(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.util","c":"ColorParser","l":"parseCssColor(String)","url":"parseCssColor(java.lang.String)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCueParser","l":"parseCue(ParsableByteArray, List)","url":"parseCue(com.google.android.exoplayer2.util.ParsableByteArray,java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseDateTime(XmlPullParser, String, long)","url":"parseDateTime(org.xmlpull.v1.XmlPullParser,java.lang.String,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseDescriptor(XmlPullParser, String)","url":"parseDescriptor(org.xmlpull.v1.XmlPullParser,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseDolbyChannelConfiguration(XmlPullParser)","url":"parseDolbyChannelConfiguration(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.audio","c":"DtsUtil","l":"parseDtsAudioSampleCount(byte[])"},{"p":"com.google.android.exoplayer2.audio","c":"DtsUtil","l":"parseDtsAudioSampleCount(ByteBuffer)","url":"parseDtsAudioSampleCount(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.audio","c":"DtsUtil","l":"parseDtsFormat(byte[], String, String, DrmInitData)","url":"parseDtsFormat(byte[],java.lang.String,java.lang.String,com.google.android.exoplayer2.drm.DrmInitData)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseDuration(XmlPullParser, String, long)","url":"parseDuration(org.xmlpull.v1.XmlPullParser,java.lang.String,long)"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"parseEAc3AnnexFFormat(ParsableByteArray, String, String, DrmInitData)","url":"parseEAc3AnnexFFormat(com.google.android.exoplayer2.util.ParsableByteArray,java.lang.String,java.lang.String,com.google.android.exoplayer2.drm.DrmInitData)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseEac3SupplementalProperties(List)","url":"parseEac3SupplementalProperties(java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseEvent(XmlPullParser, String, String, long, ByteArrayOutputStream)","url":"parseEvent(org.xmlpull.v1.XmlPullParser,java.lang.String,java.lang.String,long,java.io.ByteArrayOutputStream)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseEventObject(XmlPullParser, ByteArrayOutputStream)","url":"parseEventObject(org.xmlpull.v1.XmlPullParser,java.io.ByteArrayOutputStream)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseEventStream(XmlPullParser)","url":"parseEventStream(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseFloat(XmlPullParser, String, float)","url":"parseFloat(org.xmlpull.v1.XmlPullParser,java.lang.String,float)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseFrameRate(XmlPullParser, float)","url":"parseFrameRate(org.xmlpull.v1.XmlPullParser,float)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseInitialization(XmlPullParser)","url":"parseInitialization(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseInt(XmlPullParser, String, int)","url":"parseInt(org.xmlpull.v1.XmlPullParser,java.lang.String,int)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseLabel(XmlPullParser)","url":"parseLabel(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseLastSegmentNumberSupplementalProperty(List)","url":"parseLastSegmentNumberSupplementalProperty(java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseLong(XmlPullParser, String, long)","url":"parseLong(org.xmlpull.v1.XmlPullParser,java.lang.String,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseMediaPresentationDescription(XmlPullParser, String)","url":"parseMediaPresentationDescription(org.xmlpull.v1.XmlPullParser,java.lang.String)"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil","l":"parseMpegAudioFrameSampleCount(int)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseMpegChannelConfiguration(XmlPullParser)","url":"parseMpegChannelConfiguration(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttParserUtil","l":"parsePercentage(String)","url":"parsePercentage(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parsePeriod(XmlPullParser, String, long, long, long, long)","url":"parsePeriod(org.xmlpull.v1.XmlPullParser,java.lang.String,long,long,long,long)"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil","l":"parsePpsNalUnit(byte[], int, int)","url":"parsePpsNalUnit(byte[],int,int)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseProgramInformation(XmlPullParser)","url":"parseProgramInformation(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseRangedUrl(XmlPullParser, String, String)","url":"parseRangedUrl(org.xmlpull.v1.XmlPullParser,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseRepresentation(XmlPullParser, String, String, String, int, int, float, int, int, String, List, List, List, List, SegmentBase, long, long, long, long, long)","url":"parseRepresentation(org.xmlpull.v1.XmlPullParser,java.lang.String,java.lang.String,java.lang.String,int,int,float,int,int,java.lang.String,java.util.List,java.util.List,java.util.List,java.util.List,com.google.android.exoplayer2.source.dash.manifest.SegmentBase,long,long,long,long,long)"},{"p":"com.google.android.exoplayer2","c":"ParserException","l":"ParserException()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"ParserException","l":"ParserException(String, Throwable)","url":"%3Cinit%3E(java.lang.String,java.lang.Throwable)"},{"p":"com.google.android.exoplayer2","c":"ParserException","l":"ParserException(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"ParserException","l":"ParserException(Throwable)","url":"%3Cinit%3E(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseRoleFlagsFromAccessibilityDescriptors(List)","url":"parseRoleFlagsFromAccessibilityDescriptors(java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseRoleFlagsFromDashRoleScheme(String)","url":"parseRoleFlagsFromDashRoleScheme(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseRoleFlagsFromProperties(List)","url":"parseRoleFlagsFromProperties(java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseRoleFlagsFromRoleDescriptors(List)","url":"parseRoleFlagsFromRoleDescriptors(java.util.List)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"PsshAtomUtil","l":"parseSchemeSpecificData(byte[], UUID)","url":"parseSchemeSpecificData(byte[],java.util.UUID)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseSegmentBase(XmlPullParser, SegmentBase.SingleSegmentBase)","url":"parseSegmentBase(org.xmlpull.v1.XmlPullParser,com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseSegmentList(XmlPullParser, SegmentBase.SegmentList, long, long, long, long, long)","url":"parseSegmentList(org.xmlpull.v1.XmlPullParser,com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SegmentList,long,long,long,long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseSegmentTemplate(XmlPullParser, SegmentBase.SegmentTemplate, List, long, long, long, long, long)","url":"parseSegmentTemplate(org.xmlpull.v1.XmlPullParser,com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SegmentTemplate,java.util.List,long,long,long,long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseSegmentTimeline(XmlPullParser, long, long)","url":"parseSegmentTimeline(org.xmlpull.v1.XmlPullParser,long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseSegmentUrl(XmlPullParser)","url":"parseSegmentUrl(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseSelectionFlagsFromDashRoleScheme(String)","url":"parseSelectionFlagsFromDashRoleScheme(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseSelectionFlagsFromRoleDescriptors(List)","url":"parseSelectionFlagsFromRoleDescriptors(java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseServiceDescription(XmlPullParser)","url":"parseServiceDescription(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil","l":"parseSpsNalUnit(byte[], int, int)","url":"parseSpsNalUnit(byte[],int,int)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseString(XmlPullParser, String, String)","url":"parseString(org.xmlpull.v1.XmlPullParser,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseText(XmlPullParser, String)","url":"parseText(org.xmlpull.v1.XmlPullParser,java.lang.String)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttParserUtil","l":"parseTimestampUs(String)","url":"parseTimestampUs(java.lang.String)"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"parseTrueHdSyncframeAudioSampleCount(byte[])"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"parseTrueHdSyncframeAudioSampleCount(ByteBuffer, int)","url":"parseTrueHdSyncframeAudioSampleCount(java.nio.ByteBuffer,int)"},{"p":"com.google.android.exoplayer2.util","c":"ColorParser","l":"parseTtmlColor(String)","url":"parseTtmlColor(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseTvaAudioPurposeCsValue(String)","url":"parseTvaAudioPurposeCsValue(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseUrlTemplate(XmlPullParser, String, UrlTemplate)","url":"parseUrlTemplate(org.xmlpull.v1.XmlPullParser,java.lang.String,com.google.android.exoplayer2.source.dash.manifest.UrlTemplate)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseUtcTiming(XmlPullParser)","url":"parseUtcTiming(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"PsshAtomUtil","l":"parseUuid(byte[])"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"PsshAtomUtil","l":"parseVersion(byte[])"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"parseXsDateTime(String)","url":"parseXsDateTime(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"parseXsDuration(String)","url":"parseXsDuration(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"ParsingLoadable(DataSource, DataSpec, int, ParsingLoadable.Parser)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,int,com.google.android.exoplayer2.upstream.ParsingLoadable.Parser)"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"ParsingLoadable(DataSource, Uri, int, ParsingLoadable.Parser)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,android.net.Uri,int,com.google.android.exoplayer2.upstream.ParsingLoadable.Parser)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.Part","l":"Part(String, HlsMediaPlaylist.Segment, long, int, long, DrmInitData, String, String, long, long, boolean, boolean, boolean)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.Segment,long,int,long,com.google.android.exoplayer2.drm.DrmInitData,java.lang.String,java.lang.String,long,long,boolean,boolean,boolean)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.ServerControl","l":"partHoldBackUs"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.Segment","l":"parts"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"partTargetDurationUs"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PassthroughSectionPayloadReader","l":"PassthroughSectionPayloadReader(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"pause()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"pause()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"pause()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"pause()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"pause()"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"pause()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"pause()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"pause()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"pauseDownloads()"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"payloadData"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"payloadType"},{"p":"com.google.android.exoplayer2","c":"Format","l":"pcmEncoding"},{"p":"com.google.android.exoplayer2","c":"Format","l":"peakBitrate"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry.VariantInfo","l":"peakBitrate"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"peek(byte[], int, int)","url":"peek(byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"peek(byte[], int, int)","url":"peek(byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"peek(byte[], int, int)","url":"peek(byte[],int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"peek(byte[], int, int)","url":"peek(byte[],int,int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"peekChar()"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"peekFully(byte[], int, int, boolean)","url":"peekFully(byte[],int,int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"peekFully(byte[], int, int, boolean)","url":"peekFully(byte[],int,int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"peekFully(byte[], int, int, boolean)","url":"peekFully(byte[],int,int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"peekFully(byte[], int, int, boolean)","url":"peekFully(byte[],int,int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"peekFully(byte[], int, int)","url":"peekFully(byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"peekFully(byte[], int, int)","url":"peekFully(byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"peekFully(byte[], int, int)","url":"peekFully(byte[],int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"peekFully(byte[], int, int)","url":"peekFully(byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorUtil","l":"peekFullyQuietly(ExtractorInput, byte[], int, int, boolean)","url":"peekFullyQuietly(com.google.android.exoplayer2.extractor.ExtractorInput,byte[],int,int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"Id3Peeker","l":"peekId3Data(ExtractorInput, Id3Decoder.FramePredicate)","url":"peekId3Data(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.metadata.id3.Id3Decoder.FramePredicate)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacMetadataReader","l":"peekId3Metadata(ExtractorInput, boolean)","url":"peekId3Metadata(com.google.android.exoplayer2.extractor.ExtractorInput,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"peekSourceId()"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorUtil","l":"peekToLength(ExtractorInput, byte[], int, int)","url":"peekToLength(com.google.android.exoplayer2.extractor.ExtractorInput,byte[],int,int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"peekUnsignedByte()"},{"p":"com.google.android.exoplayer2","c":"C","l":"PERCENTAGE_UNSET"},{"p":"com.google.android.exoplayer2","c":"PercentageRating","l":"PercentageRating()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"PercentageRating","l":"PercentageRating(float)","url":"%3Cinit%3E(float)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadProgress","l":"percentDownloaded"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"performAccessibilityAction(int, Bundle)","url":"performAccessibilityAction(int,android.os.Bundle)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"performClick()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"performClick()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"Period()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Period","l":"Period(String, long, List, List, Descriptor)","url":"%3Cinit%3E(java.lang.String,long,java.util.List,java.util.List,com.google.android.exoplayer2.source.dash.manifest.Descriptor)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Period","l":"Period(String, long, List, List)","url":"%3Cinit%3E(java.lang.String,long,java.util.List,java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Period","l":"Period(String, long, List)","url":"%3Cinit%3E(java.lang.String,long,java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"periodCount"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"periodIndex"},{"p":"com.google.android.exoplayer2.offline","c":"StreamKey","l":"periodIndex"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"periodUid"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"periodUid"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"TrackEncryptionBox","l":"perSampleIvSize"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PesReader","l":"PesReader(ElementaryStreamReader)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.ts.ElementaryStreamReader)"},{"p":"com.google.android.exoplayer2.text.pgs","c":"PgsDecoder","l":"PgsDecoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MotionPhotoMetadata","l":"photoPresentationTimestampUs"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MotionPhotoMetadata","l":"photoSize"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MotionPhotoMetadata","l":"photoStartPosition"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"picOrderCntLsbLength"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"picOrderCountType"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.PpsData","l":"picParameterSetId"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"pictureData"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ApicFrame","l":"pictureData"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"PictureFrame(int, String, String, int, int, int, int, byte[])","url":"%3Cinit%3E(int,java.lang.String,java.lang.String,int,int,int,int,byte[])"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"pictureType"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ApicFrame","l":"pictureType"},{"p":"com.google.android.exoplayer2","c":"PlaybackParameters","l":"pitch"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"pixelWidthAspectRatio"},{"p":"com.google.android.exoplayer2.video","c":"AvcConfig","l":"pixelWidthAspectRatio"},{"p":"com.google.android.exoplayer2","c":"Format","l":"pixelWidthHeightRatio"},{"p":"com.google.android.exoplayer2.video","c":"VideoSize","l":"pixelWidthHeightRatio"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorOutput","l":"PLACEHOLDER"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource.PlaceholderTimeline","l":"PlaceholderTimeline(MediaItem)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.scheduler","c":"PlatformScheduler","l":"PlatformScheduler(Context, int)","url":"%3Cinit%3E(android.content.Context,int)"},{"p":"com.google.android.exoplayer2.scheduler","c":"PlatformScheduler.PlatformSchedulerService","l":"PlatformSchedulerService()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"PLAY_WHEN_READY_CHANGE_REASON_AUDIO_BECOMING_NOISY"},{"p":"com.google.android.exoplayer2","c":"Player","l":"PLAY_WHEN_READY_CHANGE_REASON_AUDIO_FOCUS_LOSS"},{"p":"com.google.android.exoplayer2","c":"Player","l":"PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM"},{"p":"com.google.android.exoplayer2","c":"Player","l":"PLAY_WHEN_READY_CHANGE_REASON_REMOTE"},{"p":"com.google.android.exoplayer2","c":"Player","l":"PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"play()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"play()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"play()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"play()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"play()"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"play()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"play()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"play()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_ABANDONED"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_BUFFERING"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_ENDED"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_FAILED"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_INTERRUPTED_BY_AD"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_JOINING_BACKGROUND"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_JOINING_FOREGROUND"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_NOT_STARTED"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_PAUSED"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_PAUSED_BUFFERING"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_PLAYING"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_SEEKING"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_STOPPED"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_SUPPRESSED"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_SUPPRESSED_BUFFERING"},{"p":"com.google.android.exoplayer2","c":"Player","l":"PLAYBACK_SUPPRESSION_REASON_NONE"},{"p":"com.google.android.exoplayer2","c":"Player","l":"PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS"},{"p":"com.google.android.exoplayer2.device","c":"DeviceInfo","l":"PLAYBACK_TYPE_LOCAL"},{"p":"com.google.android.exoplayer2.device","c":"DeviceInfo","l":"PLAYBACK_TYPE_REMOTE"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"playbackCount"},{"p":"com.google.android.exoplayer2","c":"PlaybackParameters","l":"PlaybackParameters(float, float)","url":"%3Cinit%3E(float,float)"},{"p":"com.google.android.exoplayer2","c":"PlaybackParameters","l":"PlaybackParameters(float)","url":"%3Cinit%3E(float)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"TimeSignalCommand","l":"playbackPositionUs"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"playbackProperties"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndPlaybackState","l":"playbackState"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"playbackStateHistory"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"PlaybackStatsListener(boolean, PlaybackStatsListener.Callback)","url":"%3Cinit%3E(boolean,com.google.android.exoplayer2.analytics.PlaybackStatsListener.Callback)"},{"p":"com.google.android.exoplayer2.device","c":"DeviceInfo","l":"playbackType"},{"p":"com.google.android.exoplayer2","c":"MediaItem.DrmConfiguration","l":"playClearContentWithoutKey"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"playClearSamplesWithoutKeys()"},{"p":"com.google.android.exoplayer2.drm","c":"ErrorStateDrmSession","l":"playClearSamplesWithoutKeys()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"PlayerControlView(Context, AttributeSet, int, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet,int,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"PlayerControlView(Context, AttributeSet, int)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet,int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"PlayerControlView(Context, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"PlayerControlView(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler","l":"PlayerEmsgHandler(DashManifest, PlayerEmsgHandler.PlayerEmsgCallback, Allocator)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.dash.manifest.DashManifest,com.google.android.exoplayer2.source.dash.PlayerEmsgHandler.PlayerEmsgCallback,com.google.android.exoplayer2.upstream.Allocator)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"PlayerMessage(PlayerMessage.Sender, PlayerMessage.Target, Timeline, int, Clock, Looper)","url":"%3Cinit%3E(com.google.android.exoplayer2.PlayerMessage.Sender,com.google.android.exoplayer2.PlayerMessage.Target,com.google.android.exoplayer2.Timeline,int,com.google.android.exoplayer2.util.Clock,android.os.Looper)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"PlayerNotificationManager(Context, String, int, PlayerNotificationManager.MediaDescriptionAdapter, PlayerNotificationManager.CustomActionReceiver)","url":"%3Cinit%3E(android.content.Context,java.lang.String,int,com.google.android.exoplayer2.ui.PlayerNotificationManager.MediaDescriptionAdapter,com.google.android.exoplayer2.ui.PlayerNotificationManager.CustomActionReceiver)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"PlayerNotificationManager(Context, String, int, PlayerNotificationManager.MediaDescriptionAdapter, PlayerNotificationManager.NotificationListener, PlayerNotificationManager.CustomActionReceiver)","url":"%3Cinit%3E(android.content.Context,java.lang.String,int,com.google.android.exoplayer2.ui.PlayerNotificationManager.MediaDescriptionAdapter,com.google.android.exoplayer2.ui.PlayerNotificationManager.NotificationListener,com.google.android.exoplayer2.ui.PlayerNotificationManager.CustomActionReceiver)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"PlayerNotificationManager(Context, String, int, PlayerNotificationManager.MediaDescriptionAdapter, PlayerNotificationManager.NotificationListener)","url":"%3Cinit%3E(android.content.Context,java.lang.String,int,com.google.android.exoplayer2.ui.PlayerNotificationManager.MediaDescriptionAdapter,com.google.android.exoplayer2.ui.PlayerNotificationManager.NotificationListener)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"PlayerNotificationManager(Context, String, int, PlayerNotificationManager.MediaDescriptionAdapter)","url":"%3Cinit%3E(android.content.Context,java.lang.String,int,com.google.android.exoplayer2.ui.PlayerNotificationManager.MediaDescriptionAdapter)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.PlayerRunnable","l":"PlayerRunnable()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.PlayerTarget","l":"PlayerTarget()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"PlayerView(Context, AttributeSet, int)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet,int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"PlayerView(Context, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"PlayerView(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"PLAYLIST_TYPE_EVENT"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"PLAYLIST_TYPE_UNKNOWN"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"PLAYLIST_TYPE_VOD"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker.PlaylistResetException","l":"PlaylistResetException(Uri)","url":"%3Cinit%3E(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker.PlaylistStuckException","l":"PlaylistStuckException(Uri)","url":"%3Cinit%3E(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"playlistType"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.RenditionReport","l":"playlistUri"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"PLAYREADY_CUSTOM_DATA_KEY"},{"p":"com.google.android.exoplayer2","c":"C","l":"PLAYREADY_UUID"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"playToEndOfStream()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"playToEndOfStream()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"playToEndOfStream()"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestPlayerRunHelper","l":"playUntilPosition(ExoPlayer, int, long)","url":"playUntilPosition(com.google.android.exoplayer2.ExoPlayer,int,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"playUntilPosition(int, long)","url":"playUntilPosition(int,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.PlayUntilPosition","l":"PlayUntilPosition(String, int, long)","url":"%3Cinit%3E(java.lang.String,int,long)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestPlayerRunHelper","l":"playUntilStartOfWindow(ExoPlayer, int)","url":"playUntilStartOfWindow(com.google.android.exoplayer2.ExoPlayer,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"playUntilStartOfWindow(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata.SeekTable","l":"pointOffsets"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata.SeekTable","l":"pointSampleNumbers"},{"p":"com.google.android.exoplayer2.util","c":"TimedValueQueue","l":"poll(long)"},{"p":"com.google.android.exoplayer2.util","c":"TimedValueQueue","l":"pollFirst()"},{"p":"com.google.android.exoplayer2.util","c":"TimedValueQueue","l":"pollFloor(long)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"populateFromMetadata(List)","url":"populateFromMetadata(java.util.List)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"populateFromMetadata(Metadata)","url":"populateFromMetadata(com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata.Entry","l":"populateMediaMetadata(MediaMetadata.Builder)","url":"populateMediaMetadata(com.google.android.exoplayer2.MediaMetadata.Builder)"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyInfo","l":"populateMediaMetadata(MediaMetadata.Builder)","url":"populateMediaMetadata(com.google.android.exoplayer2.MediaMetadata.Builder)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ApicFrame","l":"populateMediaMetadata(MediaMetadata.Builder)","url":"populateMediaMetadata(com.google.android.exoplayer2.MediaMetadata.Builder)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"TextInformationFrame","l":"populateMediaMetadata(MediaMetadata.Builder)","url":"populateMediaMetadata(com.google.android.exoplayer2.MediaMetadata.Builder)"},{"p":"com.google.android.exoplayer2.extractor","c":"PositionHolder","l":"position"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekPoint","l":"position"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"position"},{"p":"com.google.android.exoplayer2.text.span","c":"RubySpan","l":"position"},{"p":"com.google.android.exoplayer2.text.span","c":"TextEmphasisSpan","l":"position"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"position"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheSpan","l":"position"},{"p":"com.google.android.exoplayer2.text.span","c":"TextAnnotation","l":"POSITION_AFTER"},{"p":"com.google.android.exoplayer2.text.span","c":"TextAnnotation","l":"POSITION_BEFORE"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceException","l":"POSITION_OUT_OF_RANGE"},{"p":"com.google.android.exoplayer2.text.span","c":"TextAnnotation","l":"POSITION_UNKNOWN"},{"p":"com.google.android.exoplayer2","c":"C","l":"POSITION_UNSET"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener.EventDispatcher","l":"positionAdvancing(long)"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"positionAnchor"},{"p":"com.google.android.exoplayer2.extractor","c":"PositionHolder","l":"PositionHolder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"positionInFirstPeriodUs"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"PositionInfo(Object, int, Object, int, long, long, int, int)","url":"%3Cinit%3E(java.lang.Object,int,java.lang.Object,int,long,long,int,int)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"positionInWindowUs"},{"p":"com.google.android.exoplayer2","c":"IllegalSeekPositionException","l":"positionMs"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"positionMs"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"positionResetCount"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"post(Runnable)","url":"post(java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"postAtFrontOfQueue(Runnable)","url":"postAtFrontOfQueue(java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"postDelayed(Runnable, long)","url":"postDelayed(java.lang.Runnable,long)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"postOrRun(Handler, Runnable)","url":"postOrRun(android.os.Handler,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.PpsData","l":"PpsData(int, int, boolean)","url":"%3Cinit%3E(int,int,boolean)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"preacquireSession(Looper, DrmSessionEventListener.EventDispatcher, Format)","url":"preacquireSession(android.os.Looper,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionManager","l":"preacquireSession(Looper, DrmSessionEventListener.EventDispatcher, Format)","url":"preacquireSession(android.os.Looper,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"preciseStart"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"preferredAudioLanguages"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"preferredAudioMimeTypes"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"preferredAudioRoleFlags"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"preferredTextLanguages"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"preferredTextRoleFlags"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"preferredVideoMimeTypes"},{"p":"com.google.android.exoplayer2","c":"Player","l":"prepare()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"prepare()"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"prepare()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionManager","l":"prepare()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"prepare()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"prepare()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"prepare()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"prepare()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"prepare(DownloadHelper.Callback)","url":"prepare(com.google.android.exoplayer2.offline.DownloadHelper.Callback)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"prepare(MediaPeriod.Callback, long)","url":"prepare(com.google.android.exoplayer2.source.MediaPeriod.Callback,long)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"prepare(MediaPeriod.Callback, long)","url":"prepare(com.google.android.exoplayer2.source.MediaPeriod.Callback,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"prepare(MediaPeriod.Callback, long)","url":"prepare(com.google.android.exoplayer2.source.MediaPeriod.Callback,long)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"prepare(MediaPeriod.Callback, long)","url":"prepare(com.google.android.exoplayer2.source.MediaPeriod.Callback,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"prepare(MediaPeriod.Callback, long)","url":"prepare(com.google.android.exoplayer2.source.MediaPeriod.Callback,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"prepare(MediaPeriod.Callback, long)","url":"prepare(com.google.android.exoplayer2.source.MediaPeriod.Callback,long)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"prepare(MediaSource, boolean, boolean)","url":"prepare(com.google.android.exoplayer2.source.MediaSource,boolean,boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"prepare(MediaSource, boolean, boolean)","url":"prepare(com.google.android.exoplayer2.source.MediaSource,boolean,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"prepare(MediaSource, boolean, boolean)","url":"prepare(com.google.android.exoplayer2.source.MediaSource,boolean,boolean)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"prepare(MediaSource)","url":"prepare(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"prepare(MediaSource)","url":"prepare(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"prepare(MediaSource)","url":"prepare(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.Prepare","l":"Prepare(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"prepareChildSource(T, MediaSource)","url":"prepareChildSource(T,com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"preparePeriod(MediaPeriod, long)","url":"preparePeriod(com.google.android.exoplayer2.source.MediaPeriod,long)"},{"p":"com.google.android.exoplayer2","c":"PlaybackPreparer","l":"preparePlayback()"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"prepareSource()"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"prepareSource(MediaSource.MediaSourceCaller, TransferListener)","url":"prepareSource(com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"prepareSource(MediaSource.MediaSourceCaller, TransferListener)","url":"prepareSource(com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"LoopingMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"preRelease()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"presentationStartTimeMs"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"presentationTimeOffsetUs"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"EventStream","l":"presentationTimesUs"},{"p":"com.google.android.exoplayer2","c":"SeekParameters","l":"PREVIOUS_SYNC"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"previous()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"previous()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"primaryTrackType"},{"p":"com.google.android.exoplayer2","c":"C","l":"PRIORITY_DOWNLOAD"},{"p":"com.google.android.exoplayer2","c":"C","l":"PRIORITY_PLAYBACK"},{"p":"com.google.android.exoplayer2.upstream","c":"PriorityDataSource","l":"PriorityDataSource(DataSource, PriorityTaskManager, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.util.PriorityTaskManager,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"PriorityDataSourceFactory","l":"PriorityDataSourceFactory(DataSource.Factory, PriorityTaskManager, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.util.PriorityTaskManager,int)"},{"p":"com.google.android.exoplayer2.util","c":"PriorityTaskManager","l":"PriorityTaskManager()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.util","c":"PriorityTaskManager.PriorityTooLowException","l":"PriorityTooLowException(int, int)","url":"%3Cinit%3E(int,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"PRIVATE_STREAM_1"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"PrivFrame","l":"privateData"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"PrivFrame","l":"PrivFrame(String, byte[])","url":"%3Cinit%3E(java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.util","c":"PriorityTaskManager","l":"proceed(int)"},{"p":"com.google.android.exoplayer2.util","c":"PriorityTaskManager","l":"proceedNonBlocking(int)"},{"p":"com.google.android.exoplayer2.util","c":"PriorityTaskManager","l":"proceedOrThrow(int)"},{"p":"com.google.android.exoplayer2.robolectric","c":"RandomizedMp3Decoder","l":"process(ByteBuffer, ByteBuffer)","url":"process(java.nio.ByteBuffer,java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"processOutputBuffer(long, long, MediaCodecAdapter, ByteBuffer, int, int, int, long, boolean, boolean, Format)","url":"processOutputBuffer(long,long,com.google.android.exoplayer2.mediacodec.MediaCodecAdapter,java.nio.ByteBuffer,int,int,int,long,boolean,boolean,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"processOutputBuffer(long, long, MediaCodecAdapter, ByteBuffer, int, int, int, long, boolean, boolean, Format)","url":"processOutputBuffer(long,long,com.google.android.exoplayer2.mediacodec.MediaCodecAdapter,java.nio.ByteBuffer,int,int,int,long,boolean,boolean,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"processOutputBuffer(long, long, MediaCodecAdapter, ByteBuffer, int, int, int, long, boolean, boolean, Format)","url":"processOutputBuffer(long,long,com.google.android.exoplayer2.mediacodec.MediaCodecAdapter,java.nio.ByteBuffer,int,int,int,long,boolean,boolean,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.video","c":"DolbyVisionConfig","l":"profile"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"profileIdc"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"programInformation"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ProgramInformation","l":"ProgramInformation(String, String, String, String, String)","url":"%3Cinit%3E(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"programSpliceFlag"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.Event","l":"programSpliceFlag"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"programSplicePlaybackPositionUs"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"programSplicePts"},{"p":"com.google.android.exoplayer2.transformer","c":"ProgressHolder","l":"progress"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer","l":"PROGRESS_STATE_AVAILABLE"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer","l":"PROGRESS_STATE_NO_TRANSFORMATION"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer","l":"PROGRESS_STATE_UNAVAILABLE"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer","l":"PROGRESS_STATE_WAITING_FOR_AVAILABILITY"},{"p":"com.google.android.exoplayer2.transformer","c":"ProgressHolder","l":"ProgressHolder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.offline","c":"ProgressiveDownloader","l":"ProgressiveDownloader(MediaItem, CacheDataSource.Factory, Executor)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.offline","c":"ProgressiveDownloader","l":"ProgressiveDownloader(MediaItem, CacheDataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory)"},{"p":"com.google.android.exoplayer2.offline","c":"ProgressiveDownloader","l":"ProgressiveDownloader(Uri, String, CacheDataSource.Factory, Executor)","url":"%3Cinit%3E(android.net.Uri,java.lang.String,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.offline","c":"ProgressiveDownloader","l":"ProgressiveDownloader(Uri, String, CacheDataSource.Factory)","url":"%3Cinit%3E(android.net.Uri,java.lang.String,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory)"},{"p":"com.google.android.exoplayer2","c":"C","l":"PROJECTION_CUBEMAP"},{"p":"com.google.android.exoplayer2","c":"C","l":"PROJECTION_EQUIRECTANGULAR"},{"p":"com.google.android.exoplayer2","c":"C","l":"PROJECTION_MESH"},{"p":"com.google.android.exoplayer2","c":"C","l":"PROJECTION_RECTANGULAR"},{"p":"com.google.android.exoplayer2","c":"Format","l":"projectionData"},{"p":"com.google.android.exoplayer2.drm","c":"WidevineUtil","l":"PROPERTY_LICENSE_DURATION_REMAINING"},{"p":"com.google.android.exoplayer2.drm","c":"WidevineUtil","l":"PROPERTY_PLAYBACK_DURATION_REMAINING"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest","l":"protectionElement"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.ProtectionElement","l":"ProtectionElement(UUID, byte[], TrackEncryptionBox[])","url":"%3Cinit%3E(java.util.UUID,byte[],com.google.android.exoplayer2.extractor.mp4.TrackEncryptionBox[])"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"protectionSchemes"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"provideKeyResponse(byte[], byte[])","url":"provideKeyResponse(byte[],byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"provideKeyResponse(byte[], byte[])","url":"provideKeyResponse(byte[],byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"provideKeyResponse(byte[], byte[])","url":"provideKeyResponse(byte[],byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"provideKeyResponse(byte[], byte[])","url":"provideKeyResponse(byte[],byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"provideProvisionResponse(byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"provideProvisionResponse(byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"provideProvisionResponse(byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"provideProvisionResponse(byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.ProvisionRequest","l":"ProvisionRequest(byte[], String)","url":"%3Cinit%3E(byte[],java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"PS"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"PsExtractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"PsExtractor(TimestampAdjuster)","url":"%3Cinit%3E(com.google.android.exoplayer2.util.TimestampAdjuster)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"PrivateCommand","l":"ptsAdjustment"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"TimeSignalCommand","l":"ptsTime"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"ptsToUs(long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"publishTimeMs"},{"p":"com.google.android.exoplayer2.ui","c":"AdOverlayInfo","l":"purpose"},{"p":"com.google.android.exoplayer2.ui","c":"AdOverlayInfo","l":"PURPOSE_CLOSE_AD"},{"p":"com.google.android.exoplayer2.ui","c":"AdOverlayInfo","l":"PURPOSE_CONTROLS"},{"p":"com.google.android.exoplayer2.ui","c":"AdOverlayInfo","l":"PURPOSE_NOT_VISIBLE"},{"p":"com.google.android.exoplayer2.ui","c":"AdOverlayInfo","l":"PURPOSE_OTHER"},{"p":"com.google.android.exoplayer2.util","c":"BundleUtil","l":"putBinder(Bundle, String, IBinder)","url":"putBinder(android.os.Bundle,java.lang.String,android.os.IBinder)"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloadIndex","l":"putDownload(Download)","url":"putDownload(com.google.android.exoplayer2.offline.Download)"},{"p":"com.google.android.exoplayer2.offline","c":"WritableDownloadIndex","l":"putDownload(Download)","url":"putDownload(com.google.android.exoplayer2.offline.Download)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"putInt(int, int)","url":"putInt(int,int)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"queryKeyStatus()"},{"p":"com.google.android.exoplayer2.drm","c":"ErrorStateDrmSession","l":"queryKeyStatus()"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"queryKeyStatus(byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"queryKeyStatus(byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"queryKeyStatus(byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"queryKeyStatus(byte[])"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor","l":"queueEndOfStream()"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"queueEndOfStream()"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"queueEndOfStream()"},{"p":"com.google.android.exoplayer2.ext.gvr","c":"GvrAudioProcessor","l":"queueEndOfStream()"},{"p":"com.google.android.exoplayer2.util","c":"ListenerSet","l":"queueEvent(int, ListenerSet.Event)","url":"queueEvent(int,com.google.android.exoplayer2.util.ListenerSet.Event)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor","l":"queueInput(ByteBuffer)","url":"queueInput(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"queueInput(ByteBuffer)","url":"queueInput(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"queueInput(ByteBuffer)","url":"queueInput(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.audio","c":"TeeAudioProcessor","l":"queueInput(ByteBuffer)","url":"queueInput(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.ext.gvr","c":"GvrAudioProcessor","l":"queueInput(ByteBuffer)","url":"queueInput(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.decoder","c":"Decoder","l":"queueInputBuffer(I)"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleDecoder","l":"queueInputBuffer(I)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"queueInputBuffer(int, int, int, long, int)","url":"queueInputBuffer(int,int,int,long,int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"queueInputBuffer(int, int, int, long, int)","url":"queueInputBuffer(int,int,int,long,int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"queueSecureInputBuffer(int, int, CryptoInfo, long, int)","url":"queueSecureInputBuffer(int,int,com.google.android.exoplayer2.decoder.CryptoInfo,long,int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"queueSecureInputBuffer(int, int, CryptoInfo, long, int)","url":"queueSecureInputBuffer(int,int,com.google.android.exoplayer2.decoder.CryptoInfo,long,int)"},{"p":"com.google.android.exoplayer2.robolectric","c":"RandomizedMp3Decoder","l":"RandomizedMp3Decoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.trackselection","c":"RandomTrackSelection","l":"RandomTrackSelection(TrackGroup, int[], int, Random)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroup,int[],int,java.util.Random)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"RangedUri","l":"RangedUri(String, long, long)","url":"%3Cinit%3E(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2","c":"C","l":"RATE_UNSET"},{"p":"com.google.android.exoplayer2","c":"Rating","l":"RATING_UNSET"},{"p":"com.google.android.exoplayer2.upstream","c":"RawResourceDataSource","l":"RAW_RESOURCE_SCHEME"},{"p":"com.google.android.exoplayer2.extractor.rawcc","c":"RawCcExtractor","l":"RawCcExtractor(Format)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyInfo","l":"rawMetadata"},{"p":"com.google.android.exoplayer2.upstream","c":"RawResourceDataSource","l":"RawResourceDataSource(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.upstream","c":"RawResourceDataSource.RawResourceDataSourceException","l":"RawResourceDataSourceException(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"RawResourceDataSource.RawResourceDataSourceException","l":"RawResourceDataSourceException(Throwable)","url":"%3Cinit%3E(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceInputStream","l":"read()"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.ext.rtmp","c":"RtmpDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"InputReaderAdapterV30","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"AssetDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"ByteArrayDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"ContentDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataReader","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSchemeDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceInputStream","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DummyDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"PriorityDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"RawResourceDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"ResolvingDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"StatsDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"TeeDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"UdpDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesCipherDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceInputStream","l":"read(byte[])"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"read(ByteBuffer)","url":"read(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor","c":"Extractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.amr","c":"AmrExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.flac","c":"FlacExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.flv","c":"FlvExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.jpeg","c":"JpegExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.ogg","c":"OggExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.rawcc","c":"RawCcExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Extractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Extractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.wav","c":"WavExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.source.hls","c":"WebvttExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BundledChunkExtractor","l":"read(ExtractorInput)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkExtractor","l":"read(ExtractorInput)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaParserChunkExtractor","l":"read(ExtractorInput)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.source.hls","c":"BundledHlsMediaChunkExtractor","l":"read(ExtractorInput)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaChunkExtractor","l":"read(ExtractorInput)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.source.hls","c":"MediaParserHlsMediaChunkExtractor","l":"read(ExtractorInput)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"read(FormatHolder, DecoderInputBuffer, int, boolean)","url":"read(com.google.android.exoplayer2.FormatHolder,com.google.android.exoplayer2.decoder.DecoderInputBuffer,int,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"BundledExtractorsAdapter","l":"read(PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.source","c":"MediaParserExtractorAdapter","l":"read(PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaExtractor","l":"read(PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisBitArray","l":"readBit()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"readBit()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableNalUnitBitArray","l":"readBit()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"readBits(byte[], int, int)","url":"readBits(byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisBitArray","l":"readBits(int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"readBits(int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableNalUnitBitArray","l":"readBits(int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"readBitsToLong(int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"readBoolean(Parcel)","url":"readBoolean(android.os.Parcel)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"readBytes(byte[], int, int)","url":"readBytes(byte[],int,int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readBytes(byte[], int, int)","url":"readBytes(byte[],int,int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readBytes(ByteBuffer, int)","url":"readBytes(java.nio.ByteBuffer,int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readBytes(ParsableBitArray, int)","url":"readBytes(com.google.android.exoplayer2.util.ParsableBitArray,int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"readBytesAsString(int, Charset)","url":"readBytesAsString(int,java.nio.charset.Charset)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"readBytesAsString(int)"},{"p":"com.google.android.exoplayer2.source","c":"EmptySampleStream","l":"readData(FormatHolder, DecoderInputBuffer, int)","url":"readData(com.google.android.exoplayer2.FormatHolder,com.google.android.exoplayer2.decoder.DecoderInputBuffer,int)"},{"p":"com.google.android.exoplayer2.source","c":"SampleStream","l":"readData(FormatHolder, DecoderInputBuffer, int)","url":"readData(com.google.android.exoplayer2.FormatHolder,com.google.android.exoplayer2.decoder.DecoderInputBuffer,int)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"readData(FormatHolder, DecoderInputBuffer, int)","url":"readData(com.google.android.exoplayer2.FormatHolder,com.google.android.exoplayer2.decoder.DecoderInputBuffer,int)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream.EmbeddedSampleStream","l":"readData(FormatHolder, DecoderInputBuffer, int)","url":"readData(com.google.android.exoplayer2.FormatHolder,com.google.android.exoplayer2.decoder.DecoderInputBuffer,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"readData(FormatHolder, DecoderInputBuffer, int)","url":"readData(com.google.android.exoplayer2.FormatHolder,com.google.android.exoplayer2.decoder.DecoderInputBuffer,int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readDelimiterTerminatedString(char)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"readDiscontinuity()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"readDiscontinuity()"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"readDiscontinuity()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"readDiscontinuity()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"readDiscontinuity()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"readDiscontinuity()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readDouble()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"readExactly(DataSource, int)","url":"readExactly(com.google.android.exoplayer2.upstream.DataSource,int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readFloat()"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacFrameReader","l":"readFrameBlockSizeSamplesFromKey(ParsableByteArray, int)","url":"readFrameBlockSizeSamplesFromKey(com.google.android.exoplayer2.util.ParsableByteArray,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"readFully(byte[], int, int, boolean)","url":"readFully(byte[],int,int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"readFully(byte[], int, int, boolean)","url":"readFully(byte[],int,int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"readFully(byte[], int, int, boolean)","url":"readFully(byte[],int,int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"readFully(byte[], int, int, boolean)","url":"readFully(byte[],int,int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"readFully(byte[], int, int)","url":"readFully(byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"readFully(byte[], int, int)","url":"readFully(byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"readFully(byte[], int, int)","url":"readFully(byte[],int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"readFully(byte[], int, int)","url":"readFully(byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorUtil","l":"readFullyQuietly(ExtractorInput, byte[], int, int)","url":"readFullyQuietly(com.google.android.exoplayer2.extractor.ExtractorInput,byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacMetadataReader","l":"readId3Metadata(ExtractorInput, boolean)","url":"readId3Metadata(com.google.android.exoplayer2.extractor.ExtractorInput,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readInt()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readInt24()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readLine()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readLittleEndianInt()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readLittleEndianInt24()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readLittleEndianLong()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readLittleEndianShort()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readLittleEndianUnsignedInt()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readLittleEndianUnsignedInt24()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readLittleEndianUnsignedIntToInt()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readLittleEndianUnsignedShort()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readLong()"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacMetadataReader","l":"readMetadataBlock(ExtractorInput, FlacMetadataReader.FlacStreamMetadataHolder)","url":"readMetadataBlock(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.FlacMetadataReader.FlacStreamMetadataHolder)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readNullTerminatedString()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readNullTerminatedString(int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsUtil","l":"readPcrFromPacket(ParsableByteArray, int, int)","url":"readPcrFromPacket(com.google.android.exoplayer2.util.ParsableByteArray,int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacMetadataReader","l":"readSeekTableMetadataBlock(ParsableByteArray)","url":"readSeekTableMetadataBlock(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readShort()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableNalUnitBitArray","l":"readSignedExpGolombCodedInt()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"readSource(FormatHolder, DecoderInputBuffer, int)","url":"readSource(com.google.android.exoplayer2.FormatHolder,com.google.android.exoplayer2.decoder.DecoderInputBuffer,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacMetadataReader","l":"readStreamMarker(ExtractorInput)","url":"readStreamMarker(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readString(int, Charset)","url":"readString(int,java.nio.charset.Charset)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readString(int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readSynchSafeInt()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"readToEnd(DataSource)","url":"readToEnd(com.google.android.exoplayer2.upstream.DataSource)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readUnsignedByte()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableNalUnitBitArray","l":"readUnsignedExpGolombCodedInt()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readUnsignedFixedPoint1616()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readUnsignedInt()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readUnsignedInt24()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readUnsignedIntToInt()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readUnsignedLongToLong()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readUnsignedShort()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readUtf8EncodedLong()"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil","l":"readVorbisCommentHeader(ParsableByteArray, boolean, boolean)","url":"readVorbisCommentHeader(com.google.android.exoplayer2.util.ParsableByteArray,boolean,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil","l":"readVorbisCommentHeader(ParsableByteArray)","url":"readVorbisCommentHeader(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil","l":"readVorbisIdentificationHeader(ParsableByteArray)","url":"readVorbisIdentificationHeader(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil","l":"readVorbisModes(ParsableByteArray, int)","url":"readVorbisModes(com.google.android.exoplayer2.util.ParsableByteArray,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"realtimeMs"},{"p":"com.google.android.exoplayer2.drm","c":"UnsupportedDrmException","l":"reason"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource.IllegalClippingException","l":"reason"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource.IllegalMergeException","l":"reason"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceException","l":"reason"},{"p":"com.google.android.exoplayer2.drm","c":"UnsupportedDrmException","l":"REASON_INSTANTIATION_ERROR"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource.IllegalClippingException","l":"REASON_INVALID_PERIOD_COUNT"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource.IllegalClippingException","l":"REASON_NOT_SEEKABLE_TO_START"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource.IllegalMergeException","l":"REASON_PERIOD_COUNT_MISMATCH"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource.IllegalClippingException","l":"REASON_START_EXCEEDS_END"},{"p":"com.google.android.exoplayer2.drm","c":"UnsupportedDrmException","l":"REASON_UNSUPPORTED_SCHEME"},{"p":"com.google.android.exoplayer2.ui","c":"AdOverlayInfo","l":"reasonDetail"},{"p":"com.google.android.exoplayer2.source.hls","c":"BundledHlsMediaChunkExtractor","l":"recreate()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaChunkExtractor","l":"recreate()"},{"p":"com.google.android.exoplayer2.source.hls","c":"MediaParserHlsMediaChunkExtractor","l":"recreate()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"recursiveDelete(File)","url":"recursiveDelete(java.io.File)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"reevaluateBuffer(long)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeSequenceableLoader","l":"reevaluateBuffer(long)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"reevaluateBuffer(long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"reevaluateBuffer(long)"},{"p":"com.google.android.exoplayer2.source","c":"SequenceableLoader","l":"reevaluateBuffer(long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"reevaluateBuffer(long)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"reevaluateBuffer(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"reevaluateBuffer(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"reevaluateBuffer(long)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"refreshPlaylist(Uri)","url":"refreshPlaylist(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"refreshPlaylist(Uri)","url":"refreshPlaylist(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"refreshSourceInfo(Timeline)","url":"refreshSourceInfo(com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioCapabilitiesReceiver","l":"register()"},{"p":"com.google.android.exoplayer2.util","c":"NetworkTypeObserver","l":"register(NetworkTypeObserver.Listener)","url":"register(com.google.android.exoplayer2.util.NetworkTypeObserver.Listener)"},{"p":"com.google.android.exoplayer2.robolectric","c":"PlaybackOutput","l":"register(SimpleExoPlayer, CapturingRenderersFactory)","url":"register(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.testutil.CapturingRenderersFactory)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"registerCustomCommandReceiver(MediaSessionConnector.CommandReceiver)","url":"registerCustomCommandReceiver(com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.CommandReceiver)"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"registerCustomMimeType(String, String, int)","url":"registerCustomMimeType(java.lang.String,java.lang.String,int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayerLibraryInfo","l":"registeredModules()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayerLibraryInfo","l":"registerModule(String)","url":"registerModule(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource","l":"REJECT_PAYWALL_TYPES"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.SegmentBase","l":"relativeDiscontinuitySequence"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.SegmentBase","l":"relativeStartTimeUs"},{"p":"com.google.android.exoplayer2","c":"MediaItem.ClippingProperties","l":"relativeToDefaultPosition"},{"p":"com.google.android.exoplayer2","c":"MediaItem.ClippingProperties","l":"relativeToLiveWindow"},{"p":"com.google.android.exoplayer2","c":"Player","l":"release()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"release()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"release()"},{"p":"com.google.android.exoplayer2.decoder","c":"Decoder","l":"release()"},{"p":"com.google.android.exoplayer2.decoder","c":"OutputBuffer","l":"release()"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleDecoder","l":"release()"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleOutputBuffer","l":"release()"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"release()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionManager","l":"release()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionManager.DrmSessionReference","l":"release()"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"release()"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"release()"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"release()"},{"p":"com.google.android.exoplayer2.drm","c":"OfflineLicenseHelper","l":"release()"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Gav1Decoder","l":"release()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"release()"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacDecoder","l":"release()"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"release()"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusDecoder","l":"release()"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxDecoder","l":"release()"},{"p":"com.google.android.exoplayer2.extractor","c":"Extractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.amr","c":"AmrExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.flac","c":"FlacExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.flv","c":"FlvExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.jpeg","c":"JpegExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.ogg","c":"OggExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.rawcc","c":"RawCcExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Extractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Extractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.wav","c":"WavExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"release()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"release()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"release()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"release()"},{"p":"com.google.android.exoplayer2.source","c":"BundledExtractorsAdapter","l":"release()"},{"p":"com.google.android.exoplayer2.source","c":"MediaParserExtractorAdapter","l":"release()"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"release()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsLoader","l":"release()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BundledChunkExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"release()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream.EmbeddedSampleStream","l":"release()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSource","l":"release()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaParserChunkExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"release()"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler","l":"release()"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler.PlayerTrackEmsgHandler","l":"release()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"release()"},{"p":"com.google.android.exoplayer2.source.hls","c":"WebvttExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource","l":"release()"},{"p":"com.google.android.exoplayer2.testutil","c":"DummyMainThread","l":"release()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"release()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource","l":"release()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"release()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"release()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"release()"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"release()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"release()"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea608Decoder","l":"release()"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"release()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"release()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CachedRegionTracker","l":"release()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"release()"},{"p":"com.google.android.exoplayer2.util","c":"EGLSurfaceTexture","l":"release()"},{"p":"com.google.android.exoplayer2.util","c":"ListenerSet","l":"release()"},{"p":"com.google.android.exoplayer2.video","c":"DummySurface","l":"release()"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"release()"},{"p":"com.google.android.exoplayer2.upstream","c":"Allocator","l":"release(Allocation)","url":"release(com.google.android.exoplayer2.upstream.Allocation)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultAllocator","l":"release(Allocation)","url":"release(com.google.android.exoplayer2.upstream.Allocation)"},{"p":"com.google.android.exoplayer2.upstream","c":"Allocator","l":"release(Allocation[])","url":"release(com.google.android.exoplayer2.upstream.Allocation[])"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultAllocator","l":"release(Allocation[])","url":"release(com.google.android.exoplayer2.upstream.Allocation[])"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"release(ChunkSampleStream.ReleaseCallback)","url":"release(com.google.android.exoplayer2.source.chunk.ChunkSampleStream.ReleaseCallback)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"release(DrmSessionEventListener.EventDispatcher)","url":"release(com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2.drm","c":"ErrorStateDrmSession","l":"release(DrmSessionEventListener.EventDispatcher)","url":"release(com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"release(Loader.ReleaseCallback)","url":"release(com.google.android.exoplayer2.upstream.Loader.ReleaseCallback)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"releaseChildSource(T)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"releaseCodec()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"releaseCount"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"releaseDecoder()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"releaseHoleSpan(CacheSpan)","url":"releaseHoleSpan(com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"releaseHoleSpan(CacheSpan)","url":"releaseHoleSpan(com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.drm","c":"OfflineLicenseHelper","l":"releaseLicense(byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaSource","l":"releaseMediaPeriod(MediaPeriod)","url":"releaseMediaPeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"releaseMediaPeriod(MediaPeriod)","url":"releaseMediaPeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"releaseOutputBuffer(int, boolean)","url":"releaseOutputBuffer(int,boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"releaseOutputBuffer(int, boolean)","url":"releaseOutputBuffer(int,boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"releaseOutputBuffer(int, long)","url":"releaseOutputBuffer(int,long)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"releaseOutputBuffer(int, long)","url":"releaseOutputBuffer(int,long)"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleDecoder","l":"releaseOutputBuffer(O)"},{"p":"com.google.android.exoplayer2.decoder","c":"OutputBuffer.Owner","l":"releaseOutputBuffer(S)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Gav1Decoder","l":"releaseOutputBuffer(VideoDecoderOutputBuffer)","url":"releaseOutputBuffer(com.google.android.exoplayer2.video.VideoDecoderOutputBuffer)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxDecoder","l":"releaseOutputBuffer(VideoDecoderOutputBuffer)","url":"releaseOutputBuffer(com.google.android.exoplayer2.video.VideoDecoderOutputBuffer)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"releasePeriod()"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source","c":"LoopingMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"releaseSource()"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"releaseSource(MediaSource.MediaSourceCaller)","url":"releaseSource(com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"releaseSource(MediaSource.MediaSourceCaller)","url":"releaseSource(com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.offline","c":"Downloader","l":"remove()"},{"p":"com.google.android.exoplayer2.offline","c":"ProgressiveDownloader","l":"remove()"},{"p":"com.google.android.exoplayer2.offline","c":"SegmentDownloader","l":"remove()"},{"p":"com.google.android.exoplayer2.util","c":"IntArrayQueue","l":"remove()"},{"p":"com.google.android.exoplayer2.util","c":"CopyOnWriteMultiset","l":"remove(E)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor.QueueDataAdapter","l":"remove(int)"},{"p":"com.google.android.exoplayer2.util","c":"PriorityTaskManager","l":"remove(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.RequestProperties","l":"remove(String)","url":"remove(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadataMutations","l":"remove(String)","url":"remove(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"ListenerSet","l":"remove(T)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"removeAllDownloads()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"removeAnalyticsListener(AnalyticsListener)","url":"removeAnalyticsListener(com.google.android.exoplayer2.analytics.AnalyticsListener)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioComponent","l":"removeAudioListener(AudioListener)","url":"removeAudioListener(com.google.android.exoplayer2.audio.AudioListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"removeAudioListener(AudioListener)","url":"removeAudioListener(com.google.android.exoplayer2.audio.AudioListener)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"removeAudioOffloadListener(ExoPlayer.AudioOffloadListener)","url":"removeAudioOffloadListener(com.google.android.exoplayer2.ExoPlayer.AudioOffloadListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"removeAudioOffloadListener(ExoPlayer.AudioOffloadListener)","url":"removeAudioOffloadListener(com.google.android.exoplayer2.ExoPlayer.AudioOffloadListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"removeAudioOffloadListener(ExoPlayer.AudioOffloadListener)","url":"removeAudioOffloadListener(com.google.android.exoplayer2.ExoPlayer.AudioOffloadListener)"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"removeCallbacksAndMessages(Object)","url":"removeCallbacksAndMessages(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.DeviceComponent","l":"removeDeviceListener(DeviceListener)","url":"removeDeviceListener(com.google.android.exoplayer2.device.DeviceListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"removeDeviceListener(DeviceListener)","url":"removeDeviceListener(com.google.android.exoplayer2.device.DeviceListener)"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloadIndex","l":"removeDownload(String)","url":"removeDownload(java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"removeDownload(String)","url":"removeDownload(java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"WritableDownloadIndex","l":"removeDownload(String)","url":"removeDownload(java.lang.String)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"removeDrmEventListener(DrmSessionEventListener)","url":"removeDrmEventListener(com.google.android.exoplayer2.drm.DrmSessionEventListener)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"removeDrmEventListener(DrmSessionEventListener)","url":"removeDrmEventListener(com.google.android.exoplayer2.drm.DrmSessionEventListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"BandwidthMeter","l":"removeEventListener(BandwidthMeter.EventListener)","url":"removeEventListener(com.google.android.exoplayer2.upstream.BandwidthMeter.EventListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"removeEventListener(BandwidthMeter.EventListener)","url":"removeEventListener(com.google.android.exoplayer2.upstream.BandwidthMeter.EventListener)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener.EventDispatcher","l":"removeEventListener(DrmSessionEventListener)","url":"removeEventListener(com.google.android.exoplayer2.drm.DrmSessionEventListener)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"removeEventListener(MediaSourceEventListener)","url":"removeEventListener(com.google.android.exoplayer2.source.MediaSourceEventListener)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"removeEventListener(MediaSourceEventListener)","url":"removeEventListener(com.google.android.exoplayer2.source.MediaSourceEventListener)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"removeEventListener(MediaSourceEventListener)","url":"removeEventListener(com.google.android.exoplayer2.source.MediaSourceEventListener)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"removeItem(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"removeListener(AnalyticsListener)","url":"removeListener(com.google.android.exoplayer2.analytics.AnalyticsListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"BandwidthMeter.EventListener.EventDispatcher","l":"removeListener(BandwidthMeter.EventListener)","url":"removeListener(com.google.android.exoplayer2.upstream.BandwidthMeter.EventListener)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"removeListener(DownloadManager.Listener)","url":"removeListener(com.google.android.exoplayer2.offline.DownloadManager.Listener)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"removeListener(HlsPlaylistTracker.PlaylistEventListener)","url":"removeListener(com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker.PlaylistEventListener)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"removeListener(HlsPlaylistTracker.PlaylistEventListener)","url":"removeListener(com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker.PlaylistEventListener)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"removeListener(Player.EventListener)","url":"removeListener(com.google.android.exoplayer2.Player.EventListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"removeListener(Player.EventListener)","url":"removeListener(com.google.android.exoplayer2.Player.EventListener)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"removeListener(Player.EventListener)","url":"removeListener(com.google.android.exoplayer2.Player.EventListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"removeListener(Player.EventListener)","url":"removeListener(com.google.android.exoplayer2.Player.EventListener)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"removeListener(Player.Listener)","url":"removeListener(com.google.android.exoplayer2.Player.Listener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"removeListener(Player.Listener)","url":"removeListener(com.google.android.exoplayer2.Player.Listener)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"removeListener(Player.Listener)","url":"removeListener(com.google.android.exoplayer2.Player.Listener)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"removeListener(Player.Listener)","url":"removeListener(com.google.android.exoplayer2.Player.Listener)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"removeListener(String, Cache.Listener)","url":"removeListener(java.lang.String,com.google.android.exoplayer2.upstream.cache.Cache.Listener)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"removeListener(String, Cache.Listener)","url":"removeListener(java.lang.String,com.google.android.exoplayer2.upstream.cache.Cache.Listener)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"removeListener(TimeBar.OnScrubListener)","url":"removeListener(com.google.android.exoplayer2.ui.TimeBar.OnScrubListener)"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar","l":"removeListener(TimeBar.OnScrubListener)","url":"removeListener(com.google.android.exoplayer2.ui.TimeBar.OnScrubListener)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"removeMediaItem(int)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"removeMediaItem(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"removeMediaItem(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.RemoveMediaItem","l":"RemoveMediaItem(String, int)","url":"%3Cinit%3E(java.lang.String,int)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"removeMediaItems(int, int)","url":"removeMediaItems(int,int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"removeMediaItems(int, int)","url":"removeMediaItems(int,int)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"removeMediaItems(int, int)","url":"removeMediaItems(int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"removeMediaItems(int, int)","url":"removeMediaItems(int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"removeMediaItems(int, int)","url":"removeMediaItems(int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.RemoveMediaItems","l":"RemoveMediaItems(String, int, int)","url":"%3Cinit%3E(java.lang.String,int,int)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"removeMediaSource(int, Handler, Runnable)","url":"removeMediaSource(int,android.os.Handler,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"removeMediaSource(int)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"removeMediaSourceRange(int, int, Handler, Runnable)","url":"removeMediaSourceRange(int,int,android.os.Handler,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"removeMediaSourceRange(int, int)","url":"removeMediaSourceRange(int,int)"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"removeMessages(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.MetadataComponent","l":"removeMetadataOutput(MetadataOutput)","url":"removeMetadataOutput(com.google.android.exoplayer2.metadata.MetadataOutput)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"removeMetadataOutput(MetadataOutput)","url":"removeMetadataOutput(com.google.android.exoplayer2.metadata.MetadataOutput)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"removePlaylistItem(int)"},{"p":"com.google.android.exoplayer2.util","c":"UriUtil","l":"removeQueryParameter(Uri, String)","url":"removeQueryParameter(android.net.Uri,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"removeRange(List, int, int)","url":"removeRange(java.util.List,int,int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"removeResource(String)","url":"removeResource(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"removeResource(String)","url":"removeResource(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"removeSpan(CacheSpan)","url":"removeSpan(com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"removeSpan(CacheSpan)","url":"removeSpan(com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.TextComponent","l":"removeTextOutput(TextOutput)","url":"removeTextOutput(com.google.android.exoplayer2.text.TextOutput)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"removeTextOutput(TextOutput)","url":"removeTextOutput(com.google.android.exoplayer2.text.TextOutput)"},{"p":"com.google.android.exoplayer2.database","c":"VersionTable","l":"removeVersion(SQLiteDatabase, int, String)","url":"removeVersion(android.database.sqlite.SQLiteDatabase,int,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"removeVideoListener(VideoListener)","url":"removeVideoListener(com.google.android.exoplayer2.video.VideoListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"removeVideoListener(VideoListener)","url":"removeVideoListener(com.google.android.exoplayer2.video.VideoListener)"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView","l":"removeVideoSurfaceListener(SphericalGLSurfaceView.VideoSurfaceListener)","url":"removeVideoSurfaceListener(com.google.android.exoplayer2.video.spherical.SphericalGLSurfaceView.VideoSurfaceListener)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"removeVisibilityListener(PlayerControlView.VisibilityListener)","url":"removeVisibilityListener(com.google.android.exoplayer2.ui.PlayerControlView.VisibilityListener)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"removeVisibilityListener(StyledPlayerControlView.VisibilityListener)","url":"removeVisibilityListener(com.google.android.exoplayer2.ui.StyledPlayerControlView.VisibilityListener)"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"render(long, long)","url":"render(long,long)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"render(long, long)","url":"render(long,long)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"render(long, long)","url":"render(long,long)"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataRenderer","l":"render(long, long)","url":"render(long,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"render(long, long)","url":"render(long,long)"},{"p":"com.google.android.exoplayer2.text","c":"TextRenderer","l":"render(long, long)","url":"render(long,long)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"render(long, long)","url":"render(long,long)"},{"p":"com.google.android.exoplayer2.video.spherical","c":"CameraMotionRenderer","l":"render(long, long)","url":"render(long,long)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener.EventDispatcher","l":"renderedFirstFrame(Object)","url":"renderedFirstFrame(java.lang.Object)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"renderedOutputBufferCount"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"RENDERER_SUPPORT_EXCEEDS_CAPABILITIES_TRACKS"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"RENDERER_SUPPORT_NO_TRACKS"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"RENDERER_SUPPORT_PLAYABLE_TRACKS"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"RENDERER_SUPPORT_UNSUPPORTED_TRACKS"},{"p":"com.google.android.exoplayer2","c":"RendererConfiguration","l":"RendererConfiguration(boolean)","url":"%3Cinit%3E(boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectorResult","l":"rendererConfigurations"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"rendererFormat"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"rendererFormatSupport"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"rendererIndex"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"rendererName"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"renderers"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"renderOutputBuffer(MediaCodecAdapter, int, long)","url":"renderOutputBuffer(com.google.android.exoplayer2.mediacodec.MediaCodecAdapter,int,long)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"renderOutputBuffer(VideoDecoderOutputBuffer, long, Format)","url":"renderOutputBuffer(com.google.android.exoplayer2.video.VideoDecoderOutputBuffer,long,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Libgav1VideoRenderer","l":"renderOutputBufferToSurface(VideoDecoderOutputBuffer, Surface)","url":"renderOutputBufferToSurface(com.google.android.exoplayer2.video.VideoDecoderOutputBuffer,android.view.Surface)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"LibvpxVideoRenderer","l":"renderOutputBufferToSurface(VideoDecoderOutputBuffer, Surface)","url":"renderOutputBufferToSurface(com.google.android.exoplayer2.video.VideoDecoderOutputBuffer,android.view.Surface)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"renderOutputBufferToSurface(VideoDecoderOutputBuffer, Surface)","url":"renderOutputBufferToSurface(com.google.android.exoplayer2.video.VideoDecoderOutputBuffer,android.view.Surface)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"renderOutputBufferV21(MediaCodecAdapter, int, long, long)","url":"renderOutputBufferV21(com.google.android.exoplayer2.mediacodec.MediaCodecAdapter,int,long,long)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"renderToEndOfStream()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"renderToEndOfStream()"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Gav1Decoder","l":"renderToSurface(VideoDecoderOutputBuffer, Surface)","url":"renderToSurface(com.google.android.exoplayer2.video.VideoDecoderOutputBuffer,android.view.Surface)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxDecoder","l":"renderToSurface(VideoDecoderOutputBuffer, Surface)","url":"renderToSurface(com.google.android.exoplayer2.video.VideoDecoderOutputBuffer,android.view.Surface)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Rendition","l":"Rendition(Uri, Format, String, String)","url":"%3Cinit%3E(android.net.Uri,com.google.android.exoplayer2.Format,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.RenditionReport","l":"RenditionReport(Uri, long, int)","url":"%3Cinit%3E(android.net.Uri,long,int)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"renditionReports"},{"p":"com.google.android.exoplayer2.drm","c":"OfflineLicenseHelper","l":"renewLicense(byte[])"},{"p":"com.google.android.exoplayer2","c":"Player","l":"REPEAT_MODE_ALL"},{"p":"com.google.android.exoplayer2","c":"Player","l":"REPEAT_MODE_OFF"},{"p":"com.google.android.exoplayer2","c":"Player","l":"REPEAT_MODE_ONE"},{"p":"com.google.android.exoplayer2.util","c":"RepeatModeUtil","l":"REPEAT_TOGGLE_MODE_ALL"},{"p":"com.google.android.exoplayer2.util","c":"RepeatModeUtil","l":"REPEAT_TOGGLE_MODE_NONE"},{"p":"com.google.android.exoplayer2.util","c":"RepeatModeUtil","l":"REPEAT_TOGGLE_MODE_ONE"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"repeat(Action, long)","url":"repeat(com.google.android.exoplayer2.testutil.Action,long)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"RepeatModeActionProvider","l":"RepeatModeActionProvider(Context, int)","url":"%3Cinit%3E(android.content.Context,int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"RepeatModeActionProvider","l":"RepeatModeActionProvider(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource","l":"replaceManifestUri(Uri)","url":"replaceManifestUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"replaceOutputBuffer(int)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"replacePlaylistItem(int, MediaItem)","url":"replacePlaylistItem(int,androidx.media2.common.MediaItem)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"replaceSession(DrmSession, DrmSession)","url":"replaceSession(com.google.android.exoplayer2.drm.DrmSession,com.google.android.exoplayer2.drm.DrmSession)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"replaceStream(Format[], SampleStream, long, long)","url":"replaceStream(com.google.android.exoplayer2.Format[],com.google.android.exoplayer2.source.SampleStream,long,long)"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"replaceStream(Format[], SampleStream, long, long)","url":"replaceStream(com.google.android.exoplayer2.Format[],com.google.android.exoplayer2.source.SampleStream,long,long)"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"replaceStream(Format[], SampleStream, long, long)","url":"replaceStream(com.google.android.exoplayer2.Format[],com.google.android.exoplayer2.source.SampleStream,long,long)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"replaceTrackSelections(int, DefaultTrackSelector.Parameters)","url":"replaceTrackSelections(int,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener.EventDispatcher","l":"reportVideoFrameProcessingOffset(long, int)","url":"reportVideoFrameProcessingOffset(long,int)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationHolder","l":"representation"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"representationHolders"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser.RepresentationInfo","l":"RepresentationInfo(Format, String, SegmentBase, String, ArrayList, ArrayList, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format,java.lang.String,com.google.android.exoplayer2.source.dash.manifest.SegmentBase,java.lang.String,java.util.ArrayList,java.util.ArrayList,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"AdaptationSet","l":"representations"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationSegmentIterator","l":"RepresentationSegmentIterator(DefaultDashChunkSource.RepresentationHolder, long, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.dash.DefaultDashChunkSource.RepresentationHolder,long,long,long)"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"request"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"REQUEST_HEADER_ENABLE_METADATA_NAME"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"REQUEST_HEADER_ENABLE_METADATA_VALUE"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyRequest","l":"REQUEST_TYPE_INITIAL"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyRequest","l":"REQUEST_TYPE_NONE"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyRequest","l":"REQUEST_TYPE_RELEASE"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyRequest","l":"REQUEST_TYPE_RENEWAL"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyRequest","l":"REQUEST_TYPE_UNKNOWN"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyRequest","l":"REQUEST_TYPE_UPDATE"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"requestAds(DataSpec, Object, ViewGroup)","url":"requestAds(com.google.android.exoplayer2.upstream.DataSpec,java.lang.Object,android.view.ViewGroup)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.DrmConfiguration","l":"requestHeaders"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.RequestProperties","l":"RequestProperties()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts.RequestSet","l":"RequestSet(FakeDataSet)","url":"%3Cinit%3E(com.google.android.exoplayer2.testutil.FakeDataSet)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer.InsufficientCapacityException","l":"requiredCapacity"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"Requirements(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.scheduler","c":"RequirementsWatcher","l":"RequirementsWatcher(Context, RequirementsWatcher.Listener, Requirements)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.scheduler.RequirementsWatcher.Listener,com.google.android.exoplayer2.scheduler.Requirements)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheEvictor","l":"requiresCacheSpanTouches()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"LeastRecentlyUsedCacheEvictor","l":"requiresCacheSpanTouches()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"NoOpCacheEvictor","l":"requiresCacheSpanTouches()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"reset()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"reset()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"reset()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor","l":"reset()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"reset()"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"reset()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"reset()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"reset()"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"reset()"},{"p":"com.google.android.exoplayer2.ext.gvr","c":"GvrAudioProcessor","l":"reset()"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisBitArray","l":"reset()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"reset()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunkIterator","l":"reset()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaChunkIterator","l":"reset()"},{"p":"com.google.android.exoplayer2.source.hls","c":"TimestampAdjusterProvider","l":"reset()"},{"p":"com.google.android.exoplayer2.testutil","c":"CapturingAudioSink","l":"reset()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"reset()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"reset()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultAllocator","l":"reset()"},{"p":"com.google.android.exoplayer2.upstream","c":"TimeToFirstByteEstimator","l":"reset()"},{"p":"com.google.android.exoplayer2.util","c":"SlidingPercentile","l":"reset()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"reset(boolean)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableNalUnitBitArray","l":"reset(byte[], int, int)","url":"reset(byte[],int,int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"reset(byte[], int)","url":"reset(byte[],int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"reset(byte[], int)","url":"reset(byte[],int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"reset(byte[])"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"reset(byte[])"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"reset(int)"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"reset(long)"},{"p":"com.google.android.exoplayer2.util","c":"ReusableBufferedOutputStream","l":"reset(OutputStream)","url":"reset(java.io.OutputStream)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"reset(ParsableByteArray)","url":"reset(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.upstream","c":"StatsDataSource","l":"resetBytesRead()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"resetCodecStateForFlush()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"resetCodecStateForFlush()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"resetCodecStateForRelease()"},{"p":"com.google.android.exoplayer2.util","c":"NetworkTypeObserver","l":"resetForTests()"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"resetPeekPosition()"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"resetPeekPosition()"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"resetPeekPosition()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"resetPeekPosition()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"resetPosition(long)"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"resetPosition(long)"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"resetPosition(long)"},{"p":"com.google.android.exoplayer2.util","c":"StandaloneMediaClock","l":"resetPosition(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"resetProvisioning()"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"resetSupplementalData(int)"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout","l":"RESIZE_MODE_FILL"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout","l":"RESIZE_MODE_FIT"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout","l":"RESIZE_MODE_FIXED_HEIGHT"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout","l":"RESIZE_MODE_FIXED_WIDTH"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout","l":"RESIZE_MODE_ZOOM"},{"p":"com.google.android.exoplayer2.util","c":"UriUtil","l":"resolve(String, String)","url":"resolve(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"ResolvingDataSource.Resolver","l":"resolveDataSpec(DataSpec)","url":"resolveDataSpec(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"ResolvingDataSource.Resolver","l":"resolveReportedUri(Uri)","url":"resolveReportedUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2","c":"SeekParameters","l":"resolveSeekPositionUs(long, long, long)","url":"resolveSeekPositionUs(long,long,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource","l":"resolvesToUnknownLength()"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource.Builder","l":"resolvesToUnknownLength(boolean)"},{"p":"com.google.android.exoplayer2.util","c":"UriUtil","l":"resolveToUri(String, String)","url":"resolveToUri(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"RangedUri","l":"resolveUri(String)","url":"resolveUri(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"RangedUri","l":"resolveUriString(String)","url":"resolveUriString(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"ResolvingDataSource","l":"ResolvingDataSource(DataSource, ResolvingDataSource.Resolver)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.ResolvingDataSource.Resolver)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"resourceNotFound_transferListenerCallbacks()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"resourceNotFound()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.InvalidResponseCodeException","l":"responseBody"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.InvalidResponseCodeException","l":"responseCode"},{"p":"com.google.android.exoplayer2.drm","c":"MediaDrmCallbackException","l":"responseHeaders"},{"p":"com.google.android.exoplayer2.source","c":"LoadEventInfo","l":"responseHeaders"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.InvalidResponseCodeException","l":"responseMessage"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"restoreKeys(byte[], byte[])","url":"restoreKeys(byte[],byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"restoreKeys(byte[], byte[])","url":"restoreKeys(byte[],byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"restoreKeys(byte[], byte[])","url":"restoreKeys(byte[],byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"restoreKeys(byte[], byte[])","url":"restoreKeys(byte[],byte[])"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"result"},{"p":"com.google.android.exoplayer2","c":"C","l":"RESULT_BUFFER_READ"},{"p":"com.google.android.exoplayer2.extractor","c":"Extractor","l":"RESULT_CONTINUE"},{"p":"com.google.android.exoplayer2","c":"C","l":"RESULT_END_OF_INPUT"},{"p":"com.google.android.exoplayer2.extractor","c":"Extractor","l":"RESULT_END_OF_INPUT"},{"p":"com.google.android.exoplayer2","c":"C","l":"RESULT_FORMAT_READ"},{"p":"com.google.android.exoplayer2","c":"C","l":"RESULT_MAX_LENGTH_EXCEEDED"},{"p":"com.google.android.exoplayer2","c":"C","l":"RESULT_NOTHING_READ"},{"p":"com.google.android.exoplayer2.extractor","c":"Extractor","l":"RESULT_SEEK"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"resumeDownloads()"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"retainBackBufferFromKeyframe()"},{"p":"com.google.android.exoplayer2","c":"LoadControl","l":"retainBackBufferFromKeyframe()"},{"p":"com.google.android.exoplayer2","c":"MetadataRetriever","l":"retrieveMetadata(Context, MediaItem)","url":"retrieveMetadata(android.content.Context,com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2","c":"MetadataRetriever","l":"retrieveMetadata(MediaSourceFactory, MediaItem)","url":"retrieveMetadata(com.google.android.exoplayer2.source.MediaSourceFactory,com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"RETRY"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"RETRY_RESET_ERROR_COUNT"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"retry()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"retry()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"retry()"},{"p":"com.google.android.exoplayer2.util","c":"ReusableBufferedOutputStream","l":"ReusableBufferedOutputStream(OutputStream, int)","url":"%3Cinit%3E(java.io.OutputStream,int)"},{"p":"com.google.android.exoplayer2.util","c":"ReusableBufferedOutputStream","l":"ReusableBufferedOutputStream(OutputStream)","url":"%3Cinit%3E(java.io.OutputStream)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"REUSE_RESULT_NO"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"REUSE_RESULT_YES_WITH_FLUSH"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"REUSE_RESULT_YES_WITH_RECONFIGURATION"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"REUSE_RESULT_YES_WITHOUT_RECONFIGURATION"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"REVISION_ID_DEFAULT"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser.RepresentationInfo","l":"revisionId"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"revisionId"},{"p":"com.google.android.exoplayer2.audio","c":"WavUtil","l":"RIFF_FOURCC"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_ALTERNATE"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_CAPTION"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_COMMENTARY"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_DESCRIBES_VIDEO"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_DUB"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_EASY_TO_READ"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_EMERGENCY"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_ENHANCED_DIALOG_INTELLIGIBILITY"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_MAIN"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_SIGN"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_SUBTITLE"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_SUPPLEMENTARY"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_TRANSCRIBES_DIALOG"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_TRICK_PLAY"},{"p":"com.google.android.exoplayer2","c":"Format","l":"roleFlags"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Subtitle","l":"roleFlags"},{"p":"com.google.android.exoplayer2","c":"Format","l":"rotationDegrees"},{"p":"com.google.android.exoplayer2.ext.rtmp","c":"RtmpDataSource","l":"RtmpDataSource()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.rtmp","c":"RtmpDataSourceFactory","l":"RtmpDataSourceFactory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.rtmp","c":"RtmpDataSourceFactory","l":"RtmpDataSourceFactory(TransferListener)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"RTP_VERSION"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","c":"RtpAc3Reader","l":"RtpAc3Reader(RtpPayloadFormat)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.rtsp.RtpPayloadFormat)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPayloadFormat","l":"RtpPayloadFormat(Format, int, int, Map)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format,int,int,java.util.Map)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPayloadFormat","l":"rtpPayloadType"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.RtspPlaybackException","l":"RtspPlaybackException(String, Throwable)","url":"%3Cinit%3E(java.lang.String,java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.RtspPlaybackException","l":"RtspPlaybackException(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.RtspPlaybackException","l":"RtspPlaybackException(Throwable)","url":"%3Cinit%3E(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.text.span","c":"RubySpan","l":"RubySpan(String, int)","url":"%3Cinit%3E(java.lang.String,int)"},{"p":"com.google.android.exoplayer2.text.span","c":"RubySpan","l":"rubyText"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"run()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.PlayerRunnable","l":"run()"},{"p":"com.google.android.exoplayer2.testutil","c":"DummyMainThread.TestRunnable","l":"run()"},{"p":"com.google.android.exoplayer2.util","c":"DebugTextViewHelper","l":"run()"},{"p":"com.google.android.exoplayer2.util","c":"EGLSurfaceTexture","l":"run()"},{"p":"com.google.android.exoplayer2.util","c":"RunnableFutureTask","l":"run()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.PlayerRunnable","l":"run(SimpleExoPlayer)","url":"run(com.google.android.exoplayer2.SimpleExoPlayer)"},{"p":"com.google.android.exoplayer2.robolectric","c":"RobolectricUtil","l":"runLooperUntil(Looper, Supplier, long, Clock)","url":"runLooperUntil(android.os.Looper,com.google.common.base.Supplier,long,com.google.android.exoplayer2.util.Clock)"},{"p":"com.google.android.exoplayer2.robolectric","c":"RobolectricUtil","l":"runLooperUntil(Looper, Supplier)","url":"runLooperUntil(android.os.Looper,com.google.common.base.Supplier)"},{"p":"com.google.android.exoplayer2.robolectric","c":"RobolectricUtil","l":"runMainLooperUntil(Supplier, long, Clock)","url":"runMainLooperUntil(com.google.common.base.Supplier,long,com.google.android.exoplayer2.util.Clock)"},{"p":"com.google.android.exoplayer2.robolectric","c":"RobolectricUtil","l":"runMainLooperUntil(Supplier)","url":"runMainLooperUntil(com.google.common.base.Supplier)"},{"p":"com.google.android.exoplayer2.util","c":"RunnableFutureTask","l":"RunnableFutureTask()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"DummyMainThread","l":"runOnMainThread(int, Runnable)","url":"runOnMainThread(int,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.testutil","c":"DummyMainThread","l":"runOnMainThread(Runnable)","url":"runOnMainThread(java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"runOnPlaybackThread(Runnable)","url":"runOnPlaybackThread(java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity","l":"runTest(HostActivity.HostedTest, long, boolean)","url":"runTest(com.google.android.exoplayer2.testutil.HostActivity.HostedTest,long,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity","l":"runTest(HostActivity.HostedTest, long)","url":"runTest(com.google.android.exoplayer2.testutil.HostActivity.HostedTest,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"DummyMainThread","l":"runTestOnMainThread(DummyMainThread.TestRunnable)","url":"runTestOnMainThread(com.google.android.exoplayer2.testutil.DummyMainThread.TestRunnable)"},{"p":"com.google.android.exoplayer2.testutil","c":"DummyMainThread","l":"runTestOnMainThread(int, DummyMainThread.TestRunnable)","url":"runTestOnMainThread(int,com.google.android.exoplayer2.testutil.DummyMainThread.TestRunnable)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestPlayerRunHelper","l":"runUntilError(Player)","url":"runUntilError(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestPlayerRunHelper","l":"runUntilPendingCommandsAreFullyHandled(ExoPlayer)","url":"runUntilPendingCommandsAreFullyHandled(com.google.android.exoplayer2.ExoPlayer)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestPlayerRunHelper","l":"runUntilPlaybackState(Player, int)","url":"runUntilPlaybackState(com.google.android.exoplayer2.Player,int)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestPlayerRunHelper","l":"runUntilPlayWhenReady(Player, boolean)","url":"runUntilPlayWhenReady(com.google.android.exoplayer2.Player,boolean)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestPlayerRunHelper","l":"runUntilPositionDiscontinuity(Player, int)","url":"runUntilPositionDiscontinuity(com.google.android.exoplayer2.Player,int)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestPlayerRunHelper","l":"runUntilReceiveOffloadSchedulingEnabledNewState(ExoPlayer)","url":"runUntilReceiveOffloadSchedulingEnabledNewState(com.google.android.exoplayer2.ExoPlayer)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestPlayerRunHelper","l":"runUntilRenderedFirstFrame(SimpleExoPlayer)","url":"runUntilRenderedFirstFrame(com.google.android.exoplayer2.SimpleExoPlayer)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestPlayerRunHelper","l":"runUntilSleepingForOffload(ExoPlayer, boolean)","url":"runUntilSleepingForOffload(com.google.android.exoplayer2.ExoPlayer,boolean)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestPlayerRunHelper","l":"runUntilTimelineChanged(Player, Timeline)","url":"runUntilTimelineChanged(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestPlayerRunHelper","l":"runUntilTimelineChanged(Player)","url":"runUntilTimelineChanged(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput","l":"SAMPLE_DATA_PART_ENCRYPTION"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput","l":"SAMPLE_DATA_PART_MAIN"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput","l":"SAMPLE_DATA_PART_SUPPLEMENTAL"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util","l":"SAMPLE_HEADER_SIZE"},{"p":"com.google.android.exoplayer2.audio","c":"OpusUtil","l":"SAMPLE_RATE"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"SAMPLE_RATE_NO_CHANGE"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream.FakeSampleStreamItem","l":"sample(long, int, byte[])","url":"sample(long,int,byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"sampleBufferReadCount"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util.SyncFrameInfo","l":"sampleCount"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util.SyncFrameInfo","l":"sampleCount"},{"p":"com.google.android.exoplayer2.extractor","c":"DummyTrackOutput","l":"sampleData(DataReader, int, boolean, int)","url":"sampleData(com.google.android.exoplayer2.upstream.DataReader,int,boolean,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput","l":"sampleData(DataReader, int, boolean, int)","url":"sampleData(com.google.android.exoplayer2.upstream.DataReader,int,boolean,int)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"sampleData(DataReader, int, boolean, int)","url":"sampleData(com.google.android.exoplayer2.upstream.DataReader,int,boolean,int)"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler.PlayerTrackEmsgHandler","l":"sampleData(DataReader, int, boolean, int)","url":"sampleData(com.google.android.exoplayer2.upstream.DataReader,int,boolean,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"sampleData(DataReader, int, boolean, int)","url":"sampleData(com.google.android.exoplayer2.upstream.DataReader,int,boolean,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput","l":"sampleData(DataReader, int, boolean)","url":"sampleData(com.google.android.exoplayer2.upstream.DataReader,int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"DummyTrackOutput","l":"sampleData(ParsableByteArray, int, int)","url":"sampleData(com.google.android.exoplayer2.util.ParsableByteArray,int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput","l":"sampleData(ParsableByteArray, int, int)","url":"sampleData(com.google.android.exoplayer2.util.ParsableByteArray,int,int)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"sampleData(ParsableByteArray, int, int)","url":"sampleData(com.google.android.exoplayer2.util.ParsableByteArray,int,int)"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler.PlayerTrackEmsgHandler","l":"sampleData(ParsableByteArray, int, int)","url":"sampleData(com.google.android.exoplayer2.util.ParsableByteArray,int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"sampleData(ParsableByteArray, int, int)","url":"sampleData(com.google.android.exoplayer2.util.ParsableByteArray,int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput","l":"sampleData(ParsableByteArray, int)","url":"sampleData(com.google.android.exoplayer2.util.ParsableByteArray,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"DummyTrackOutput","l":"sampleMetadata(long, int, int, int, TrackOutput.CryptoData)","url":"sampleMetadata(long,int,int,int,com.google.android.exoplayer2.extractor.TrackOutput.CryptoData)"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput","l":"sampleMetadata(long, int, int, int, TrackOutput.CryptoData)","url":"sampleMetadata(long,int,int,int,com.google.android.exoplayer2.extractor.TrackOutput.CryptoData)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"sampleMetadata(long, int, int, int, TrackOutput.CryptoData)","url":"sampleMetadata(long,int,int,int,com.google.android.exoplayer2.extractor.TrackOutput.CryptoData)"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler.PlayerTrackEmsgHandler","l":"sampleMetadata(long, int, int, int, TrackOutput.CryptoData)","url":"sampleMetadata(long,int,int,int,com.google.android.exoplayer2.extractor.TrackOutput.CryptoData)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"sampleMetadata(long, int, int, int, TrackOutput.CryptoData)","url":"sampleMetadata(long,int,int,int,com.google.android.exoplayer2.extractor.TrackOutput.CryptoData)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"sampleMimeType"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacFrameReader.SampleNumberHolder","l":"sampleNumber"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacFrameReader.SampleNumberHolder","l":"SampleNumberHolder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"SampleQueue(Allocator, Looper, DrmSessionManager, DrmSessionEventListener.EventDispatcher)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.Allocator,android.os.Looper,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2.source.hls","c":"SampleQueueMappingException","l":"SampleQueueMappingException(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"sampleRate"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util.SyncFrameInfo","l":"sampleRate"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util.SyncFrameInfo","l":"sampleRate"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor.AudioFormat","l":"sampleRate"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil.Header","l":"sampleRate"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"sampleRate"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.VorbisIdHeader","l":"sampleRate"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil.Config","l":"sampleRateHz"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"sampleRateLookupKey"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil.Header","l":"samplesPerFrame"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"sampleTransformation"},{"p":"com.google.android.exoplayer2","c":"C","l":"SANS_SERIF_NAME"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"scaleLargeTimestamp(long, long, long)","url":"scaleLargeTimestamp(long,long,long)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"scaleLargeTimestamps(List, long, long)","url":"scaleLargeTimestamps(java.util.List,long,long)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"scaleLargeTimestampsInPlace(long[], long, long)","url":"scaleLargeTimestampsInPlace(long[],long,long)"},{"p":"com.google.android.exoplayer2.ext.workmanager","c":"WorkManagerScheduler","l":"schedule(Requirements, String, String)","url":"schedule(com.google.android.exoplayer2.scheduler.Requirements,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.scheduler","c":"PlatformScheduler","l":"schedule(Requirements, String, String)","url":"schedule(com.google.android.exoplayer2.scheduler.Requirements,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.scheduler","c":"Scheduler","l":"schedule(Requirements, String, String)","url":"schedule(com.google.android.exoplayer2.scheduler.Requirements,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.workmanager","c":"WorkManagerScheduler.SchedulerWorker","l":"SchedulerWorker(Context, WorkerParameters)","url":"%3Cinit%3E(android.content.Context,androidx.work.WorkerParameters)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSchemeDataSource","l":"SCHEME_DATA"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"SchemeData(UUID, String, byte[])","url":"%3Cinit%3E(java.util.UUID,java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"SchemeData(UUID, String, String, byte[])","url":"%3Cinit%3E(java.util.UUID,java.lang.String,java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"schemeDataCount"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"schemeIdUri"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Descriptor","l":"schemeIdUri"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"EventStream","l":"schemeIdUri"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"UtcTimingElement","l":"schemeIdUri"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"schemeType"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"TrackEncryptionBox","l":"schemeType"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"SCTE35_SCHEME_ID"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"SDK_INT"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.TimestampSeeker","l":"searchForTimestamp(ExtractorInput, long)","url":"searchForTimestamp(com.google.android.exoplayer2.extractor.ExtractorInput,long)"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap.SeekPoints","l":"second"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"SectionReader","l":"SectionReader(SectionPayloadReader)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.ts.SectionPayloadReader)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"secure"},{"p":"com.google.android.exoplayer2.video","c":"DummySurface","l":"secure"},{"p":"com.google.android.exoplayer2.util","c":"EGLSurfaceTexture","l":"SECURE_MODE_NONE"},{"p":"com.google.android.exoplayer2.util","c":"EGLSurfaceTexture","l":"SECURE_MODE_PROTECTED_PBUFFER"},{"p":"com.google.android.exoplayer2.util","c":"EGLSurfaceTexture","l":"SECURE_MODE_SURFACELESS_CONTEXT"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer.DecoderInitializationException","l":"secureDecoderRequired"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Reader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Reader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsReader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DtsReader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DvbSubtitleReader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"ElementaryStreamReader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H262Reader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H263Reader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H264Reader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H265Reader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Id3Reader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"LatmReader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"MpegAudioReader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PesReader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"SectionReader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader","l":"seek()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"seek(int, long, boolean)","url":"seek(int,long,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"seek(int, long)","url":"seek(int,long)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor","c":"Extractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.amr","c":"AmrExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.flac","c":"FlacExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.flv","c":"FlvExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.jpeg","c":"JpegExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.ogg","c":"OggExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.rawcc","c":"RawCcExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Extractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Extractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.wav","c":"WavExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.source","c":"BundledExtractorsAdapter","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaParserExtractorAdapter","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.source.hls","c":"WebvttExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","c":"RtpAc3Reader","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","c":"RtpPayloadReader","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"seek(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.Seek","l":"Seek(String, int, long, boolean)","url":"%3Cinit%3E(java.lang.String,int,long,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.Seek","l":"Seek(String, long)","url":"%3Cinit%3E(java.lang.String,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"seekAndWait(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"seekMap"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorOutput","l":"seekMap"},{"p":"com.google.android.exoplayer2.extractor","c":"DummyExtractorOutput","l":"seekMap(SeekMap)","url":"seekMap(com.google.android.exoplayer2.extractor.SeekMap)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorOutput","l":"seekMap(SeekMap)","url":"seekMap(com.google.android.exoplayer2.extractor.SeekMap)"},{"p":"com.google.android.exoplayer2.extractor.jpeg","c":"StartOffsetExtractorOutput","l":"seekMap(SeekMap)","url":"seekMap(com.google.android.exoplayer2.extractor.SeekMap)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BundledChunkExtractor","l":"seekMap(SeekMap)","url":"seekMap(com.google.android.exoplayer2.extractor.SeekMap)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorOutput","l":"seekMap(SeekMap)","url":"seekMap(com.google.android.exoplayer2.extractor.SeekMap)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"seekOperationParams"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.SeekOperationParams","l":"SeekOperationParams(long, long, long, long, long, long, long)","url":"%3Cinit%3E(long,long,long,long,long,long,long)"},{"p":"com.google.android.exoplayer2","c":"SeekParameters","l":"SeekParameters(long, long)","url":"%3Cinit%3E(long,long)"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekPoint","l":"SeekPoint(long, long)","url":"%3Cinit%3E(long,long)"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap.SeekPoints","l":"SeekPoints(SeekPoint, SeekPoint)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.SeekPoint,com.google.android.exoplayer2.extractor.SeekPoint)"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap.SeekPoints","l":"SeekPoints(SeekPoint)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.SeekPoint)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"seekTable"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata.SeekTable","l":"SeekTable(long[], long[])","url":"%3Cinit%3E(long[],long[])"},{"p":"com.google.android.exoplayer2","c":"Player","l":"seekTo(int, long)","url":"seekTo(int,long)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"seekTo(int, long)","url":"seekTo(int,long)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"seekTo(int, long)","url":"seekTo(int,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"seekTo(int, long)","url":"seekTo(int,long)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"seekTo(int)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"seekTo(long, boolean)","url":"seekTo(long,boolean)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"seekTo(long)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"seekTo(long)"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"seekTo(long)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"seekTo(long)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"seekToDefaultPosition()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"seekToDefaultPosition()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"seekToDefaultPosition(int)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"seekToDefaultPosition(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"seekToPosition(ExtractorInput, long, PositionHolder)","url":"seekToPosition(com.google.android.exoplayer2.extractor.ExtractorInput,long,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"InputReaderAdapterV30","l":"seekToPosition(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"seekToTimeUs(Extractor, SeekMap, long, DataSource, FakeTrackOutput, Uri)","url":"seekToTimeUs(com.google.android.exoplayer2.extractor.Extractor,com.google.android.exoplayer2.extractor.SeekMap,long,com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.testutil.FakeTrackOutput,android.net.Uri)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"seekToUs(long)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"seekToUs(long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"seekToUs(long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"seekToUs(long)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"seekToUs(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"seekToUs(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"seekToUs(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"seekToUs(long)"},{"p":"com.google.android.exoplayer2.offline","c":"SegmentDownloader.Segment","l":"Segment(long, DataSpec)","url":"%3Cinit%3E(long,com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData.Segment","l":"Segment(long, long, int)","url":"%3Cinit%3E(long,long,int)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.Segment","l":"Segment(String, HlsMediaPlaylist.Segment, String, long, int, long, DrmInitData, String, String, long, long, boolean, List)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.Segment,java.lang.String,long,int,long,com.google.android.exoplayer2.drm.DrmInitData,java.lang.String,java.lang.String,long,long,boolean,java.util.List)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.Segment","l":"Segment(String, long, long, String, String)","url":"%3Cinit%3E(java.lang.String,long,long,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser.RepresentationInfo","l":"segmentBase"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase","l":"SegmentBase(RangedUri, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.dash.manifest.RangedUri,long,long)"},{"p":"com.google.android.exoplayer2.offline","c":"SegmentDownloader","l":"SegmentDownloader(MediaItem, ParsingLoadable.Parser, CacheDataSource.Factory, Executor)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.upstream.ParsingLoadable.Parser,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationHolder","l":"segmentIndex"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SegmentList","l":"SegmentList(RangedUri, long, long, long, long, List, long, List, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.dash.manifest.RangedUri,long,long,long,long,java.util.List,long,java.util.List,long,long)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData","l":"segments"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"segments"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SegmentTemplate","l":"SegmentTemplate(RangedUri, long, long, long, long, long, List, long, UrlTemplate, UrlTemplate, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.dash.manifest.RangedUri,long,long,long,long,long,java.util.List,long,com.google.android.exoplayer2.source.dash.manifest.UrlTemplate,com.google.android.exoplayer2.source.dash.manifest.UrlTemplate,long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SegmentTimelineElement","l":"SegmentTimelineElement(long, long)","url":"%3Cinit%3E(long,long)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"SeiReader","l":"SeiReader(List)","url":"%3Cinit%3E(java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelector","l":"selectAllTracks(MappingTrackSelector.MappedTrackInfo, int[][][], int[], DefaultTrackSelector.Parameters)","url":"selectAllTracks(com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo,int[][][],int[],com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"selectAllTracks(MappingTrackSelector.MappedTrackInfo, int[][][], int[], DefaultTrackSelector.Parameters)","url":"selectAllTracks(com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo,int[][][],int[],com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"selectAudioTrack(TrackGroupArray, int[][], int, DefaultTrackSelector.Parameters, boolean)","url":"selectAudioTrack(com.google.android.exoplayer2.source.TrackGroupArray,int[][],int,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters,boolean)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"selectEmbeddedTrack(long, int)","url":"selectEmbeddedTrack(long,int)"},{"p":"com.google.android.exoplayer2","c":"C","l":"SELECTION_FLAG_AUTOSELECT"},{"p":"com.google.android.exoplayer2","c":"C","l":"SELECTION_FLAG_DEFAULT"},{"p":"com.google.android.exoplayer2","c":"C","l":"SELECTION_FLAG_FORCED"},{"p":"com.google.android.exoplayer2","c":"C","l":"SELECTION_REASON_ADAPTIVE"},{"p":"com.google.android.exoplayer2","c":"C","l":"SELECTION_REASON_CUSTOM_BASE"},{"p":"com.google.android.exoplayer2","c":"C","l":"SELECTION_REASON_INITIAL"},{"p":"com.google.android.exoplayer2","c":"C","l":"SELECTION_REASON_MANUAL"},{"p":"com.google.android.exoplayer2","c":"C","l":"SELECTION_REASON_TRICK_PLAY"},{"p":"com.google.android.exoplayer2","c":"C","l":"SELECTION_REASON_UNKNOWN"},{"p":"com.google.android.exoplayer2","c":"Format","l":"selectionFlags"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Subtitle","l":"selectionFlags"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.SelectionOverride","l":"SelectionOverride(int, int...)","url":"%3Cinit%3E(int,int...)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.SelectionOverride","l":"SelectionOverride(int, int[], int)","url":"%3Cinit%3E(int,int[],int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectorResult","l":"selections"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"selectOtherTrack(int, TrackGroupArray, int[][], DefaultTrackSelector.Parameters)","url":"selectOtherTrack(int,com.google.android.exoplayer2.source.TrackGroupArray,int[][],com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"selectTextTrack(TrackGroupArray, int[][], DefaultTrackSelector.Parameters, String)","url":"selectTextTrack(com.google.android.exoplayer2.source.TrackGroupArray,int[][],com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters,java.lang.String)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"selectTracks(ExoTrackSelection[], boolean[], SampleStream[], boolean[], long)","url":"selectTracks(com.google.android.exoplayer2.trackselection.ExoTrackSelection[],boolean[],com.google.android.exoplayer2.source.SampleStream[],boolean[],long)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"selectTracks(ExoTrackSelection[], boolean[], SampleStream[], boolean[], long)","url":"selectTracks(com.google.android.exoplayer2.trackselection.ExoTrackSelection[],boolean[],com.google.android.exoplayer2.source.SampleStream[],boolean[],long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"selectTracks(ExoTrackSelection[], boolean[], SampleStream[], boolean[], long)","url":"selectTracks(com.google.android.exoplayer2.trackselection.ExoTrackSelection[],boolean[],com.google.android.exoplayer2.source.SampleStream[],boolean[],long)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"selectTracks(ExoTrackSelection[], boolean[], SampleStream[], boolean[], long)","url":"selectTracks(com.google.android.exoplayer2.trackselection.ExoTrackSelection[],boolean[],com.google.android.exoplayer2.source.SampleStream[],boolean[],long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"selectTracks(ExoTrackSelection[], boolean[], SampleStream[], boolean[], long)","url":"selectTracks(com.google.android.exoplayer2.trackselection.ExoTrackSelection[],boolean[],com.google.android.exoplayer2.source.SampleStream[],boolean[],long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"selectTracks(ExoTrackSelection[], boolean[], SampleStream[], boolean[], long)","url":"selectTracks(com.google.android.exoplayer2.trackselection.ExoTrackSelection[],boolean[],com.google.android.exoplayer2.source.SampleStream[],boolean[],long)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"selectTracks(MappingTrackSelector.MappedTrackInfo, int[][][], int[], MediaSource.MediaPeriodId, Timeline)","url":"selectTracks(com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo,int[][][],int[],com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector","l":"selectTracks(MappingTrackSelector.MappedTrackInfo, int[][][], int[], MediaSource.MediaPeriodId, Timeline)","url":"selectTracks(com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo,int[][][],int[],com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector","l":"selectTracks(RendererCapabilities[], TrackGroupArray, MediaSource.MediaPeriodId, Timeline)","url":"selectTracks(com.google.android.exoplayer2.RendererCapabilities[],com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelector","l":"selectTracks(RendererCapabilities[], TrackGroupArray, MediaSource.MediaPeriodId, Timeline)","url":"selectTracks(com.google.android.exoplayer2.RendererCapabilities[],com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"selectUndeterminedTextLanguage"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"selectVideoTrack(TrackGroupArray, int[][], int, DefaultTrackSelector.Parameters, boolean)","url":"selectVideoTrack(com.google.android.exoplayer2.source.TrackGroupArray,int[][],int,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters,boolean)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"send()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"sendAddDownload(Context, Class, DownloadRequest, boolean)","url":"sendAddDownload(android.content.Context,java.lang.Class,com.google.android.exoplayer2.offline.DownloadRequest,boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"sendAddDownload(Context, Class, DownloadRequest, int, boolean)","url":"sendAddDownload(android.content.Context,java.lang.Class,com.google.android.exoplayer2.offline.DownloadRequest,int,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"sendEmptyMessage(int)"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"sendEmptyMessageAtTime(int, long)","url":"sendEmptyMessageAtTime(int,long)"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"sendEmptyMessageDelayed(int, int)","url":"sendEmptyMessageDelayed(int,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"sendEvent(AnalyticsListener.EventTime, int, ListenerSet.Event)","url":"sendEvent(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,com.google.android.exoplayer2.util.ListenerSet.Event)"},{"p":"com.google.android.exoplayer2.util","c":"ListenerSet","l":"sendEvent(int, ListenerSet.Event)","url":"sendEvent(int,com.google.android.exoplayer2.util.ListenerSet.Event)"},{"p":"com.google.android.exoplayer2.audio","c":"AuxEffectInfo","l":"sendLevel"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"sendMessage(PlayerMessage.Target, int, long, boolean)","url":"sendMessage(com.google.android.exoplayer2.PlayerMessage.Target,int,long,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"sendMessage(PlayerMessage.Target, int, long)","url":"sendMessage(com.google.android.exoplayer2.PlayerMessage.Target,int,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"sendMessage(PlayerMessage.Target, long)","url":"sendMessage(com.google.android.exoplayer2.PlayerMessage.Target,long)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage.Sender","l":"sendMessage(PlayerMessage)","url":"sendMessage(com.google.android.exoplayer2.PlayerMessage)"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"sendMessageAtFrontOfQueue(HandlerWrapper.Message)","url":"sendMessageAtFrontOfQueue(com.google.android.exoplayer2.util.HandlerWrapper.Message)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SendMessages","l":"SendMessages(String, PlayerMessage.Target, int, long, boolean)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.PlayerMessage.Target,int,long,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SendMessages","l":"SendMessages(String, PlayerMessage.Target, long)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.PlayerMessage.Target,long)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"sendPauseDownloads(Context, Class, boolean)","url":"sendPauseDownloads(android.content.Context,java.lang.Class,boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"sendRemoveAllDownloads(Context, Class, boolean)","url":"sendRemoveAllDownloads(android.content.Context,java.lang.Class,boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"sendRemoveDownload(Context, Class, String, boolean)","url":"sendRemoveDownload(android.content.Context,java.lang.Class,java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"sendResumeDownloads(Context, Class, boolean)","url":"sendResumeDownloads(android.content.Context,java.lang.Class,boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"sendSetRequirements(Context, Class, Requirements, boolean)","url":"sendSetRequirements(android.content.Context,java.lang.Class,com.google.android.exoplayer2.scheduler.Requirements,boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"sendSetStopReason(Context, Class, String, int, boolean)","url":"sendSetStopReason(android.content.Context,java.lang.Class,java.lang.String,int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock.HandlerMessage","l":"sendToTarget()"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper.Message","l":"sendToTarget()"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"separateColorPlaneFlag"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.PpsData","l":"seqParameterSetId"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"seqParameterSetId"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"sequenceNumber"},{"p":"com.google.android.exoplayer2","c":"C","l":"SERIF_NAME"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"serverControl"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.ServerControl","l":"ServerControl(long, boolean, long, long, boolean)","url":"%3Cinit%3E(long,boolean,long,long,boolean)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"serviceDescription"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ServiceDescriptionElement","l":"ServiceDescriptionElement(long, long, long, float, float)","url":"%3Cinit%3E(long,long,long,float,float)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"SessionCallbackBuilder(Context, SessionPlayerConnector)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.ext.media2.SessionPlayerConnector)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.DrmConfiguration","l":"sessionForClearTypes"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaCrypto","l":"sessionId"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"sessionKeyDrmInitData"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"SessionPlayerConnector(Player, MediaItemConverter)","url":"%3Cinit%3E(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ext.media2.MediaItemConverter)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"SessionPlayerConnector(Player)","url":"%3Cinit%3E(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.decoder","c":"CryptoInfo","l":"set(int, int[], int[], byte[], byte[], int, int, int)","url":"set(int,int[],int[],byte[],byte[],int,int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.RequestProperties","l":"set(Map)","url":"set(java.util.Map)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"set(Object, MediaItem, Object, long, long, long, boolean, boolean, MediaItem.LiveConfiguration, long, long, int, int, long)","url":"set(java.lang.Object,com.google.android.exoplayer2.MediaItem,java.lang.Object,long,long,long,boolean,boolean,com.google.android.exoplayer2.MediaItem.LiveConfiguration,long,long,int,int,long)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"set(Object, Object, int, long, long, AdPlaybackState, boolean)","url":"set(java.lang.Object,java.lang.Object,int,long,long,com.google.android.exoplayer2.source.ads.AdPlaybackState,boolean)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"set(Object, Object, int, long, long)","url":"set(java.lang.Object,java.lang.Object,int,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadataMutations","l":"set(String, byte[])","url":"set(java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadataMutations","l":"set(String, long)","url":"set(java.lang.String,long)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.RequestProperties","l":"set(String, String)","url":"set(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadataMutations","l":"set(String, String)","url":"set(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setAccessibilityChannel(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setActionSchedule(ActionSchedule)","url":"setActionSchedule(com.google.android.exoplayer2.testutil.ActionSchedule)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setAdErrorListener(AdErrorEvent.AdErrorListener)","url":"setAdErrorListener(com.google.ads.interactivemedia.v3.api.AdErrorEvent.AdErrorListener)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setAdEventListener(AdEvent.AdEventListener)","url":"setAdEventListener(com.google.ads.interactivemedia.v3.api.AdEvent.AdEventListener)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setAdGroupTimesMs(long[], boolean[], int)","url":"setAdGroupTimesMs(long[],boolean[],int)"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar","l":"setAdGroupTimesMs(long[], boolean[], int)","url":"setAdGroupTimesMs(long[],boolean[],int)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setAdMarkerColor(int)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setAdMediaMimeTypes(List)","url":"setAdMediaMimeTypes(java.util.List)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setAdPreloadTimeoutMs(long)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setAdsLoaderProvider(DefaultMediaSourceFactory.AdsLoaderProvider)","url":"setAdsLoaderProvider(com.google.android.exoplayer2.source.DefaultMediaSourceFactory.AdsLoaderProvider)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setAdTagUri(String)","url":"setAdTagUri(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setAdTagUri(Uri, Object)","url":"setAdTagUri(android.net.Uri,java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setAdTagUri(Uri)","url":"setAdTagUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"setAdtsExtractorFlags(int)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setAdUiElements(Set)","url":"setAdUiElements(java.util.Set)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setAdViewProvider(AdViewProvider)","url":"setAdViewProvider(com.google.android.exoplayer2.ui.AdViewProvider)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setAlbumArtist(CharSequence)","url":"setAlbumArtist(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setAlbumTitle(CharSequence)","url":"setAlbumTitle(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl.Builder","l":"setAllocator(DefaultAllocator)","url":"setAllocator(com.google.android.exoplayer2.upstream.DefaultAllocator)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder","l":"setAllowAdaptiveSelections(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionView","l":"setAllowAdaptiveSelections(boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setAllowAudioMixedChannelCountAdaptiveness(boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setAllowAudioMixedMimeTypeAdaptiveness(boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setAllowAudioMixedSampleRateAdaptiveness(boolean)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setAllowChunklessPreparation(boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource.Factory","l":"setAllowCrossProtocolRedirects(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes.Builder","l":"setAllowedCapturePolicy(int)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"setAllowedCommandProvider(SessionCallbackBuilder.AllowedCommandProvider)","url":"setAllowedCommandProvider(com.google.android.exoplayer2.ext.media2.SessionCallbackBuilder.AllowedCommandProvider)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"setAllowedVideoJoiningTimeMs(long)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setAllowMultipleAdaptiveSelections(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder","l":"setAllowMultipleOverrides(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionView","l":"setAllowMultipleOverrides(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"setAllowPreparation(boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setAllowVideoMixedMimeTypeAdaptiveness(boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setAllowVideoNonSeamlessAdaptiveness(boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"setAmrExtractorFlags(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"setAnalyticsCollector(AnalyticsCollector)","url":"setAnalyticsCollector(com.google.android.exoplayer2.analytics.AnalyticsCollector)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setAnalyticsCollector(AnalyticsCollector)","url":"setAnalyticsCollector(com.google.android.exoplayer2.analytics.AnalyticsCollector)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setAnalyticsListener(AnalyticsListener)","url":"setAnalyticsListener(com.google.android.exoplayer2.analytics.AnalyticsListener)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setAnimationEnabled(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"setApplyEmbeddedFontSizes(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"setApplyEmbeddedStyles(boolean)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setArtist(CharSequence)","url":"setArtist(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setArtworkData(byte[])"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setArtworkUri(Uri)","url":"setArtworkUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout","l":"setAspectRatio(float)"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout","l":"setAspectRatioListener(AspectRatioFrameLayout.AspectRatioListener)","url":"setAspectRatioListener(com.google.android.exoplayer2.ui.AspectRatioFrameLayout.AspectRatioListener)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setAspectRatioListener(AspectRatioFrameLayout.AspectRatioListener)","url":"setAspectRatioListener(com.google.android.exoplayer2.ui.AspectRatioFrameLayout.AspectRatioListener)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setAspectRatioListener(AspectRatioFrameLayout.AspectRatioListener)","url":"setAspectRatioListener(com.google.android.exoplayer2.ui.AspectRatioFrameLayout.AspectRatioListener)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioComponent","l":"setAudioAttributes(AudioAttributes, boolean)","url":"setAudioAttributes(com.google.android.exoplayer2.audio.AudioAttributes,boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setAudioAttributes(AudioAttributes, boolean)","url":"setAudioAttributes(com.google.android.exoplayer2.audio.AudioAttributes,boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setAudioAttributes(AudioAttributes, boolean)","url":"setAudioAttributes(com.google.android.exoplayer2.audio.AudioAttributes,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"setAudioAttributes(AudioAttributes, boolean)","url":"setAudioAttributes(com.google.android.exoplayer2.audio.AudioAttributes,boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"setAudioAttributes(AudioAttributes)","url":"setAudioAttributes(com.google.android.exoplayer2.audio.AudioAttributes)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"setAudioAttributes(AudioAttributes)","url":"setAudioAttributes(com.google.android.exoplayer2.audio.AudioAttributes)"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"setAudioAttributes(AudioAttributes)","url":"setAudioAttributes(com.google.android.exoplayer2.audio.AudioAttributes)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"setAudioAttributes(AudioAttributesCompat)","url":"setAudioAttributes(androidx.media.AudioAttributesCompat)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetAudioAttributes","l":"SetAudioAttributes(String, AudioAttributes, boolean)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.audio.AudioAttributes,boolean)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioComponent","l":"setAudioSessionId(int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setAudioSessionId(int)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"setAudioSessionId(int)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"setAudioSessionId(int)"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"setAudioSessionId(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioComponent","l":"setAuxEffectInfo(AuxEffectInfo)","url":"setAuxEffectInfo(com.google.android.exoplayer2.audio.AuxEffectInfo)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setAuxEffectInfo(AuxEffectInfo)","url":"setAuxEffectInfo(com.google.android.exoplayer2.audio.AuxEffectInfo)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"setAuxEffectInfo(AuxEffectInfo)","url":"setAuxEffectInfo(com.google.android.exoplayer2.audio.AuxEffectInfo)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"setAuxEffectInfo(AuxEffectInfo)","url":"setAuxEffectInfo(com.google.android.exoplayer2.audio.AuxEffectInfo)"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"setAuxEffectInfo(AuxEffectInfo)","url":"setAuxEffectInfo(com.google.android.exoplayer2.audio.AuxEffectInfo)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setAverageBitrate(int)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl.Builder","l":"setBackBuffer(int, boolean)","url":"setBackBuffer(int,boolean)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setBackgroundColor(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setBadgeIconType(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"setBandwidthMeter(BandwidthMeter)","url":"setBandwidthMeter(com.google.android.exoplayer2.upstream.BandwidthMeter)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setBandwidthMeter(BandwidthMeter)","url":"setBandwidthMeter(com.google.android.exoplayer2.upstream.BandwidthMeter)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setBandwidthMeter(BandwidthMeter)","url":"setBandwidthMeter(com.google.android.exoplayer2.upstream.BandwidthMeter)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"setBandwidthMeter(BandwidthMeter)","url":"setBandwidthMeter(com.google.android.exoplayer2.upstream.BandwidthMeter)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setBitmap(Bitmap)","url":"setBitmap(android.graphics.Bitmap)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setBitmapHeight(float)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setBold(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"setBottomPaddingFraction(float)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil.Attribute","l":"setBuffer(float[], int)","url":"setBuffer(float[],int)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl.Builder","l":"setBufferDurationsMs(int, int, int, int)","url":"setBufferDurationsMs(int,int,int,int)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setBufferedColor(int)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setBufferedPosition(long)"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar","l":"setBufferedPosition(long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink.Factory","l":"setBufferSize(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setBytesDownloaded(long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink.Factory","l":"setCache(Cache)","url":"setCache(com.google.android.exoplayer2.upstream.cache.Cache)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"setCache(Cache)","url":"setCache(com.google.android.exoplayer2.upstream.cache.Cache)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource.Factory","l":"setCacheControl(CacheControl)","url":"setCacheControl(okhttp3.CacheControl)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setCacheKey(String)","url":"setCacheKey(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"setCacheKeyFactory(CacheKeyFactory)","url":"setCacheKeyFactory(com.google.android.exoplayer2.upstream.cache.CacheKeyFactory)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"setCacheReadDataSourceFactory(DataSource.Factory)","url":"setCacheReadDataSourceFactory(com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"setCacheWriteDataSinkFactory(DataSink.Factory)","url":"setCacheWriteDataSinkFactory(com.google.android.exoplayer2.upstream.DataSink.Factory)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.PlayerTarget","l":"setCallback(ActionSchedule.PlayerTarget.Callback)","url":"setCallback(com.google.android.exoplayer2.testutil.ActionSchedule.PlayerTarget.Callback)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"setCameraMotionListener(CameraMotionListener)","url":"setCameraMotionListener(com.google.android.exoplayer2.video.spherical.CameraMotionListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setCameraMotionListener(CameraMotionListener)","url":"setCameraMotionListener(com.google.android.exoplayer2.video.spherical.CameraMotionListener)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setCaptionCallback(MediaSessionConnector.CaptionCallback)","url":"setCaptionCallback(com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.CaptionCallback)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setChannelCount(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setChannelDescriptionResourceId(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setChannelImportance(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setChannelNameResourceId(int)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setClipEndPositionMs(long)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setClipRelativeToDefaultPosition(boolean)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setClipRelativeToLiveWindow(boolean)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setClipStartPositionMs(long)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setClipStartsAtKeyFrame(boolean)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"setClock(Clock)","url":"setClock(com.google.android.exoplayer2.util.Clock)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setClock(Clock)","url":"setClock(com.google.android.exoplayer2.util.Clock)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setClock(Clock)","url":"setClock(com.google.android.exoplayer2.util.Clock)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"setClock(Clock)","url":"setClock(com.google.android.exoplayer2.util.Clock)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter.Builder","l":"setClock(Clock)","url":"setClock(com.google.android.exoplayer2.util.Clock)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setCodecs(String)","url":"setCodecs(java.lang.String)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setColor(int)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setColorInfo(ColorInfo)","url":"setColorInfo(com.google.android.exoplayer2.video.ColorInfo)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setColorized(boolean)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setCombineUpright(boolean)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setCompanionAdSlots(Collection)","url":"setCompanionAdSlots(java.util.Collection)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"setCompositeSequenceableLoaderFactory(CompositeSequenceableLoaderFactory)","url":"setCompositeSequenceableLoaderFactory(com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setCompositeSequenceableLoaderFactory(CompositeSequenceableLoaderFactory)","url":"setCompositeSequenceableLoaderFactory(com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"setCompositeSequenceableLoaderFactory(CompositeSequenceableLoaderFactory)","url":"setCompositeSequenceableLoaderFactory(com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"setConnectionTimeoutMs(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource.Factory","l":"setConnectTimeoutMs(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"setConstantBitrateSeekingEnabled(boolean)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setContainerMimeType(String)","url":"setContainerMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleOutputBuffer","l":"setContent(long, Subtitle, long)","url":"setContent(long,com.google.android.exoplayer2.text.Subtitle,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadataMutations","l":"setContentLength(ContentMetadataMutations, long)","url":"setContentLength(com.google.android.exoplayer2.upstream.cache.ContentMetadataMutations,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setContentLength(long)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes.Builder","l":"setContentType(int)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"setContentTypePredicate(Predicate)","url":"setContentTypePredicate(com.google.common.base.Predicate)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"setContentTypePredicate(Predicate)","url":"setContentTypePredicate(com.google.common.base.Predicate)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"setContentTypePredicate(Predicate)","url":"setContentTypePredicate(com.google.common.base.Predicate)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource.Factory","l":"setContentTypePredicate(Predicate)","url":"setContentTypePredicate(com.google.common.base.Predicate)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"setContentTypePredicate(Predicate)","url":"setContentTypePredicate(com.google.common.base.Predicate)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource.Factory","l":"setContentTypePredicate(Predicate)","url":"setContentTypePredicate(com.google.common.base.Predicate)"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer.Builder","l":"setContext(Context)","url":"setContext(android.content.Context)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"setContinueLoadingCheckIntervalBytes(int)"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"setControlDispatcher(ControlDispatcher)","url":"setControlDispatcher(com.google.android.exoplayer2.ControlDispatcher)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"setControlDispatcher(ControlDispatcher)","url":"setControlDispatcher(com.google.android.exoplayer2.ControlDispatcher)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setControlDispatcher(ControlDispatcher)","url":"setControlDispatcher(com.google.android.exoplayer2.ControlDispatcher)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setControlDispatcher(ControlDispatcher)","url":"setControlDispatcher(com.google.android.exoplayer2.ControlDispatcher)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setControlDispatcher(ControlDispatcher)","url":"setControlDispatcher(com.google.android.exoplayer2.ControlDispatcher)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setControlDispatcher(ControlDispatcher)","url":"setControlDispatcher(com.google.android.exoplayer2.ControlDispatcher)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setControlDispatcher(ControlDispatcher)","url":"setControlDispatcher(com.google.android.exoplayer2.ControlDispatcher)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setControlDispatcher(ControlDispatcher)","url":"setControlDispatcher(com.google.android.exoplayer2.ControlDispatcher)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setControllerAutoShow(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setControllerAutoShow(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setControllerHideDuringAds(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setControllerHideDuringAds(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setControllerHideOnTouch(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setControllerHideOnTouch(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setControllerOnFullScreenModeChangedListener(StyledPlayerControlView.OnFullScreenModeChangedListener)","url":"setControllerOnFullScreenModeChangedListener(com.google.android.exoplayer2.ui.StyledPlayerControlView.OnFullScreenModeChangedListener)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setControllerShowTimeoutMs(int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setControllerShowTimeoutMs(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setControllerVisibilityListener(PlayerControlView.VisibilityListener)","url":"setControllerVisibilityListener(com.google.android.exoplayer2.ui.PlayerControlView.VisibilityListener)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setControllerVisibilityListener(StyledPlayerControlView.VisibilityListener)","url":"setControllerVisibilityListener(com.google.android.exoplayer2.ui.StyledPlayerControlView.VisibilityListener)"},{"p":"com.google.android.exoplayer2.util","c":"MediaFormatUtil","l":"setCsdBuffers(MediaFormat, List)","url":"setCsdBuffers(android.media.MediaFormat,java.util.List)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket.Builder","l":"setCsrc(byte[])"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"setCues(List)","url":"setCues(java.util.List)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"InputReaderAdapterV30","l":"setCurrentPosition(long)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"setCurrentStreamFinal()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"setCurrentStreamFinal()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"setCurrentStreamFinal()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setCustomActionProviders(MediaSessionConnector.CustomActionProvider...)","url":"setCustomActionProviders(com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.CustomActionProvider...)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setCustomActionReceiver(PlayerNotificationManager.CustomActionReceiver)","url":"setCustomActionReceiver(com.google.android.exoplayer2.ui.PlayerNotificationManager.CustomActionReceiver)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setCustomCacheKey(String)","url":"setCustomCacheKey(java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest.Builder","l":"setCustomCacheKey(String)","url":"setCustomCacheKey(java.lang.String)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"setCustomCacheKey(String)","url":"setCustomCacheKey(java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"setCustomCommandProvider(SessionCallbackBuilder.CustomCommandProvider)","url":"setCustomCommandProvider(com.google.android.exoplayer2.ext.media2.SessionCallbackBuilder.CustomCommandProvider)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"setCustomData(Object)","url":"setCustomData(java.lang.Object)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setCustomErrorMessage(CharSequence, int, Bundle)","url":"setCustomErrorMessage(java.lang.CharSequence,int,android.os.Bundle)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setCustomErrorMessage(CharSequence, int)","url":"setCustomErrorMessage(java.lang.CharSequence,int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setCustomErrorMessage(CharSequence)","url":"setCustomErrorMessage(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setCustomErrorMessage(CharSequence)","url":"setCustomErrorMessage(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setCustomErrorMessage(CharSequence)","url":"setCustomErrorMessage(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setCustomMetadata(byte[])"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest.Builder","l":"setData(byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput.Builder","l":"setData(byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource.Builder","l":"setData(byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet","l":"setData(String, byte[])","url":"setData(java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet","l":"setData(Uri, byte[])","url":"setData(android.net.Uri,byte[])"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"InputReaderAdapterV30","l":"setDataReader(DataReader, long)","url":"setDataReader(com.google.android.exoplayer2.upstream.DataReader,long)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setDebugModeEnabled(boolean)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Libgav1VideoRenderer","l":"setDecoderOutputMode(int)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"LibvpxVideoRenderer","l":"setDecoderOutputMode(int)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"setDecoderOutputMode(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts.AssertionConfig.Builder","l":"setDeduplicateConsecutiveFormats(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setDefaultArtwork(Drawable)","url":"setDefaultArtwork(android.graphics.drawable.Drawable)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setDefaultArtwork(Drawable)","url":"setDefaultArtwork(android.graphics.drawable.Drawable)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"setDefaultRequestProperties(Map)","url":"setDefaultRequestProperties(java.util.Map)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource.Factory","l":"setDefaultRequestProperties(Map)","url":"setDefaultRequestProperties(java.util.Map)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource.Factory","l":"setDefaultRequestProperties(Map)","url":"setDefaultRequestProperties(java.util.Map)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.BaseFactory","l":"setDefaultRequestProperties(Map)","url":"setDefaultRequestProperties(java.util.Map)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.Factory","l":"setDefaultRequestProperties(Map)","url":"setDefaultRequestProperties(java.util.Map)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setDefaults(int)"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView","l":"setDefaultStereoMode(int)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"setDeleteAfterDelivery(boolean)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setDescription(CharSequence)","url":"setDescription(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setDetachSurfaceTimeoutMs(long)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.DeviceComponent","l":"setDeviceMuted(boolean)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setDeviceMuted(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setDeviceMuted(boolean)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setDeviceMuted(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setDeviceMuted(boolean)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.DeviceComponent","l":"setDeviceVolume(int)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setDeviceVolume(int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setDeviceVolume(int)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setDeviceVolume(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setDeviceVolume(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setDisabledTextTrackSelectionFlags(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setDisabledTextTrackSelectionFlags(int)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"setDisconnectedCallback(SessionCallbackBuilder.DisconnectedCallback)","url":"setDisconnectedCallback(com.google.android.exoplayer2.ext.media2.SessionCallbackBuilder.DisconnectedCallback)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"setDiscontinuityPositionUs(long)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setDisplayTitle(CharSequence)","url":"setDisplayTitle(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloadIndex","l":"setDownloadingStatesToQueued()"},{"p":"com.google.android.exoplayer2.offline","c":"WritableDownloadIndex","l":"setDownloadingStatesToQueued()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setDrmForceDefaultLicenseUri(boolean)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManagerProvider","l":"setDrmHttpDataSourceFactory(HttpDataSource.Factory)","url":"setDrmHttpDataSourceFactory(com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setDrmHttpDataSourceFactory(HttpDataSource.Factory)","url":"setDrmHttpDataSourceFactory(com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceFactory","l":"setDrmHttpDataSourceFactory(HttpDataSource.Factory)","url":"setDrmHttpDataSourceFactory(com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"setDrmHttpDataSourceFactory(HttpDataSource.Factory)","url":"setDrmHttpDataSourceFactory(com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"setDrmHttpDataSourceFactory(HttpDataSource.Factory)","url":"setDrmHttpDataSourceFactory(com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setDrmHttpDataSourceFactory(HttpDataSource.Factory)","url":"setDrmHttpDataSourceFactory(com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.Factory","l":"setDrmHttpDataSourceFactory(HttpDataSource.Factory)","url":"setDrmHttpDataSourceFactory(com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"setDrmHttpDataSourceFactory(HttpDataSource.Factory)","url":"setDrmHttpDataSourceFactory(com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setDrmInitData(DrmInitData)","url":"setDrmInitData(com.google.android.exoplayer2.drm.DrmInitData)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setDrmKeySetId(byte[])"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setDrmLicenseRequestHeaders(Map)","url":"setDrmLicenseRequestHeaders(java.util.Map)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setDrmLicenseUri(String)","url":"setDrmLicenseUri(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setDrmLicenseUri(Uri)","url":"setDrmLicenseUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setDrmMultiSession(boolean)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setDrmPlayClearContentWithoutKey(boolean)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setDrmSessionForClearPeriods(boolean)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setDrmSessionForClearTypes(List)","url":"setDrmSessionForClearTypes(java.util.List)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setDrmSessionManager(DrmSessionManager)","url":"setDrmSessionManager(com.google.android.exoplayer2.drm.DrmSessionManager)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceFactory","l":"setDrmSessionManager(DrmSessionManager)","url":"setDrmSessionManager(com.google.android.exoplayer2.drm.DrmSessionManager)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"setDrmSessionManager(DrmSessionManager)","url":"setDrmSessionManager(com.google.android.exoplayer2.drm.DrmSessionManager)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"setDrmSessionManager(DrmSessionManager)","url":"setDrmSessionManager(com.google.android.exoplayer2.drm.DrmSessionManager)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setDrmSessionManager(DrmSessionManager)","url":"setDrmSessionManager(com.google.android.exoplayer2.drm.DrmSessionManager)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.Factory","l":"setDrmSessionManager(DrmSessionManager)","url":"setDrmSessionManager(com.google.android.exoplayer2.drm.DrmSessionManager)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"setDrmSessionManager(DrmSessionManager)","url":"setDrmSessionManager(com.google.android.exoplayer2.drm.DrmSessionManager)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setDrmSessionManagerProvider(DrmSessionManagerProvider)","url":"setDrmSessionManagerProvider(com.google.android.exoplayer2.drm.DrmSessionManagerProvider)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceFactory","l":"setDrmSessionManagerProvider(DrmSessionManagerProvider)","url":"setDrmSessionManagerProvider(com.google.android.exoplayer2.drm.DrmSessionManagerProvider)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"setDrmSessionManagerProvider(DrmSessionManagerProvider)","url":"setDrmSessionManagerProvider(com.google.android.exoplayer2.drm.DrmSessionManagerProvider)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"setDrmSessionManagerProvider(DrmSessionManagerProvider)","url":"setDrmSessionManagerProvider(com.google.android.exoplayer2.drm.DrmSessionManagerProvider)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setDrmSessionManagerProvider(DrmSessionManagerProvider)","url":"setDrmSessionManagerProvider(com.google.android.exoplayer2.drm.DrmSessionManagerProvider)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.Factory","l":"setDrmSessionManagerProvider(DrmSessionManagerProvider)","url":"setDrmSessionManagerProvider(com.google.android.exoplayer2.drm.DrmSessionManagerProvider)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"setDrmSessionManagerProvider(DrmSessionManagerProvider)","url":"setDrmSessionManagerProvider(com.google.android.exoplayer2.drm.DrmSessionManagerProvider)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManagerProvider","l":"setDrmUserAgent(String)","url":"setDrmUserAgent(java.lang.String)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setDrmUserAgent(String)","url":"setDrmUserAgent(java.lang.String)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceFactory","l":"setDrmUserAgent(String)","url":"setDrmUserAgent(java.lang.String)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"setDrmUserAgent(String)","url":"setDrmUserAgent(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"setDrmUserAgent(String)","url":"setDrmUserAgent(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setDrmUserAgent(String)","url":"setDrmUserAgent(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.Factory","l":"setDrmUserAgent(String)","url":"setDrmUserAgent(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"setDrmUserAgent(String)","url":"setDrmUserAgent(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setDrmUuid(UUID)","url":"setDrmUuid(java.util.UUID)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts.AssertionConfig.Builder","l":"setDumpFilesPrefix(String)","url":"setDumpFilesPrefix(java.lang.String)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setDuration(long)"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar","l":"setDuration(long)"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource.Factory","l":"setDurationUs(long)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"setEnableAudioFloatOutput(boolean)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"setEnableAudioOffload(boolean)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"setEnableAudioTrackPlaybackParams(boolean)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setEnableContinuousPlayback(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"setEnabled(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setEnabled(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar","l":"setEnabled(boolean)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"setEnableDecoderFallback(boolean)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setEnabledPlaybackActions(long)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setEncoderDelay(int)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setEncoderPadding(int)"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"setErrorMessageProvider(ErrorMessageProvider)","url":"setErrorMessageProvider(com.google.android.exoplayer2.util.ErrorMessageProvider)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setErrorMessageProvider(ErrorMessageProvider)","url":"setErrorMessageProvider(com.google.android.exoplayer2.util.ErrorMessageProvider)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setErrorMessageProvider(ErrorMessageProvider)","url":"setErrorMessageProvider(com.google.android.exoplayer2.util.ErrorMessageProvider)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setErrorMessageProvider(ErrorMessageProvider)","url":"setErrorMessageProvider(com.google.android.exoplayer2.util.ErrorMessageProvider)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"setEventListener(CacheDataSource.EventListener)","url":"setEventListener(com.google.android.exoplayer2.upstream.cache.CacheDataSource.EventListener)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setExceedAudioConstraintsIfNecessary(boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setExceedRendererCapabilitiesIfNecessary(boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setExceedVideoConstraintsIfNecessary(boolean)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setExoMediaCryptoType(Class)","url":"setExoMediaCryptoType(java.lang.Class)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.TestResource.Builder","l":"setExpectedBytes(byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setExpectedPlayerEndedCount(int)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"setExtensionRendererMode(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setExtraAdGroupMarkers(long[], boolean[])","url":"setExtraAdGroupMarkers(long[],boolean[])"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setExtraAdGroupMarkers(long[], boolean[])","url":"setExtraAdGroupMarkers(long[],boolean[])"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setExtraAdGroupMarkers(long[], boolean[])","url":"setExtraAdGroupMarkers(long[],boolean[])"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setExtraAdGroupMarkers(long[], boolean[])","url":"setExtraAdGroupMarkers(long[],boolean[])"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setExtractorFactory(HlsExtractorFactory)","url":"setExtractorFactory(com.google.android.exoplayer2.source.hls.HlsExtractorFactory)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"setExtractorOutput(ExtractorOutput)","url":"setExtractorOutput(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"setExtractorsFactory(ExtractorsFactory)","url":"setExtractorsFactory(com.google.android.exoplayer2.extractor.ExtractorsFactory)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setExtras(Bundle)","url":"setExtras(android.os.Bundle)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setFailureReason(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource.Factory","l":"setFakeDataSet(FakeDataSet)","url":"setFakeDataSet(com.google.android.exoplayer2.testutil.FakeDataSet)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"setFallbackFactory(HttpDataSource.Factory)","url":"setFallbackFactory(com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl.Builder","l":"setFallbackMaxPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl.Builder","l":"setFallbackMinPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"setFallbackTargetLiveOffsetMs(long)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setFastForwardActionIconResourceId(int)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"setFastForwardIncrementMs(int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setFastForwardIncrementMs(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setFastForwardIncrementMs(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setFastForwardIncrementMs(int)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"setFastForwardIncrementMs(long)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setFastForwardIncrementMs(long)"},{"p":"com.google.android.exoplayer2.text","c":"TextRenderer","l":"setFinalStreamEndPositionUs(long)"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"setFixedTextSize(int, float)","url":"setFixedTextSize(int,float)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"setFlacExtractorFlags(int)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes.Builder","l":"setFlags(int)"},{"p":"com.google.android.exoplayer2.decoder","c":"Buffer","l":"setFlags(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"setFlags(int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"setFlags(int)"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer.Builder","l":"setFlattenForSlowMotion(boolean)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil.Uniform","l":"setFloat(float)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil.Uniform","l":"setFloats(float[])"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setFocusSkipButtonWhenAvailable(boolean)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setFolderType(Integer)","url":"setFolderType(java.lang.Integer)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setFontColor(int)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setFontFamily(String)","url":"setFontFamily(java.lang.String)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setFontSize(float)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setFontSizeUnit(short)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setForceHighestSupportedBitrate(boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setForceLowestBitrate(boolean)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.Factory","l":"setForceUseRtpTcp(boolean)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"setForegroundMode(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setForegroundMode(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setForegroundMode(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil.Header","l":"setForHeaderData(int)"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"setFractionalTextSize(float, boolean)","url":"setFractionalTextSize(float,boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"setFractionalTextSize(float)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"setFragmentedMp4ExtractorFlags(int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink.Factory","l":"setFragmentSize(long)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setFrameRate(float)"},{"p":"com.google.android.exoplayer2.extractor","c":"GaplessInfoHolder","l":"setFromMetadata(Metadata)","url":"setFromMetadata(com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2.extractor","c":"GaplessInfoHolder","l":"setFromXingHeaderValue(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setGroup(String)","url":"setGroup(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource.Builder","l":"setGzipSupport(int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setHandleAudioBecomingNoisy(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setHandleAudioBecomingNoisy(boolean)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"setHandler(Handler)","url":"setHandler(android.os.Handler)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"setHandleSetCookieRequests(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setHandleWakeLock(boolean)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setHeight(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"setHttpBody(byte[])"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"setHttpMethod(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"setHttpRequestHeaders(Map)","url":"setHttpRequestHeaders(java.util.Map)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setId(int)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setId(String)","url":"setId(java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setImaSdkSettings(ImaSdkSettings)","url":"setImaSdkSettings(com.google.ads.interactivemedia.v3.api.ImaSdkSettings)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"setIndex(int)"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"setIndex(int)"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"setIndex(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"AdditionalFailureInfo","l":"setInfo(String)","url":"setInfo(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter.Builder","l":"setInitialBitrateEstimate(int, long)","url":"setInitialBitrateEstimate(int,long)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter.Builder","l":"setInitialBitrateEstimate(long)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter.Builder","l":"setInitialBitrateEstimate(String)","url":"setInitialBitrateEstimate(java.lang.String)"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleDecoder","l":"setInitialInputBufferSize(int)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setInitializationData(List)","url":"setInitializationData(java.util.List)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder","l":"setIsDisabled(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource.Factory","l":"setIsNetwork(boolean)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setIsPlayable(Boolean)","url":"setIsPlayable(java.lang.Boolean)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setItalic(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setKeepContentOnPlayerReset(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setKeepContentOnPlayerReset(boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"setKey(String)","url":"setKey(java.lang.String)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setKeyCountIncrement(int)"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar","l":"setKeyCountIncrement(int)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager.Builder","l":"setKeyRequestParameters(Map)","url":"setKeyRequestParameters(java.util.Map)"},{"p":"com.google.android.exoplayer2.drm","c":"HttpMediaDrmCallback","l":"setKeyRequestProperty(String, String)","url":"setKeyRequestProperty(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest.Builder","l":"setKeySetId(byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setKeySetId(byte[])"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setKeyTimeIncrement(long)"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar","l":"setKeyTimeIncrement(long)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setLabel(String)","url":"setLabel(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setLanguage(String)","url":"setLanguage(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"setLength(long)"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusLibrary","l":"setLibraries(Class, String...)","url":"setLibraries(java.lang.Class,java.lang.String...)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxLibrary","l":"setLibraries(Class, String...)","url":"setLibraries(java.lang.Class,java.lang.String...)"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegLibrary","l":"setLibraries(String...)","url":"setLibraries(java.lang.String...)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacLibrary","l":"setLibraries(String...)","url":"setLibraries(java.lang.String...)"},{"p":"com.google.android.exoplayer2.util","c":"LibraryLoader","l":"setLibraries(String...)","url":"setLibraries(java.lang.String...)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"setLimit(int)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setLine(float, int)","url":"setLine(float,int)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setLineAnchor(int)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setLinethrough(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"setListener(AudioSink.Listener)","url":"setListener(com.google.android.exoplayer2.audio.AudioSink.Listener)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"setListener(AudioSink.Listener)","url":"setListener(com.google.android.exoplayer2.audio.AudioSink.Listener)"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"setListener(AudioSink.Listener)","url":"setListener(com.google.android.exoplayer2.audio.AudioSink.Listener)"},{"p":"com.google.android.exoplayer2.analytics","c":"DefaultPlaybackSessionManager","l":"setListener(PlaybackSessionManager.Listener)","url":"setListener(com.google.android.exoplayer2.analytics.PlaybackSessionManager.Listener)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackSessionManager","l":"setListener(PlaybackSessionManager.Listener)","url":"setListener(com.google.android.exoplayer2.analytics.PlaybackSessionManager.Listener)"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSource.Factory","l":"setListener(TransferListener)","url":"setListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer","l":"setListener(Transformer.Listener)","url":"setListener(com.google.android.exoplayer2.transformer.Transformer.Listener)"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer.Builder","l":"setListener(Transformer.Listener)","url":"setListener(com.google.android.exoplayer2.transformer.Transformer.Listener)"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl","l":"setLiveConfiguration(MediaItem.LiveConfiguration)","url":"setLiveConfiguration(com.google.android.exoplayer2.MediaItem.LiveConfiguration)"},{"p":"com.google.android.exoplayer2","c":"LivePlaybackSpeedControl","l":"setLiveConfiguration(MediaItem.LiveConfiguration)","url":"setLiveConfiguration(com.google.android.exoplayer2.MediaItem.LiveConfiguration)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setLiveMaxOffsetMs(long)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setLiveMaxOffsetMs(long)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setLiveMaxPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setLiveMaxSpeed(float)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setLiveMinOffsetMs(long)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setLiveMinOffsetMs(long)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setLiveMinPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setLiveMinSpeed(float)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"setLivePlaybackSpeedControl(LivePlaybackSpeedControl)","url":"setLivePlaybackSpeedControl(com.google.android.exoplayer2.LivePlaybackSpeedControl)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setLivePlaybackSpeedControl(LivePlaybackSpeedControl)","url":"setLivePlaybackSpeedControl(com.google.android.exoplayer2.LivePlaybackSpeedControl)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"setLivePresentationDelayMs(long, boolean)","url":"setLivePresentationDelayMs(long,boolean)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"setLivePresentationDelayMs(long)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setLiveTargetOffsetMs(long)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setLiveTargetOffsetMs(long)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"setLoadControl(LoadControl)","url":"setLoadControl(com.google.android.exoplayer2.LoadControl)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setLoadControl(LoadControl)","url":"setLoadControl(com.google.android.exoplayer2.LoadControl)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setLoadControl(LoadControl)","url":"setLoadControl(com.google.android.exoplayer2.LoadControl)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"setLoadControl(LoadControl)","url":"setLoadControl(com.google.android.exoplayer2.LoadControl)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager.Builder","l":"setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)","url":"setLoadErrorHandlingPolicy(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)","url":"setLoadErrorHandlingPolicy(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceFactory","l":"setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)","url":"setLoadErrorHandlingPolicy(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)","url":"setLoadErrorHandlingPolicy(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy)"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource.Factory","l":"setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)","url":"setLoadErrorHandlingPolicy(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)","url":"setLoadErrorHandlingPolicy(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)","url":"setLoadErrorHandlingPolicy(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.Factory","l":"setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)","url":"setLoadErrorHandlingPolicy(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)","url":"setLoadErrorHandlingPolicy(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy)"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"setLogLevel(int)"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"setLogStackTraces(boolean)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"setLooper(Looper)","url":"setLooper(android.os.Looper)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"setLooper(Looper)","url":"setLooper(android.os.Looper)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setLooper(Looper)","url":"setLooper(android.os.Looper)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"setLooper(Looper)","url":"setLooper(android.os.Looper)"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer.Builder","l":"setLooper(Looper)","url":"setLooper(android.os.Looper)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setManifest(Object)","url":"setManifest(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"setManifestParser(ParsingLoadable.Parser)","url":"setManifestParser(com.google.android.exoplayer2.upstream.ParsingLoadable.Parser)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"setManifestParser(ParsingLoadable.Parser)","url":"setManifestParser(com.google.android.exoplayer2.upstream.ParsingLoadable.Parser)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket.Builder","l":"setMarker(boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"setMatroskaExtractorFlags(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setMaxAudioBitrate(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setMaxAudioChannelCount(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm.Builder","l":"setMaxConcurrentSessions(int)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setMaxInputSize(int)"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl.Builder","l":"setMaxLiveOffsetErrorMsForUnitSpeed(long)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setMaxMediaBitrate(int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"setMaxParallelDownloads(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setMaxVideoBitrate(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setMaxVideoFrameRate(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setMaxVideoSize(int, int)","url":"setMaxVideoSize(int,int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setMaxVideoSizeSd()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setMediaButtonEventHandler(MediaSessionConnector.MediaButtonEventHandler)","url":"setMediaButtonEventHandler(com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.MediaButtonEventHandler)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"setMediaCodecSelector(MediaCodecSelector)","url":"setMediaCodecSelector(com.google.android.exoplayer2.mediacodec.MediaCodecSelector)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setMediaId(String)","url":"setMediaId(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"setMediaItem(MediaItem, boolean)","url":"setMediaItem(com.google.android.exoplayer2.MediaItem,boolean)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setMediaItem(MediaItem, boolean)","url":"setMediaItem(com.google.android.exoplayer2.MediaItem,boolean)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"setMediaItem(MediaItem, long)","url":"setMediaItem(com.google.android.exoplayer2.MediaItem,long)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setMediaItem(MediaItem, long)","url":"setMediaItem(com.google.android.exoplayer2.MediaItem,long)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"setMediaItem(MediaItem)","url":"setMediaItem(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setMediaItem(MediaItem)","url":"setMediaItem(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"setMediaItem(MediaItem)","url":"setMediaItem(androidx.media2.common.MediaItem)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"setMediaItemProvider(SessionCallbackBuilder.MediaItemProvider)","url":"setMediaItemProvider(com.google.android.exoplayer2.ext.media2.SessionCallbackBuilder.MediaItemProvider)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setMediaItems(List, boolean)","url":"setMediaItems(java.util.List,boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setMediaItems(List, boolean)","url":"setMediaItems(java.util.List,boolean)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setMediaItems(List, boolean)","url":"setMediaItems(java.util.List,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setMediaItems(List, boolean)","url":"setMediaItems(java.util.List,boolean)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setMediaItems(List, int, long)","url":"setMediaItems(java.util.List,int,long)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setMediaItems(List, int, long)","url":"setMediaItems(java.util.List,int,long)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setMediaItems(List, int, long)","url":"setMediaItems(java.util.List,int,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setMediaItems(List, int, long)","url":"setMediaItems(java.util.List,int,long)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"setMediaItems(List)","url":"setMediaItems(java.util.List)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setMediaItems(List)","url":"setMediaItems(java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetMediaItems","l":"SetMediaItems(String, int, long, MediaSource...)","url":"%3Cinit%3E(java.lang.String,int,long,com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetMediaItemsResetPosition","l":"SetMediaItemsResetPosition(String, boolean, MediaSource...)","url":"%3Cinit%3E(java.lang.String,boolean,com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setMediaLoadTimeoutMs(int)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setMediaMetadata(MediaMetadata)","url":"setMediaMetadata(com.google.android.exoplayer2.MediaMetadata)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setMediaMetadataProvider(MediaSessionConnector.MediaMetadataProvider)","url":"setMediaMetadataProvider(com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.MediaMetadataProvider)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setMediaSessionToken(MediaSessionCompat.Token)","url":"setMediaSessionToken(android.support.v4.media.session.MediaSessionCompat.Token)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"setMediaSource(MediaSource, boolean)","url":"setMediaSource(com.google.android.exoplayer2.source.MediaSource,boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setMediaSource(MediaSource, boolean)","url":"setMediaSource(com.google.android.exoplayer2.source.MediaSource,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setMediaSource(MediaSource, boolean)","url":"setMediaSource(com.google.android.exoplayer2.source.MediaSource,boolean)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"setMediaSource(MediaSource, long)","url":"setMediaSource(com.google.android.exoplayer2.source.MediaSource,long)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setMediaSource(MediaSource, long)","url":"setMediaSource(com.google.android.exoplayer2.source.MediaSource,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setMediaSource(MediaSource, long)","url":"setMediaSource(com.google.android.exoplayer2.source.MediaSource,long)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"setMediaSource(MediaSource)","url":"setMediaSource(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setMediaSource(MediaSource)","url":"setMediaSource(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"setMediaSource(MediaSource)","url":"setMediaSource(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setMediaSource(MediaSource)","url":"setMediaSource(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"setMediaSourceFactory(MediaSourceFactory)","url":"setMediaSourceFactory(com.google.android.exoplayer2.source.MediaSourceFactory)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setMediaSourceFactory(MediaSourceFactory)","url":"setMediaSourceFactory(com.google.android.exoplayer2.source.MediaSourceFactory)"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer.Builder","l":"setMediaSourceFactory(MediaSourceFactory)","url":"setMediaSourceFactory(com.google.android.exoplayer2.source.MediaSourceFactory)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"setMediaSources(boolean, MediaSource...)","url":"setMediaSources(boolean,com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"setMediaSources(int, long, MediaSource...)","url":"setMediaSources(int,long,com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"setMediaSources(List, boolean)","url":"setMediaSources(java.util.List,boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setMediaSources(List, boolean)","url":"setMediaSources(java.util.List,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setMediaSources(List, boolean)","url":"setMediaSources(java.util.List,boolean)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"setMediaSources(List, int, long)","url":"setMediaSources(java.util.List,int,long)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setMediaSources(List, int, long)","url":"setMediaSources(java.util.List,int,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setMediaSources(List, int, long)","url":"setMediaSources(java.util.List,int,long)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"setMediaSources(List)","url":"setMediaSources(java.util.List)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setMediaSources(List)","url":"setMediaSources(java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setMediaSources(List)","url":"setMediaSources(java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"setMediaSources(MediaSource...)","url":"setMediaSources(com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setMediaSources(MediaSource...)","url":"setMediaSources(com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setMediaUri(Uri)","url":"setMediaUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setMetadata(Metadata)","url":"setMetadata(com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setMetadataType(int)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setMimeType(String)","url":"setMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest.Builder","l":"setMimeType(String)","url":"setMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setMimeType(String)","url":"setMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl.Builder","l":"setMinPossibleLiveOffsetSmoothingFactor(float)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"setMinRetryCount(int)"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl.Builder","l":"setMinUpdateIntervalMs(long)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setMinVideoBitrate(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setMinVideoFrameRate(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setMinVideoSize(int, int)","url":"setMinVideoSize(int,int)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"setMode(int, byte[])","url":"setMode(int,byte[])"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"setMp3ExtractorFlags(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"setMp4ExtractorFlags(int)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setMultiRowAlignment(Layout.Alignment)","url":"setMultiRowAlignment(android.text.Layout.Alignment)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager.Builder","l":"setMultiSession(boolean)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"setMuxedCaptionFormats(List)","url":"setMuxedCaptionFormats(java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.TestResource.Builder","l":"setName(String)","url":"setName(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"setNetworkTypeOverride(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"setNewSourceInfo(Timeline, boolean)","url":"setNewSourceInfo(com.google.android.exoplayer2.Timeline,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"setNewSourceInfo(Timeline)","url":"setNewSourceInfo(com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setNextActionIconResourceId(int)"},{"p":"com.google.android.exoplayer2.util","c":"NotificationUtil","l":"setNotification(Context, int, Notification)","url":"setNotification(android.content.Context,int,android.app.Notification)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setNotificationListener(PlayerNotificationManager.NotificationListener)","url":"setNotificationListener(com.google.android.exoplayer2.ui.PlayerNotificationManager.NotificationListener)"},{"p":"com.google.android.exoplayer2.util","c":"SntpClient","l":"setNtpHost(String)","url":"setNtpHost(java.lang.String)"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"setOnEventListener(ExoMediaDrm.OnEventListener)","url":"setOnEventListener(com.google.android.exoplayer2.drm.ExoMediaDrm.OnEventListener)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"setOnEventListener(ExoMediaDrm.OnEventListener)","url":"setOnEventListener(com.google.android.exoplayer2.drm.ExoMediaDrm.OnEventListener)"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"setOnEventListener(ExoMediaDrm.OnEventListener)","url":"setOnEventListener(com.google.android.exoplayer2.drm.ExoMediaDrm.OnEventListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"setOnEventListener(ExoMediaDrm.OnEventListener)","url":"setOnEventListener(com.google.android.exoplayer2.drm.ExoMediaDrm.OnEventListener)"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"setOnExpirationUpdateListener(ExoMediaDrm.OnExpirationUpdateListener)","url":"setOnExpirationUpdateListener(com.google.android.exoplayer2.drm.ExoMediaDrm.OnExpirationUpdateListener)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"setOnExpirationUpdateListener(ExoMediaDrm.OnExpirationUpdateListener)","url":"setOnExpirationUpdateListener(com.google.android.exoplayer2.drm.ExoMediaDrm.OnExpirationUpdateListener)"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"setOnExpirationUpdateListener(ExoMediaDrm.OnExpirationUpdateListener)","url":"setOnExpirationUpdateListener(com.google.android.exoplayer2.drm.ExoMediaDrm.OnExpirationUpdateListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"setOnExpirationUpdateListener(ExoMediaDrm.OnExpirationUpdateListener)","url":"setOnExpirationUpdateListener(com.google.android.exoplayer2.drm.ExoMediaDrm.OnExpirationUpdateListener)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"setOnFrameRenderedListener(MediaCodecAdapter.OnFrameRenderedListener, Handler)","url":"setOnFrameRenderedListener(com.google.android.exoplayer2.mediacodec.MediaCodecAdapter.OnFrameRenderedListener,android.os.Handler)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"setOnFrameRenderedListener(MediaCodecAdapter.OnFrameRenderedListener, Handler)","url":"setOnFrameRenderedListener(com.google.android.exoplayer2.mediacodec.MediaCodecAdapter.OnFrameRenderedListener,android.os.Handler)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setOnFullScreenModeChangedListener(StyledPlayerControlView.OnFullScreenModeChangedListener)","url":"setOnFullScreenModeChangedListener(com.google.android.exoplayer2.ui.StyledPlayerControlView.OnFullScreenModeChangedListener)"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"setOnKeyStatusChangeListener(ExoMediaDrm.OnKeyStatusChangeListener)","url":"setOnKeyStatusChangeListener(com.google.android.exoplayer2.drm.ExoMediaDrm.OnKeyStatusChangeListener)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"setOnKeyStatusChangeListener(ExoMediaDrm.OnKeyStatusChangeListener)","url":"setOnKeyStatusChangeListener(com.google.android.exoplayer2.drm.ExoMediaDrm.OnKeyStatusChangeListener)"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"setOnKeyStatusChangeListener(ExoMediaDrm.OnKeyStatusChangeListener)","url":"setOnKeyStatusChangeListener(com.google.android.exoplayer2.drm.ExoMediaDrm.OnKeyStatusChangeListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"setOnKeyStatusChangeListener(ExoMediaDrm.OnKeyStatusChangeListener)","url":"setOnKeyStatusChangeListener(com.google.android.exoplayer2.drm.ExoMediaDrm.OnKeyStatusChangeListener)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"setOutput(Object)","url":"setOutput(java.lang.Object)"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderGLSurfaceView","l":"setOutputBuffer(VideoDecoderOutputBuffer)","url":"setOutputBuffer(com.google.android.exoplayer2.video.VideoDecoderOutputBuffer)"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBufferRenderer","l":"setOutputBuffer(VideoDecoderOutputBuffer)","url":"setOutputBuffer(com.google.android.exoplayer2.video.VideoDecoderOutputBuffer)"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer.Builder","l":"setOutputMimeType(String)","url":"setOutputMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Gav1Decoder","l":"setOutputMode(int)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxDecoder","l":"setOutputMode(int)"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"setOutputSampleRateHz(int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"setOutputSurface(Surface)","url":"setOutputSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"setOutputSurface(Surface)","url":"setOutputSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"setOutputSurfaceV23(MediaCodecAdapter, Surface)","url":"setOutputSurfaceV23(com.google.android.exoplayer2.mediacodec.MediaCodecAdapter,android.view.Surface)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setOverallRating(Rating)","url":"setOverallRating(com.google.android.exoplayer2.Rating)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder","l":"setOverride(DefaultTrackSelector.SelectionOverride)","url":"setOverride(com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder","l":"setOverrides(List)","url":"setOverrides(java.util.List)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket.Builder","l":"setPadding(boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"setParameters(Bundle)","url":"setParameters(android.os.Bundle)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"setParameters(Bundle)","url":"setParameters(android.os.Bundle)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"setParameters(DefaultTrackSelector.Parameters)","url":"setParameters(com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"setParameters(DefaultTrackSelector.ParametersBuilder)","url":"setParameters(com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder)"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource.Builder","l":"setPath(String)","url":"setPath(java.lang.String)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setPauseActionIconResourceId(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"setPauseAtEndOfMediaItems(boolean)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"setPauseAtEndOfMediaItems(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setPauseAtEndOfMediaItems(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setPauseAtEndOfMediaItems(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setPauseAtEndOfMediaItems(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setPauseAtEndOfMediaItems(boolean)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"setPayload(Object)","url":"setPayload(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket.Builder","l":"setPayloadData(byte[])"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket.Builder","l":"setPayloadType(byte)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setPcmEncoding(int)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setPeakBitrate(int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"setPendingOutputEndOfStream()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"setPendingPlaybackException(ExoPlaybackException)","url":"setPendingPlaybackException(com.google.android.exoplayer2.ExoPlaybackException)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setPercentDownloaded(float)"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"setPitch(float)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setPixelWidthHeightRatio(float)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setPlayActionIconResourceId(int)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setPlayAdBeforeStartPosition(boolean)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.util","c":"MediaClock","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.util","c":"StandaloneMediaClock","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetPlaybackParameters","l":"SetPlaybackParameters(String, PlaybackParameters)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setPlaybackPreparer(MediaSessionConnector.PlaybackPreparer)","url":"setPlaybackPreparer(com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.PlaybackPreparer)"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"setPlaybackPreparer(PlaybackPreparer)","url":"setPlaybackPreparer(com.google.android.exoplayer2.PlaybackPreparer)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setPlaybackPreparer(PlaybackPreparer)","url":"setPlaybackPreparer(com.google.android.exoplayer2.PlaybackPreparer)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setPlaybackPreparer(PlaybackPreparer)","url":"setPlaybackPreparer(com.google.android.exoplayer2.PlaybackPreparer)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setPlaybackPreparer(PlaybackPreparer)","url":"setPlaybackPreparer(com.google.android.exoplayer2.PlaybackPreparer)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setPlaybackPreparer(PlaybackPreparer)","url":"setPlaybackPreparer(com.google.android.exoplayer2.PlaybackPreparer)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setPlaybackPreparer(PlaybackPreparer)","url":"setPlaybackPreparer(com.google.android.exoplayer2.PlaybackPreparer)"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"setPlaybackSpeed(float, float)","url":"setPlaybackSpeed(float,float)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"setPlaybackSpeed(float, float)","url":"setPlaybackSpeed(float,float)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"setPlaybackSpeed(float, float)","url":"setPlaybackSpeed(float,float)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"setPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"setPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager.Builder","l":"setPlayClearSamplesWithoutKeys(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setPlayedAdMarkerColor(int)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setPlayedColor(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"setPlayer(Player, Looper)","url":"setPlayer(com.google.android.exoplayer2.Player,android.os.Looper)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"setPlayer(Player)","url":"setPlayer(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setPlayer(Player)","url":"setPlayer(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsLoader","l":"setPlayer(Player)","url":"setPlayer(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setPlayer(Player)","url":"setPlayer(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setPlayer(Player)","url":"setPlayer(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setPlayer(Player)","url":"setPlayer(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setPlayer(Player)","url":"setPlayer(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setPlayer(Player)","url":"setPlayer(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setPlayerListener(Player.Listener)","url":"setPlayerListener(com.google.android.exoplayer2.Player.Listener)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"setPlaylist(List, MediaMetadata)","url":"setPlaylist(java.util.List,androidx.media2.common.MediaMetadata)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setPlaylistParserFactory(HlsPlaylistParserFactory)","url":"setPlaylistParserFactory(com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParserFactory)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setPlaylistTrackerFactory(HlsPlaylistTracker.Factory)","url":"setPlaylistTrackerFactory(com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker.Factory)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setPlayWhenReady(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setPlayWhenReady(boolean)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setPlayWhenReady(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setPlayWhenReady(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetPlayWhenReady","l":"SetPlayWhenReady(String, boolean)","url":"%3Cinit%3E(java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setPosition(float)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"setPosition(int, long)","url":"setPosition(int,long)"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisBitArray","l":"setPosition(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"setPosition(int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"setPosition(int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"setPosition(int)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"setPosition(long)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setPosition(long)"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar","l":"setPosition(long)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"setPosition(long)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setPositionAnchor(int)"},{"p":"com.google.android.exoplayer2.text","c":"SimpleSubtitleDecoder","l":"setPositionUs(long)"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleDecoder","l":"setPositionUs(long)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"setPostConnectCallback(SessionCallbackBuilder.PostConnectCallback)","url":"setPostConnectCallback(com.google.android.exoplayer2.ext.media2.SessionCallbackBuilder.PostConnectCallback)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setPreferredAudioLanguage(String)","url":"setPreferredAudioLanguage(java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setPreferredAudioLanguage(String)","url":"setPreferredAudioLanguage(java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setPreferredAudioLanguages(String...)","url":"setPreferredAudioLanguages(java.lang.String...)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setPreferredAudioLanguages(String...)","url":"setPreferredAudioLanguages(java.lang.String...)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setPreferredAudioMimeType(String)","url":"setPreferredAudioMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setPreferredAudioMimeTypes(String...)","url":"setPreferredAudioMimeTypes(java.lang.String...)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setPreferredAudioRoleFlags(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setPreferredAudioRoleFlags(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setPreferredTextLanguage(String)","url":"setPreferredTextLanguage(java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setPreferredTextLanguage(String)","url":"setPreferredTextLanguage(java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings(Context)","url":"setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings(android.content.Context)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings(Context)","url":"setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings(android.content.Context)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setPreferredTextLanguages(String...)","url":"setPreferredTextLanguages(java.lang.String...)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setPreferredTextLanguages(String...)","url":"setPreferredTextLanguages(java.lang.String...)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setPreferredTextRoleFlags(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setPreferredTextRoleFlags(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setPreferredVideoMimeType(String)","url":"setPreferredVideoMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setPreferredVideoMimeTypes(String...)","url":"setPreferredVideoMimeTypes(java.lang.String...)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"setPreparationComplete()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"setPrepareListener(MaskingMediaPeriod.PrepareListener)","url":"setPrepareListener(com.google.android.exoplayer2.source.MaskingMediaPeriod.PrepareListener)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setPreviousActionIconResourceId(int)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl.Builder","l":"setPrioritizeTimeOverSizeThresholds(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setPriority(int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setPriorityTaskManager(PriorityTaskManager)","url":"setPriorityTaskManager(com.google.android.exoplayer2.util.PriorityTaskManager)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setPriorityTaskManager(PriorityTaskManager)","url":"setPriorityTaskManager(com.google.android.exoplayer2.util.PriorityTaskManager)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setProgressUpdateListener(PlayerControlView.ProgressUpdateListener)","url":"setProgressUpdateListener(com.google.android.exoplayer2.ui.PlayerControlView.ProgressUpdateListener)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setProgressUpdateListener(StyledPlayerControlView.ProgressUpdateListener)","url":"setProgressUpdateListener(com.google.android.exoplayer2.ui.StyledPlayerControlView.ProgressUpdateListener)"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"setProgressUpdatingEnabled(boolean)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setProjectionData(byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"setPropertyByteArray(String, byte[])","url":"setPropertyByteArray(java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"setPropertyByteArray(String, byte[])","url":"setPropertyByteArray(java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"setPropertyByteArray(String, byte[])","url":"setPropertyByteArray(java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"setPropertyByteArray(String, byte[])","url":"setPropertyByteArray(java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"setPropertyString(String, String)","url":"setPropertyString(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"setPropertyString(String, String)","url":"setPropertyString(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"setPropertyString(String, String)","url":"setPropertyString(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"setPropertyString(String, String)","url":"setPropertyString(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl.Builder","l":"setProportionalControlFactor(float)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm.Builder","l":"setProvisionsRequired(int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setQueueEditor(MediaSessionConnector.QueueEditor)","url":"setQueueEditor(com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.QueueEditor)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setQueueNavigator(MediaSessionConnector.QueueNavigator)","url":"setQueueNavigator(com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.QueueNavigator)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet","l":"setRandomData(String, int)","url":"setRandomData(java.lang.String,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet","l":"setRandomData(Uri, int)","url":"setRandomData(android.net.Uri,int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setRatingCallback(MediaSessionConnector.RatingCallback)","url":"setRatingCallback(com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.RatingCallback)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"setRatingCallback(SessionCallbackBuilder.RatingCallback)","url":"setRatingCallback(com.google.android.exoplayer2.ext.media2.SessionCallbackBuilder.RatingCallback)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"setReadTimeoutMs(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource.Factory","l":"setReadTimeoutMs(int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadataMutations","l":"setRedirectedUri(ContentMetadataMutations, Uri)","url":"setRedirectedUri(com.google.android.exoplayer2.upstream.cache.ContentMetadataMutations,android.net.Uri)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"setReleaseTimeoutMs(long)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setReleaseTimeoutMs(long)"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer.Builder","l":"setRemoveAudio(boolean)"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer.Builder","l":"setRemoveVideo(boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setRendererDisabled(int, boolean)","url":"setRendererDisabled(int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetRendererDisabled","l":"SetRendererDisabled(String, int, boolean)","url":"%3Cinit%3E(java.lang.String,int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setRenderers(Renderer...)","url":"setRenderers(com.google.android.exoplayer2.Renderer...)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"setRenderers(Renderer...)","url":"setRenderers(com.google.android.exoplayer2.Renderer...)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setRenderersFactory(RenderersFactory)","url":"setRenderersFactory(com.google.android.exoplayer2.RenderersFactory)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"setRenderersFactory(RenderersFactory)","url":"setRenderersFactory(com.google.android.exoplayer2.RenderersFactory)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"setRenderTimeLimitMs(long)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setRepeatMode(int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setRepeatMode(int)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setRepeatMode(int)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"setRepeatMode(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"setRepeatMode(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setRepeatMode(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetRepeatMode","l":"SetRepeatMode(String, int)","url":"%3Cinit%3E(java.lang.String,int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setRepeatToggleModes(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setRepeatToggleModes(int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setRepeatToggleModes(int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setRepeatToggleModes(int)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"setRequestProperty(String, String)","url":"setRequestProperty(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"setRequestProperty(String, String)","url":"setRequestProperty(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"setRequestProperty(String, String)","url":"setRequestProperty(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource","l":"setRequestProperty(String, String)","url":"setRequestProperty(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"setRequirements(Requirements)","url":"setRequirements(com.google.android.exoplayer2.scheduler.Requirements)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter.Builder","l":"setResetOnNetworkTypeChange(boolean)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"setResetTimeoutOnRedirects(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout","l":"setResizeMode(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setResizeMode(int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setResizeMode(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"setRetryPosition(long, E)","url":"setRetryPosition(long,E)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"setRetryPosition(long, E)","url":"setRetryPosition(long,E)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"setRetryPosition(long, E)","url":"setRetryPosition(long,E)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"setRetryPosition(long, E)","url":"setRetryPosition(long,E)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setRewindActionIconResourceId(int)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"setRewindIncrementMs(int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setRewindIncrementMs(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setRewindIncrementMs(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setRewindIncrementMs(int)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"setRewindIncrementMs(long)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setRewindIncrementMs(long)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setRoleFlags(int)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setRotationDegrees(int)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setRubyPosition(int)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setSampleMimeType(String)","url":"setSampleMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"setSampleOffsetUs(long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunkOutput","l":"setSampleOffsetUs(long)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setSampleRate(int)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil.Uniform","l":"setSamplerTexId(int, int)","url":"setSamplerTexId(int,int)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"setSampleTimestampUpperLimitFilterUs(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"setSchedule(ActionSchedule)","url":"setSchedule(com.google.android.exoplayer2.testutil.ActionSchedule)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setScrubberColor(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"setSeekParameters(SeekParameters)","url":"setSeekParameters(com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"setSeekParameters(SeekParameters)","url":"setSeekParameters(com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setSeekParameters(SeekParameters)","url":"setSeekParameters(com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setSeekParameters(SeekParameters)","url":"setSeekParameters(com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setSeekParameters(SeekParameters)","url":"setSeekParameters(com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"setSeekTargetUs(long)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"setSeekTimeoutMs(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"setSeekToUsOffset(long)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"setSelectedParserName(String)","url":"setSelectedParserName(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setSelectionFlags(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setSelectionOverride(int, TrackGroupArray, DefaultTrackSelector.SelectionOverride)","url":"setSelectionOverride(int,com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setSelectUndeterminedTextLanguage(boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setSelectUndeterminedTextLanguage(boolean)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket.Builder","l":"setSequenceNumber(int)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setSessionAvailabilityListener(SessionAvailabilityListener)","url":"setSessionAvailabilityListener(com.google.android.exoplayer2.ext.cast.SessionAvailabilityListener)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager.Builder","l":"setSessionKeepaliveMs(long)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setShearDegrees(float)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setShowBuffering(int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setShowBuffering(int)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder","l":"setShowDisableOption(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionView","l":"setShowDisableOption(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setShowFastForwardButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setShowFastForwardButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setShowFastForwardButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setShowFastForwardButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setShowMultiWindowTimeBar(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setShowMultiWindowTimeBar(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setShowMultiWindowTimeBar(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setShowMultiWindowTimeBar(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setShowNextButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setShowNextButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setShowNextButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setShowNextButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setShowPreviousButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setShowPreviousButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setShowPreviousButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setShowPreviousButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setShowRewindButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setShowRewindButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setShowRewindButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setShowRewindButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setShowShuffleButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setShowShuffleButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setShowShuffleButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setShowShuffleButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setShowSubtitleButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setShowSubtitleButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setShowTimeoutMs(int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setShowTimeoutMs(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setShowVrButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setShowVrButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setShowVrButton(boolean)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"setShuffleMode(int)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setShuffleModeEnabled(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setShuffleModeEnabled(boolean)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setShuffleModeEnabled(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"setShuffleModeEnabled(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setShuffleModeEnabled(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetShuffleModeEnabled","l":"SetShuffleModeEnabled(String, boolean)","url":"%3Cinit%3E(java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"setShuffleOrder(ShuffleOrder, Handler, Runnable)","url":"setShuffleOrder(com.google.android.exoplayer2.source.ShuffleOrder,android.os.Handler,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"setShuffleOrder(ShuffleOrder)","url":"setShuffleOrder(com.google.android.exoplayer2.source.ShuffleOrder)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setShuffleOrder(ShuffleOrder)","url":"setShuffleOrder(com.google.android.exoplayer2.source.ShuffleOrder)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"setShuffleOrder(ShuffleOrder)","url":"setShuffleOrder(com.google.android.exoplayer2.source.ShuffleOrder)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"setShuffleOrder(ShuffleOrder)","url":"setShuffleOrder(com.google.android.exoplayer2.source.ShuffleOrder)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setShuffleOrder(ShuffleOrder)","url":"setShuffleOrder(com.google.android.exoplayer2.source.ShuffleOrder)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetShuffleOrder","l":"SetShuffleOrder(String, ShuffleOrder)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.source.ShuffleOrder)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setShutterBackgroundColor(int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setShutterBackgroundColor(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput.Builder","l":"setSimulateIOErrors(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput.Builder","l":"setSimulatePartialReads(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData","l":"setSimulateUnknownLength(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput.Builder","l":"setSimulateUnknownLength(boolean)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setSize(float)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"setSkipCallback(SessionCallbackBuilder.SkipCallback)","url":"setSkipCallback(com.google.android.exoplayer2.ext.media2.SessionCallbackBuilder.SkipCallback)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioComponent","l":"setSkipSilenceEnabled(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setSkipSilenceEnabled(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setSkipSilenceEnabled(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"setSkipSilenceEnabled(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"setSkipSilenceEnabled(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"setSkipSilenceEnabled(boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter.Builder","l":"setSlidingWindowMaxWeight(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setSmallIcon(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setSmallIconResourceId(int)"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"setSpeed(float)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket.Builder","l":"setSsrc(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setStartTimeMs(long)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"setStartTimeUs(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setState(int)"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloadIndex","l":"setStatesToRemoving()"},{"p":"com.google.android.exoplayer2.offline","c":"WritableDownloadIndex","l":"setStatesToRemoving()"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setStereoMode(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setStopActionIconResourceId(int)"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloadIndex","l":"setStopReason(int)"},{"p":"com.google.android.exoplayer2.offline","c":"WritableDownloadIndex","l":"setStopReason(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setStopReason(int)"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloadIndex","l":"setStopReason(String, int)","url":"setStopReason(java.lang.String,int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"setStopReason(String, int)","url":"setStopReason(java.lang.String,int)"},{"p":"com.google.android.exoplayer2.offline","c":"WritableDownloadIndex","l":"setStopReason(String, int)","url":"setStopReason(java.lang.String,int)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setStreamKeys(List)","url":"setStreamKeys(java.util.List)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest.Builder","l":"setStreamKeys(List)","url":"setStreamKeys(java.util.List)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setStreamKeys(List)","url":"setStreamKeys(java.util.List)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceFactory","l":"setStreamKeys(List)","url":"setStreamKeys(java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"setStreamKeys(List)","url":"setStreamKeys(java.util.List)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setStreamKeys(List)","url":"setStreamKeys(java.util.List)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"setStreamKeys(List)","url":"setStreamKeys(java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setStreamKeys(StreamKey...)","url":"setStreamKeys(com.google.android.exoplayer2.offline.StreamKey...)"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"setStyle(CaptionStyleCompat)","url":"setStyle(com.google.android.exoplayer2.ui.CaptionStyleCompat)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setSubsampleOffsetUs(long)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setSubtitle(CharSequence)","url":"setSubtitle(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setSubtitles(List)","url":"setSubtitles(java.util.List)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"setSupportedContentTypes(int...)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsLoader","l":"setSupportedContentTypes(int...)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setSupportedFormats(Format...)","url":"setSupportedFormats(com.google.android.exoplayer2.Format...)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setTag(Object)","url":"setTag(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"setTag(Object)","url":"setTag(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource.Factory","l":"setTag(Object)","url":"setTag(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource.Factory","l":"setTag(Object)","url":"setTag(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"setTag(Object)","url":"setTag(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setTag(Object)","url":"setTag(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"setTag(Object)","url":"setTag(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl.Builder","l":"setTargetBufferBytes(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultAllocator","l":"setTargetBufferSize(int)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setTargetClasses(String[])","url":"setTargetClasses(java.lang.String[])"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setTargetId(String)","url":"setTargetId(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl.Builder","l":"setTargetLiveOffsetIncrementOnRebufferMs(long)"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl","l":"setTargetLiveOffsetOverrideUs(long)"},{"p":"com.google.android.exoplayer2","c":"LivePlaybackSpeedControl","l":"setTargetLiveOffsetOverrideUs(long)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setTargetTagName(String)","url":"setTargetTagName(java.lang.String)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setTargetVoice(String)","url":"setTargetVoice(java.lang.String)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setText(CharSequence)","url":"setText(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setTextAlignment(Layout.Alignment)","url":"setTextAlignment(android.text.Layout.Alignment)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setTextSize(float, int)","url":"setTextSize(float,int)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder","l":"setTheme(int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setThrowsWhenUsingWrongThread(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setTimeBarMinUpdateInterval(int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setTimeBarMinUpdateInterval(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setTimeline(Timeline)","url":"setTimeline(com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.Factory","l":"setTimeoutMs(long)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket.Builder","l":"setTimestamp(long)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"setTimestampAdjuster(TimestampAdjuster)","url":"setTimestampAdjuster(com.google.android.exoplayer2.util.TimestampAdjuster)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setTitle(CharSequence)","url":"setTitle(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setTotalTrackCount(Integer)","url":"setTotalTrackCount(java.lang.Integer)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder","l":"setTrackFormatComparator(Comparator)","url":"setTrackFormatComparator(java.util.Comparator)"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource.Factory","l":"setTrackId(String)","url":"setTrackId(java.lang.String)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder","l":"setTrackNameProvider(TrackNameProvider)","url":"setTrackNameProvider(com.google.android.exoplayer2.ui.TrackNameProvider)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionView","l":"setTrackNameProvider(TrackNameProvider)","url":"setTrackNameProvider(com.google.android.exoplayer2.ui.TrackNameProvider)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setTrackNumber(Integer)","url":"setTrackNumber(java.lang.Integer)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setTrackSelector(DefaultTrackSelector)","url":"setTrackSelector(com.google.android.exoplayer2.trackselection.DefaultTrackSelector)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"setTrackSelector(DefaultTrackSelector)","url":"setTrackSelector(com.google.android.exoplayer2.trackselection.DefaultTrackSelector)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"setTrackSelector(TrackSelector)","url":"setTrackSelector(com.google.android.exoplayer2.trackselection.TrackSelector)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setTrackSelector(TrackSelector)","url":"setTrackSelector(com.google.android.exoplayer2.trackselection.TrackSelector)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"setTransferListener(TransferListener)","url":"setTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource.Factory","l":"setTransferListener(TransferListener)","url":"setTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource.Factory","l":"setTransferListener(TransferListener)","url":"setTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource.Factory","l":"setTreatLoadErrorsAsEndOfStream(boolean)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.DefaultAllowedCommandProvider","l":"setTrustedPackageNames(List)","url":"setTrustedPackageNames(java.util.List)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"setTsExtractorFlags(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"setTsExtractorMode(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"setTsExtractorTimestampSearchBytes(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setTunnelingEnabled(boolean)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"setType(int)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setUnderline(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setUnplayedColor(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setUpdateTimeMs(long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"setUpstreamDataSourceFactory(DataSource.Factory)","url":"setUpstreamDataSourceFactory(com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"setUpstreamFormatChangeListener(SampleQueue.UpstreamFormatChangedListener)","url":"setUpstreamFormatChangeListener(com.google.android.exoplayer2.source.SampleQueue.UpstreamFormatChangedListener)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"setUpstreamPriority(int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"setUpstreamPriorityTaskManager(PriorityTaskManager)","url":"setUpstreamPriorityTaskManager(com.google.android.exoplayer2.util.PriorityTaskManager)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setUri(String)","url":"setUri(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.TestResource.Builder","l":"setUri(String)","url":"setUri(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setUri(String)","url":"setUri(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"setUri(String)","url":"setUri(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setUri(Uri)","url":"setUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.TestResource.Builder","l":"setUri(Uri)","url":"setUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setUri(Uri)","url":"setUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"setUri(Uri)","url":"setUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"setUriPositionOffset(long)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes.Builder","l":"setUsage(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setUseArtwork(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setUseArtwork(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setUseChronometer(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setUseController(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setUseController(boolean)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager.Builder","l":"setUseDrmSessionsForClearContent(int...)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"setUseLazyPreparation(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setUseLazyPreparation(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setUseLazyPreparation(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"setUseLazyPreparation(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setUseNavigationActions(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setUseNavigationActionsInCompactView(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setUseNextAction(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setUseNextActionInCompactView(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setUsePlayPauseActions(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setUsePreviousAction(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setUsePreviousActionInCompactView(boolean)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"setUserAgent(String)","url":"setUserAgent(java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource.Factory","l":"setUserAgent(String)","url":"setUserAgent(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.Factory","l":"setUserAgent(String)","url":"setUserAgent(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource.Factory","l":"setUserAgent(String)","url":"setUserAgent(java.lang.String)"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"setUserDefaultStyle()"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"setUserDefaultTextSize()"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setUserRating(Rating)","url":"setUserRating(com.google.android.exoplayer2.Rating)"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView","l":"setUseSensorRotation(boolean)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setUseSessionKeys(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setUseStopAction(boolean)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager.Builder","l":"setUuidAndExoMediaDrmProvider(UUID, ExoMediaDrm.Provider)","url":"setUuidAndExoMediaDrmProvider(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm.Provider)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setVastLoadTimeoutMs(int)"},{"p":"com.google.android.exoplayer2.database","c":"VersionTable","l":"setVersion(SQLiteDatabase, int, String, int)","url":"setVersion(android.database.sqlite.SQLiteDatabase,int,java.lang.String,int)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setVerticalType(int)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setVideoAdPlayerCallback(VideoAdPlayer.VideoAdPlayerCallback)","url":"setVideoAdPlayerCallback(com.google.ads.interactivemedia.v3.api.player.VideoAdPlayer.VideoAdPlayerCallback)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"setVideoFrameMetadataListener(VideoFrameMetadataListener)","url":"setVideoFrameMetadataListener(com.google.android.exoplayer2.video.VideoFrameMetadataListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setVideoFrameMetadataListener(VideoFrameMetadataListener)","url":"setVideoFrameMetadataListener(com.google.android.exoplayer2.video.VideoFrameMetadataListener)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"setVideoScalingMode(int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setVideoScalingMode(int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setVideoScalingMode(int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"setVideoScalingMode(int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"setVideoScalingMode(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"setVideoSurface()"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetVideoSurface","l":"SetVideoSurface(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"setVideoSurface(Surface)","url":"setVideoSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setVideoSurface(Surface)","url":"setVideoSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setVideoSurface(Surface)","url":"setVideoSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setVideoSurface(Surface)","url":"setVideoSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setVideoSurface(Surface)","url":"setVideoSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setVideoSurface(Surface)","url":"setVideoSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"setVideoSurfaceHolder(SurfaceHolder)","url":"setVideoSurfaceHolder(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setVideoSurfaceHolder(SurfaceHolder)","url":"setVideoSurfaceHolder(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setVideoSurfaceHolder(SurfaceHolder)","url":"setVideoSurfaceHolder(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setVideoSurfaceHolder(SurfaceHolder)","url":"setVideoSurfaceHolder(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setVideoSurfaceHolder(SurfaceHolder)","url":"setVideoSurfaceHolder(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"setVideoSurfaceView(SurfaceView)","url":"setVideoSurfaceView(android.view.SurfaceView)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setVideoSurfaceView(SurfaceView)","url":"setVideoSurfaceView(android.view.SurfaceView)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setVideoSurfaceView(SurfaceView)","url":"setVideoSurfaceView(android.view.SurfaceView)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setVideoSurfaceView(SurfaceView)","url":"setVideoSurfaceView(android.view.SurfaceView)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setVideoSurfaceView(SurfaceView)","url":"setVideoSurfaceView(android.view.SurfaceView)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"setVideoTextureView(TextureView)","url":"setVideoTextureView(android.view.TextureView)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setVideoTextureView(TextureView)","url":"setVideoTextureView(android.view.TextureView)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setVideoTextureView(TextureView)","url":"setVideoTextureView(android.view.TextureView)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setVideoTextureView(TextureView)","url":"setVideoTextureView(android.view.TextureView)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setVideoTextureView(TextureView)","url":"setVideoTextureView(android.view.TextureView)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setViewportSize(int, int, boolean)","url":"setViewportSize(int,int,boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setViewportSizeToPhysicalDisplaySize(Context, boolean)","url":"setViewportSizeToPhysicalDisplaySize(android.content.Context,boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"setViewType(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setVisibility(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setVisibility(int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setVisibility(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioComponent","l":"setVolume(float)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setVolume(float)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setVolume(float)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"setVolume(float)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"setVolume(float)"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"setVolume(float)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setVolume(float)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setVolume(float)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setVrButtonListener(View.OnClickListener)","url":"setVrButtonListener(android.view.View.OnClickListener)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setVrButtonListener(View.OnClickListener)","url":"setVrButtonListener(android.view.View.OnClickListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setWakeMode(int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setWakeMode(int)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setWidth(int)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setWindowColor(int)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setYear(Integer)","url":"setYear(java.lang.Integer)"},{"p":"com.google.android.exoplayer2.robolectric","c":"ShadowMediaCodecConfig","l":"ShadowMediaCodecConfig()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"sharedInitializeOrWait(boolean, long)","url":"sharedInitializeOrWait(boolean,long)"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"shearDegrees"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"shouldCancelChunkLoad(long, Chunk, List)","url":"shouldCancelChunkLoad(long,com.google.android.exoplayer2.source.chunk.Chunk,java.util.List)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSource","l":"shouldCancelLoad(long, Chunk, List)","url":"shouldCancelLoad(long,com.google.android.exoplayer2.source.chunk.Chunk,java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"shouldCancelLoad(long, Chunk, List)","url":"shouldCancelLoad(long,com.google.android.exoplayer2.source.chunk.Chunk,java.util.List)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource","l":"shouldCancelLoad(long, Chunk, List)","url":"shouldCancelLoad(long,com.google.android.exoplayer2.source.chunk.Chunk,java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource","l":"shouldCancelLoad(long, Chunk, List)","url":"shouldCancelLoad(long,com.google.android.exoplayer2.source.chunk.Chunk,java.util.List)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"shouldContinueLoading(long, long, float)","url":"shouldContinueLoading(long,long,float)"},{"p":"com.google.android.exoplayer2","c":"LoadControl","l":"shouldContinueLoading(long, long, float)","url":"shouldContinueLoading(long,long,float)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"shouldDropBuffersToKeyframe(long, long, boolean)","url":"shouldDropBuffersToKeyframe(long,long,boolean)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"shouldDropBuffersToKeyframe(long, long)","url":"shouldDropBuffersToKeyframe(long,long)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"shouldDropOutputBuffer(long, long, boolean)","url":"shouldDropOutputBuffer(long,long,boolean)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"shouldDropOutputBuffer(long, long)","url":"shouldDropOutputBuffer(long,long)"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"shouldEvaluateQueueSize(long, List)","url":"shouldEvaluateQueueSize(long,java.util.List)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"shouldForceRenderOutputBuffer(long, long)","url":"shouldForceRenderOutputBuffer(long,long)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"shouldForceRenderOutputBuffer(long, long)","url":"shouldForceRenderOutputBuffer(long,long)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"shouldInitCodec(MediaCodecInfo)","url":"shouldInitCodec(com.google.android.exoplayer2.mediacodec.MediaCodecInfo)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"shouldInitCodec(MediaCodecInfo)","url":"shouldInitCodec(com.google.android.exoplayer2.mediacodec.MediaCodecInfo)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAudioRenderer","l":"shouldProcessBuffer(long, long)","url":"shouldProcessBuffer(long,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"shouldProcessBuffer(long, long)","url":"shouldProcessBuffer(long,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeVideoRenderer","l":"shouldProcessBuffer(long, long)","url":"shouldProcessBuffer(long,long)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"shouldStartPlayback(long, float, boolean, long)","url":"shouldStartPlayback(long,float,boolean,long)"},{"p":"com.google.android.exoplayer2","c":"LoadControl","l":"shouldStartPlayback(long, float, boolean, long)","url":"shouldStartPlayback(long,float,boolean,long)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"shouldUseBypass(Format)","url":"shouldUseBypass(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"shouldUseBypass(Format)","url":"shouldUseBypass(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"SHOW_BUFFERING_ALWAYS"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"SHOW_BUFFERING_ALWAYS"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"SHOW_BUFFERING_NEVER"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"SHOW_BUFFERING_NEVER"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"SHOW_BUFFERING_WHEN_PLAYING"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"SHOW_BUFFERING_WHEN_PLAYING"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"show()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"show()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"showController()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"showController()"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"showScrubber()"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"showScrubber(long)"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource","l":"SilenceMediaSource(long)","url":"%3Cinit%3E(long)"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"SilenceSkippingAudioProcessor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"SilenceSkippingAudioProcessor(long, long, short)","url":"%3Cinit%3E(long,long,short)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"SimpleCache(File, CacheEvictor, byte[], boolean)","url":"%3Cinit%3E(java.io.File,com.google.android.exoplayer2.upstream.cache.CacheEvictor,byte[],boolean)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"SimpleCache(File, CacheEvictor, byte[])","url":"%3Cinit%3E(java.io.File,com.google.android.exoplayer2.upstream.cache.CacheEvictor,byte[])"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"SimpleCache(File, CacheEvictor, DatabaseProvider, byte[], boolean, boolean)","url":"%3Cinit%3E(java.io.File,com.google.android.exoplayer2.upstream.cache.CacheEvictor,com.google.android.exoplayer2.database.DatabaseProvider,byte[],boolean,boolean)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"SimpleCache(File, CacheEvictor, DatabaseProvider)","url":"%3Cinit%3E(java.io.File,com.google.android.exoplayer2.upstream.cache.CacheEvictor,com.google.android.exoplayer2.database.DatabaseProvider)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"SimpleCache(File, CacheEvictor)","url":"%3Cinit%3E(java.io.File,com.google.android.exoplayer2.upstream.cache.CacheEvictor)"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleDecoder","l":"SimpleDecoder(I[], O[])","url":"%3Cinit%3E(I[],O[])"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"SimpleExoPlayer(Context, RenderersFactory, TrackSelector, MediaSourceFactory, LoadControl, BandwidthMeter, AnalyticsCollector, boolean, Clock, Looper)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.RenderersFactory,com.google.android.exoplayer2.trackselection.TrackSelector,com.google.android.exoplayer2.source.MediaSourceFactory,com.google.android.exoplayer2.LoadControl,com.google.android.exoplayer2.upstream.BandwidthMeter,com.google.android.exoplayer2.analytics.AnalyticsCollector,boolean,com.google.android.exoplayer2.util.Clock,android.os.Looper)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"SimpleExoPlayer(SimpleExoPlayer.Builder)","url":"%3Cinit%3E(com.google.android.exoplayer2.SimpleExoPlayer.Builder)"},{"p":"com.google.android.exoplayer2.metadata","c":"SimpleMetadataDecoder","l":"SimpleMetadataDecoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleOutputBuffer","l":"SimpleOutputBuffer(OutputBuffer.Owner)","url":"%3Cinit%3E(com.google.android.exoplayer2.decoder.OutputBuffer.Owner)"},{"p":"com.google.android.exoplayer2.text","c":"SimpleSubtitleDecoder","l":"SimpleSubtitleDecoder(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput.SimulatedIOException","l":"SimulatedIOException(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts.SimulationConfig","l":"simulateIOErrors"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts.SimulationConfig","l":"simulatePartialReads"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts.SimulationConfig","l":"simulateUnknownLength"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"SINGLE_WINDOW_UID"},{"p":"com.google.android.exoplayer2.source.ads","c":"SinglePeriodAdTimeline","l":"SinglePeriodAdTimeline(Timeline, AdPlaybackState)","url":"%3Cinit%3E(com.google.android.exoplayer2.Timeline,com.google.android.exoplayer2.source.ads.AdPlaybackState)"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"SinglePeriodTimeline(long, boolean, boolean, boolean, Object, MediaItem)","url":"%3Cinit%3E(long,boolean,boolean,boolean,java.lang.Object,com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"SinglePeriodTimeline(long, boolean, boolean, boolean, Object, Object)","url":"%3Cinit%3E(long,boolean,boolean,boolean,java.lang.Object,java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"SinglePeriodTimeline(long, long, long, long, boolean, boolean, boolean, Object, MediaItem)","url":"%3Cinit%3E(long,long,long,long,boolean,boolean,boolean,java.lang.Object,com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"SinglePeriodTimeline(long, long, long, long, boolean, boolean, boolean, Object, Object)","url":"%3Cinit%3E(long,long,long,long,boolean,boolean,boolean,java.lang.Object,java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"SinglePeriodTimeline(long, long, long, long, long, long, long, boolean, boolean, boolean, Object, MediaItem, MediaItem.LiveConfiguration)","url":"%3Cinit%3E(long,long,long,long,long,long,long,boolean,boolean,boolean,java.lang.Object,com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.MediaItem.LiveConfiguration)"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"SinglePeriodTimeline(long, long, long, long, long, long, long, boolean, boolean, boolean, Object, Object)","url":"%3Cinit%3E(long,long,long,long,long,long,long,boolean,boolean,boolean,java.lang.Object,java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"SinglePeriodTimeline(long, long, long, long, long, long, long, boolean, boolean, Object, MediaItem, MediaItem.LiveConfiguration)","url":"%3Cinit%3E(long,long,long,long,long,long,long,boolean,boolean,java.lang.Object,com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.MediaItem.LiveConfiguration)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"SingleSampleMediaChunk","l":"SingleSampleMediaChunk(DataSource, DataSpec, Format, int, Object, long, long, long, int, Format)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,com.google.android.exoplayer2.Format,int,java.lang.Object,long,long,long,int,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod.TrackDataFactory","l":"singleSampleWithTimeUs(long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SingleSegmentBase","l":"SingleSegmentBase()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SingleSegmentBase","l":"SingleSegmentBase(RangedUri, long, long, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.dash.manifest.RangedUri,long,long,long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.SingleSegmentRepresentation","l":"SingleSegmentRepresentation(long, Format, String, SegmentBase.SingleSegmentBase, List, String, long)","url":"%3Cinit%3E(long,com.google.android.exoplayer2.Format,java.lang.String,com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase,java.util.List,java.lang.String,long)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"SINK_FORMAT_SUPPORTED_DIRECTLY"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"SINK_FORMAT_SUPPORTED_WITH_TRANSCODING"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"SINK_FORMAT_UNSUPPORTED"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"sinkSupportsFormat(Format)","url":"sinkSupportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"size"},{"p":"com.google.android.exoplayer2","c":"Player.Commands","l":"size()"},{"p":"com.google.android.exoplayer2","c":"Player.Events","l":"size()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.Events","l":"size()"},{"p":"com.google.android.exoplayer2.util","c":"ExoFlags","l":"size()"},{"p":"com.google.android.exoplayer2.util","c":"IntArrayQueue","l":"size()"},{"p":"com.google.android.exoplayer2.util","c":"LongArray","l":"size()"},{"p":"com.google.android.exoplayer2.util","c":"TimedValueQueue","l":"size()"},{"p":"com.google.android.exoplayer2.extractor","c":"ChunkIndex","l":"sizes"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"skip(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"skip(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"skip(int)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"skip(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"skip(int)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"skipAd()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"skipBit()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableNalUnitBitArray","l":"skipBit()"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisBitArray","l":"skipBits(int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"skipBits(int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableNalUnitBitArray","l":"skipBits(int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"skipBytes(int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"skipBytes(int)"},{"p":"com.google.android.exoplayer2.source","c":"EmptySampleStream","l":"skipData(long)"},{"p":"com.google.android.exoplayer2.source","c":"SampleStream","l":"skipData(long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"skipData(long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream.EmbeddedSampleStream","l":"skipData(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"skipData(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"skipFully(int, boolean)","url":"skipFully(int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"skipFully(int, boolean)","url":"skipFully(int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"skipFully(int, boolean)","url":"skipFully(int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"skipFully(int, boolean)","url":"skipFully(int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"skipFully(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"skipFully(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"skipFully(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"skipFully(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorUtil","l":"skipFullyQuietly(ExtractorInput, int)","url":"skipFullyQuietly(com.google.android.exoplayer2.extractor.ExtractorInput,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"skipInputUntilPosition(ExtractorInput, long)","url":"skipInputUntilPosition(com.google.android.exoplayer2.extractor.ExtractorInput,long)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"skipOutputBuffer(MediaCodecAdapter, int, long)","url":"skipOutputBuffer(com.google.android.exoplayer2.mediacodec.MediaCodecAdapter,int,long)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"skipOutputBuffer(VideoDecoderOutputBuffer)","url":"skipOutputBuffer(com.google.android.exoplayer2.video.VideoDecoderOutputBuffer)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"skippedInputBufferCount"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"skippedOutputBufferCount"},{"p":"com.google.android.exoplayer2.decoder","c":"OutputBuffer","l":"skippedOutputBufferCount"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"skipSettingMediaSources()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener.EventDispatcher","l":"skipSilenceEnabledChanged(boolean)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"skipSource(long)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"skipToNextPlaylistItem()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"skipToPlaylistItem(int)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"skipToPreviousPlaylistItem()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.ServerControl","l":"skipUntilUs"},{"p":"com.google.android.exoplayer2.util","c":"SlidingPercentile","l":"SlidingPercentile(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData","l":"SlowMotionData(List)","url":"%3Cinit%3E(java.util.List)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SmtaMetadataEntry","l":"SmtaMetadataEntry(float, int)","url":"%3Cinit%3E(float,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"sneakyThrow(Throwable)","url":"sneakyThrow(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor","c":"Extractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.amr","c":"AmrExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.flac","c":"FlacExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.flv","c":"FlvExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.jpeg","c":"JpegExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.ogg","c":"OggExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.rawcc","c":"RawCcExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Extractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Extractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.wav","c":"WavExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.source.hls","c":"WebvttExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts.SimulationConfig","l":"sniffFirst"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"softwareOnly"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"SonicAudioProcessor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ProgramInformation","l":"source"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetEngineWrapper","l":"SOURCE_GMS"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetEngineWrapper","l":"SOURCE_NATIVE"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetEngineWrapper","l":"SOURCE_UNAVAILABLE"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetEngineWrapper","l":"SOURCE_UNKNOWN"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetEngineWrapper","l":"SOURCE_USER_PROVIDED"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"sourceId(int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"spanned()"},{"p":"com.google.android.exoplayer2","c":"PlaybackParameters","l":"speed"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData.Segment","l":"speedDivisor"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView","l":"SphericalGLSurfaceView(Context, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView","l":"SphericalGLSurfaceView(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"splice()"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceCommand","l":"SpliceCommand()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"spliceEventCancelIndicator"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.Event","l":"spliceEventCancelIndicator"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"spliceEventId"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.Event","l":"spliceEventId"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"spliceImmediateFlag"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInfoDecoder","l":"SpliceInfoDecoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceNullCommand","l":"SpliceNullCommand()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"split(String, String)","url":"split(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"splitAtFirst(String, String)","url":"splitAtFirst(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"splitCodecs(String)","url":"splitCodecs(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"CodecSpecificDataUtil","l":"splitNalUnits(byte[])"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"SpsData(int, int, int, int, int, int, float, boolean, boolean, int, int, int, boolean)","url":"%3Cinit%3E(int,int,int,int,int,int,float,boolean,boolean,int,int,int,boolean)"},{"p":"com.google.android.exoplayer2.text.ssa","c":"SsaDecoder","l":"SsaDecoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.text.ssa","c":"SsaDecoder","l":"SsaDecoder(List)","url":"%3Cinit%3E(java.util.List)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.offline","c":"SsDownloader","l":"SsDownloader(MediaItem, CacheDataSource.Factory, Executor)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.offline","c":"SsDownloader","l":"SsDownloader(MediaItem, CacheDataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.offline","c":"SsDownloader","l":"SsDownloader(MediaItem, ParsingLoadable.Parser, CacheDataSource.Factory, Executor)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.upstream.ParsingLoadable.Parser,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.offline","c":"SsDownloader","l":"SsDownloader(Uri, List, CacheDataSource.Factory, Executor)","url":"%3Cinit%3E(android.net.Uri,java.util.List,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.offline","c":"SsDownloader","l":"SsDownloader(Uri, List, CacheDataSource.Factory)","url":"%3Cinit%3E(android.net.Uri,java.util.List,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest","l":"SsManifest(int, int, long, long, long, int, boolean, SsManifest.ProtectionElement, SsManifest.StreamElement[])","url":"%3Cinit%3E(int,int,long,long,long,int,boolean,com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest.ProtectionElement,com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest.StreamElement[])"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifestParser","l":"SsManifestParser()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"ssrc"},{"p":"com.google.android.exoplayer2.util","c":"StandaloneMediaClock","l":"StandaloneMediaClock(Clock)","url":"%3Cinit%3E(com.google.android.exoplayer2.util.Clock)"},{"p":"com.google.android.exoplayer2","c":"StarRating","l":"StarRating(int, float)","url":"%3Cinit%3E(int,float)"},{"p":"com.google.android.exoplayer2","c":"StarRating","l":"StarRating(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"RangedUri","l":"start"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekPoint","l":"START"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"start()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"start()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"start()"},{"p":"com.google.android.exoplayer2.scheduler","c":"RequirementsWatcher","l":"start()"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"start()"},{"p":"com.google.android.exoplayer2.util","c":"DebugTextViewHelper","l":"start()"},{"p":"com.google.android.exoplayer2.util","c":"StandaloneMediaClock","l":"start()"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"start(AdsMediaSource, DataSpec, Object, AdViewProvider, AdsLoader.EventListener)","url":"start(com.google.android.exoplayer2.source.ads.AdsMediaSource,com.google.android.exoplayer2.upstream.DataSpec,java.lang.Object,com.google.android.exoplayer2.ui.AdViewProvider,com.google.android.exoplayer2.source.ads.AdsLoader.EventListener)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsLoader","l":"start(AdsMediaSource, DataSpec, Object, AdViewProvider, AdsLoader.EventListener)","url":"start(com.google.android.exoplayer2.source.ads.AdsMediaSource,com.google.android.exoplayer2.upstream.DataSpec,java.lang.Object,com.google.android.exoplayer2.ui.AdViewProvider,com.google.android.exoplayer2.source.ads.AdsLoader.EventListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"start(boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"start(Context, Class)","url":"start(android.content.Context,java.lang.Class)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"start(Uri, MediaSourceEventListener.EventDispatcher, HlsPlaylistTracker.PrimaryPlaylistListener)","url":"start(android.net.Uri,com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher,com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker.PrimaryPlaylistListener)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"start(Uri, MediaSourceEventListener.EventDispatcher, HlsPlaylistTracker.PrimaryPlaylistListener)","url":"start(android.net.Uri,com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher,com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker.PrimaryPlaylistListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"Dumper","l":"startBlock(String)","url":"startBlock(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"startFile(String, long, long)","url":"startFile(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"startFile(String, long, long)","url":"startFile(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"startForeground(Context, Class)","url":"startForeground(android.content.Context,java.lang.Class)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"startForegroundService(Context, Intent)","url":"startForegroundService(android.content.Context,android.content.Intent)"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"startLoading(T, Loader.Callback, int)","url":"startLoading(T,com.google.android.exoplayer2.upstream.Loader.Callback,int)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"startMasterElement(int, long, long)","url":"startMasterElement(int,long,long)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"startMasterElement(int, long, long)","url":"startMasterElement(int,long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Period","l":"startMs"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"startOffset"},{"p":"com.google.android.exoplayer2.extractor.jpeg","c":"StartOffsetExtractorOutput","l":"StartOffsetExtractorOutput(long, ExtractorOutput)","url":"%3Cinit%3E(long,com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"startOffsetUs"},{"p":"com.google.android.exoplayer2","c":"MediaItem.ClippingProperties","l":"startPositionMs"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"startReadWrite(String, long, long)","url":"startReadWrite(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"startReadWrite(String, long, long)","url":"startReadWrite(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"startReadWriteNonBlocking(String, long, long)","url":"startReadWriteNonBlocking(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"startReadWriteNonBlocking(String, long, long)","url":"startReadWriteNonBlocking(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.ClippingProperties","l":"startsAtKeyFrame"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"startTimeMs"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData.Segment","l":"startTimeMs"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"startTimeMs"},{"p":"com.google.android.exoplayer2.offline","c":"SegmentDownloader.Segment","l":"startTimeUs"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"startTimeUs"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"startTimeUs"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCueInfo","l":"startTimeUs"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer","l":"startTransformation(MediaItem, ParcelFileDescriptor)","url":"startTransformation(com.google.android.exoplayer2.MediaItem,android.os.ParcelFileDescriptor)"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer","l":"startTransformation(MediaItem, String)","url":"startTransformation(com.google.android.exoplayer2.MediaItem,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"AtomicFile","l":"startWrite()"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"state"},{"p":"com.google.android.exoplayer2","c":"Player","l":"STATE_BUFFERING"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"STATE_COMPLETED"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"STATE_DISABLED"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"STATE_DOWNLOADING"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"STATE_ENABLED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"STATE_ENDED"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"STATE_ERROR"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"STATE_FAILED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"STATE_IDLE"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"STATE_OPENED"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"STATE_OPENED_WITH_KEYS"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"STATE_OPENING"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"STATE_QUEUED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"STATE_READY"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"STATE_RELEASED"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"STATE_REMOVING"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"STATE_RESTARTING"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"STATE_STARTED"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"STATE_STOPPED"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"states"},{"p":"com.google.android.exoplayer2.upstream","c":"StatsDataSource","l":"StatsDataSource(DataSource)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource)"},{"p":"com.google.android.exoplayer2","c":"C","l":"STEREO_MODE_LEFT_RIGHT"},{"p":"com.google.android.exoplayer2","c":"C","l":"STEREO_MODE_MONO"},{"p":"com.google.android.exoplayer2","c":"C","l":"STEREO_MODE_STEREO_MESH"},{"p":"com.google.android.exoplayer2","c":"C","l":"STEREO_MODE_TOP_BOTTOM"},{"p":"com.google.android.exoplayer2","c":"Format","l":"stereoMode"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"STOP_REASON_NONE"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"stop()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"stop()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"stop()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"stop()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"stop()"},{"p":"com.google.android.exoplayer2.scheduler","c":"RequirementsWatcher","l":"stop()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"stop()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"stop()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"stop()"},{"p":"com.google.android.exoplayer2.util","c":"DebugTextViewHelper","l":"stop()"},{"p":"com.google.android.exoplayer2.util","c":"StandaloneMediaClock","l":"stop()"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"stop(AdsMediaSource, AdsLoader.EventListener)","url":"stop(com.google.android.exoplayer2.source.ads.AdsMediaSource,com.google.android.exoplayer2.source.ads.AdsLoader.EventListener)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsLoader","l":"stop(AdsMediaSource, AdsLoader.EventListener)","url":"stop(com.google.android.exoplayer2.source.ads.AdsMediaSource,com.google.android.exoplayer2.source.ads.AdsLoader.EventListener)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"stop(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"stop(boolean)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"stop(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"stop(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"stop(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.Stop","l":"Stop(String, boolean)","url":"%3Cinit%3E(java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.Stop","l":"Stop(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"stopReason"},{"p":"com.google.android.exoplayer2.util","c":"FlacConstants","l":"STREAM_INFO_BLOCK_SIZE"},{"p":"com.google.android.exoplayer2.util","c":"FlacConstants","l":"STREAM_MARKER_SIZE"},{"p":"com.google.android.exoplayer2","c":"C","l":"STREAM_TYPE_ALARM"},{"p":"com.google.android.exoplayer2","c":"C","l":"STREAM_TYPE_DEFAULT"},{"p":"com.google.android.exoplayer2","c":"C","l":"STREAM_TYPE_DTMF"},{"p":"com.google.android.exoplayer2","c":"C","l":"STREAM_TYPE_MUSIC"},{"p":"com.google.android.exoplayer2","c":"C","l":"STREAM_TYPE_NOTIFICATION"},{"p":"com.google.android.exoplayer2","c":"C","l":"STREAM_TYPE_RING"},{"p":"com.google.android.exoplayer2","c":"C","l":"STREAM_TYPE_SYSTEM"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util.SyncFrameInfo","l":"STREAM_TYPE_TYPE0"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util.SyncFrameInfo","l":"STREAM_TYPE_TYPE1"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util.SyncFrameInfo","l":"STREAM_TYPE_TYPE2"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util.SyncFrameInfo","l":"STREAM_TYPE_UNDEFINED"},{"p":"com.google.android.exoplayer2","c":"C","l":"STREAM_TYPE_VOICE_CALL"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"StreamElement(String, String, int, String, long, String, int, int, int, int, String, Format[], List, long)","url":"%3Cinit%3E(java.lang.String,java.lang.String,int,java.lang.String,long,java.lang.String,int,int,int,int,java.lang.String,com.google.android.exoplayer2.Format[],java.util.List,long)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest","l":"streamElements"},{"p":"com.google.android.exoplayer2.offline","c":"StreamKey","l":"StreamKey(int, int, int)","url":"%3Cinit%3E(int,int,int)"},{"p":"com.google.android.exoplayer2.offline","c":"StreamKey","l":"StreamKey(int, int)","url":"%3Cinit%3E(int,int)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.PlaybackProperties","l":"streamKeys"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"streamKeys"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util.SyncFrameInfo","l":"streamType"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.EsInfo","l":"streamType"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"stringElement(int, String)","url":"stringElement(int,java.lang.String)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"stringElement(int, String)","url":"stringElement(int,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"StubExoPlayer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"STYLE_BOLD"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"STYLE_BOLD_ITALIC"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"STYLE_ITALIC"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"STYLE_NORMAL"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"StyledPlayerControlView(Context, AttributeSet, int, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet,int,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"StyledPlayerControlView(Context, AttributeSet, int)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet,int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"StyledPlayerControlView(Context, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"StyledPlayerControlView(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"StyledPlayerView(Context, AttributeSet, int)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet,int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"StyledPlayerView(Context, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"StyledPlayerView(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"subrange(long, long)","url":"subrange(long,long)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"subrange(long)"},{"p":"com.google.android.exoplayer2.text.subrip","c":"SubripDecoder","l":"SubripDecoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"Format","l":"subsampleOffsetUs"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataInputBuffer","l":"subsampleOffsetUs"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleInputBuffer","l":"subsampleOffsetUs"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts.RequestSet","l":"subset(DataSpec...)","url":"subset(com.google.android.exoplayer2.upstream.DataSpec...)"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts.RequestSet","l":"subset(String...)","url":"subset(java.lang.String...)"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts.RequestSet","l":"subset(Uri...)","url":"subset(android.net.Uri...)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"subtitle"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Subtitle","l":"Subtitle(Uri, String, String, int, int, String)","url":"%3Cinit%3E(android.net.Uri,java.lang.String,java.lang.String,int,int,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Subtitle","l":"Subtitle(Uri, String, String, int)","url":"%3Cinit%3E(android.net.Uri,java.lang.String,java.lang.String,int)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Subtitle","l":"Subtitle(Uri, String, String)","url":"%3Cinit%3E(android.net.Uri,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleDecoderException","l":"SubtitleDecoderException(String, Throwable)","url":"%3Cinit%3E(java.lang.String,java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleDecoderException","l":"SubtitleDecoderException(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleDecoderException","l":"SubtitleDecoderException(Throwable)","url":"%3Cinit%3E(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry.VariantInfo","l":"subtitleGroupId"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Variant","l":"subtitleGroupId"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleInputBuffer","l":"SubtitleInputBuffer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleOutputBuffer","l":"SubtitleOutputBuffer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.PlaybackProperties","l":"subtitles"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"subtitles"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"SubtitleView(Context, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"SubtitleView(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"subtractWithOverflowDefault(long, long, long)","url":"subtractWithOverflowDefault(long,long,long)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"subType"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"suggestedPresentationDelayMs"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"supplementalData"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"supplementalData"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"AdaptationSet","l":"supplementalProperties"},{"p":"com.google.android.exoplayer2.audio","c":"AudioCapabilities","l":"supportsEncoding(int)"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Libgav1VideoRenderer","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"LibvpxVideoRenderer","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataDecoderFactory","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataRenderer","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleDecoderFactory","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.text","c":"TextRenderer","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.video.spherical","c":"CameraMotionRenderer","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"supportsFormat(MediaCodecSelector, Format)","url":"supportsFormat(com.google.android.exoplayer2.mediacodec.MediaCodecSelector,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"supportsFormat(MediaCodecSelector, Format)","url":"supportsFormat(com.google.android.exoplayer2.mediacodec.MediaCodecSelector,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"supportsFormat(MediaCodecSelector, Format)","url":"supportsFormat(com.google.android.exoplayer2.mediacodec.MediaCodecSelector,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegLibrary","l":"supportsFormat(String)","url":"supportsFormat(java.lang.String)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"supportsFormatDrm(Format)","url":"supportsFormatDrm(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"supportsFormatInternal(Format)","url":"supportsFormatInternal(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegAudioRenderer","l":"supportsFormatInternal(Format)","url":"supportsFormatInternal(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"LibflacAudioRenderer","l":"supportsFormatInternal(Format)","url":"supportsFormatInternal(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.ext.opus","c":"LibopusAudioRenderer","l":"supportsFormatInternal(Format)","url":"supportsFormatInternal(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"supportsMixedMimeTypeAdaptation()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"supportsMixedMimeTypeAdaptation()"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"supportsMixedMimeTypeAdaptation()"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegAudioRenderer","l":"supportsMixedMimeTypeAdaptation()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"supportsMixedMimeTypeAdaptation()"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource","l":"supportsRangeRequests()"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource.Builder","l":"supportsRangeRequests(boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter.Configuration","l":"surface"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity","l":"surfaceChanged(SurfaceHolder, int, int, int)","url":"surfaceChanged(android.view.SurfaceHolder,int,int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity","l":"surfaceCreated(SurfaceHolder)","url":"surfaceCreated(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity","l":"surfaceDestroyed(SurfaceHolder)","url":"surfaceDestroyed(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoDecoderException","l":"surfaceIdentityHashCode"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SmtaMetadataEntry","l":"svcTemporalLayerCount"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"switchTargetView(Player, PlayerView, PlayerView)","url":"switchTargetView(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ui.PlayerView,com.google.android.exoplayer2.ui.PlayerView)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"switchTargetView(Player, StyledPlayerView, StyledPlayerView)","url":"switchTargetView(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ui.StyledPlayerView,com.google.android.exoplayer2.ui.StyledPlayerView)"},{"p":"com.google.android.exoplayer2.util","c":"SystemClock","l":"SystemClock()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.database","c":"DatabaseProvider","l":"TABLE_PREFIX"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"tableExists(SQLiteDatabase, String)","url":"tableExists(android.database.sqlite.SQLiteDatabase,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.PlaybackProperties","l":"tag"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"tag"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"tag"},{"p":"com.google.android.exoplayer2","c":"ExoPlayerLibraryInfo","l":"TAG"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"TAG"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylist","l":"tags"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"targetDurationUs"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.TimestampSearchResult","l":"targetFoundResult(long)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.LiveConfiguration","l":"targetOffsetMs"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ServiceDescriptionElement","l":"targetOffsetMs"},{"p":"com.google.android.exoplayer2.audio","c":"TeeAudioProcessor","l":"TeeAudioProcessor(TeeAudioProcessor.AudioBufferSink)","url":"%3Cinit%3E(com.google.android.exoplayer2.audio.TeeAudioProcessor.AudioBufferSink)"},{"p":"com.google.android.exoplayer2.upstream","c":"TeeDataSource","l":"TeeDataSource(DataSource, DataSink)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSink)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestDownloadManagerListener","l":"TestDownloadManagerListener(DownloadManager)","url":"%3Cinit%3E(com.google.android.exoplayer2.offline.DownloadManager)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"TestExoPlayerBuilder(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"CommentFrame","l":"text"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"InternalFrame","l":"text"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"text"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"TEXT_SIZE_TYPE_ABSOLUTE"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"TEXT_SIZE_TYPE_FRACTIONAL"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"TEXT_SIZE_TYPE_FRACTIONAL_IGNORE_PADDING"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"TEXT_SSA"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"TEXT_VTT"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"textAlignment"},{"p":"com.google.android.exoplayer2.text.span","c":"TextEmphasisSpan","l":"TextEmphasisSpan(int, int, int)","url":"%3Cinit%3E(int,int,int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"TextInformationFrame","l":"TextInformationFrame(String, String, String)","url":"%3Cinit%3E(java.lang.String,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.text","c":"TextRenderer","l":"TextRenderer(TextOutput, Looper, SubtitleDecoderFactory)","url":"%3Cinit%3E(com.google.android.exoplayer2.text.TextOutput,android.os.Looper,com.google.android.exoplayer2.text.SubtitleDecoderFactory)"},{"p":"com.google.android.exoplayer2.text","c":"TextRenderer","l":"TextRenderer(TextOutput, Looper)","url":"%3Cinit%3E(com.google.android.exoplayer2.text.TextOutput,android.os.Looper)"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"textSize"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"textSizeType"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.TextTrackScore","l":"TextTrackScore(Format, DefaultTrackSelector.Parameters, int, String)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters,int,java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Libgav1VideoRenderer","l":"THREAD_COUNT_AUTODETECT"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"throwPlaybackException(ExoPlaybackException)","url":"throwPlaybackException(com.google.android.exoplayer2.ExoPlaybackException)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.ThrowPlaybackException","l":"ThrowPlaybackException(String, ExoPlaybackException)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.ExoPlaybackException)"},{"p":"com.google.android.exoplayer2","c":"ThumbRating","l":"ThumbRating()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"ThumbRating","l":"ThumbRating(boolean)","url":"%3Cinit%3E(boolean)"},{"p":"com.google.android.exoplayer2","c":"C","l":"TIME_END_OF_SOURCE"},{"p":"com.google.android.exoplayer2","c":"C","l":"TIME_UNSET"},{"p":"com.google.android.exoplayer2.util","c":"TimedValueQueue","l":"TimedValueQueue()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.util","c":"TimedValueQueue","l":"TimedValueQueue(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2","c":"IllegalSeekPositionException","l":"timeline"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"timeline"},{"p":"com.google.android.exoplayer2.source","c":"ForwardingTimeline","l":"timeline"},{"p":"com.google.android.exoplayer2","c":"Player","l":"TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"TIMELINE_CHANGE_REASON_SOURCE_UPDATE"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"Timeline()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor","l":"TimelineQueueEditor(MediaControllerCompat, TimelineQueueEditor.QueueDataAdapter, TimelineQueueEditor.MediaDescriptionConverter, TimelineQueueEditor.MediaDescriptionEqualityChecker)","url":"%3Cinit%3E(android.support.v4.media.session.MediaControllerCompat,com.google.android.exoplayer2.ext.mediasession.TimelineQueueEditor.QueueDataAdapter,com.google.android.exoplayer2.ext.mediasession.TimelineQueueEditor.MediaDescriptionConverter,com.google.android.exoplayer2.ext.mediasession.TimelineQueueEditor.MediaDescriptionEqualityChecker)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor","l":"TimelineQueueEditor(MediaControllerCompat, TimelineQueueEditor.QueueDataAdapter, TimelineQueueEditor.MediaDescriptionConverter)","url":"%3Cinit%3E(android.support.v4.media.session.MediaControllerCompat,com.google.android.exoplayer2.ext.mediasession.TimelineQueueEditor.QueueDataAdapter,com.google.android.exoplayer2.ext.mediasession.TimelineQueueEditor.MediaDescriptionConverter)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueNavigator","l":"TimelineQueueNavigator(MediaSessionCompat, int)","url":"%3Cinit%3E(android.support.v4.media.session.MediaSessionCompat,int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueNavigator","l":"TimelineQueueNavigator(MediaSessionCompat)","url":"%3Cinit%3E(android.support.v4.media.session.MediaSessionCompat)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"TimelineWindowDefinition(boolean, boolean, long)","url":"%3Cinit%3E(boolean,boolean,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"TimelineWindowDefinition(int, Object, boolean, boolean, boolean, boolean, long, long, long, AdPlaybackState, MediaItem)","url":"%3Cinit%3E(int,java.lang.Object,boolean,boolean,boolean,boolean,long,long,long,com.google.android.exoplayer2.source.ads.AdPlaybackState,com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"TimelineWindowDefinition(int, Object, boolean, boolean, boolean, boolean, long, long, long, AdPlaybackState)","url":"%3Cinit%3E(int,java.lang.Object,boolean,boolean,boolean,boolean,long,long,long,com.google.android.exoplayer2.source.ads.AdPlaybackState)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"TimelineWindowDefinition(int, Object, boolean, boolean, long, AdPlaybackState)","url":"%3Cinit%3E(int,java.lang.Object,boolean,boolean,long,com.google.android.exoplayer2.source.ads.AdPlaybackState)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"TimelineWindowDefinition(int, Object, boolean, boolean, long)","url":"%3Cinit%3E(int,java.lang.Object,boolean,boolean,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"TimelineWindowDefinition(int, Object)","url":"%3Cinit%3E(int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.testutil","c":"DummyMainThread","l":"TIMEOUT_MS"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"TIMEOUT_MS"},{"p":"com.google.android.exoplayer2","c":"ExoTimeoutException","l":"TIMEOUT_OPERATION_DETACH_SURFACE"},{"p":"com.google.android.exoplayer2","c":"ExoTimeoutException","l":"TIMEOUT_OPERATION_RELEASE"},{"p":"com.google.android.exoplayer2","c":"ExoTimeoutException","l":"TIMEOUT_OPERATION_SET_FOREGROUND_MODE"},{"p":"com.google.android.exoplayer2","c":"ExoTimeoutException","l":"TIMEOUT_OPERATION_UNDEFINED"},{"p":"com.google.android.exoplayer2","c":"ExoTimeoutException","l":"timeoutOperation"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"timescale"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"EventStream","l":"timescale"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"timescale"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"timeShiftBufferDepthMs"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"timestamp"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"TimestampAdjuster(long)","url":"%3Cinit%3E(long)"},{"p":"com.google.android.exoplayer2.source.hls","c":"TimestampAdjusterProvider","l":"TimestampAdjusterProvider()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"timestampMs"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"timestampSeeker"},{"p":"com.google.android.exoplayer2.extractor","c":"ChunkIndex","l":"timesUs"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"timeUs"},{"p":"com.google.android.exoplayer2.decoder","c":"OutputBuffer","l":"timeUs"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekPoint","l":"timeUs"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.BinarySearchSeekMap","l":"timeUsToTargetTime(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.DefaultSeekTimestampConverter","l":"timeUsToTargetTime(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.SeekTimestampConverter","l":"timeUsToTargetTime(long)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"title"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyInfo","l":"title"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ProgramInformation","l":"title"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.Segment","l":"title"},{"p":"com.google.android.exoplayer2.util","c":"LongArray","l":"toArray()"},{"p":"com.google.android.exoplayer2","c":"Bundleable","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"HeartRating","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.ClippingProperties","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.LiveConfiguration","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"PercentageRating","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"PlaybackParameters","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"StarRating","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"ThumbRating","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"toBundle()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes","l":"toBundle()"},{"p":"com.google.android.exoplayer2.device","c":"DeviceInfo","l":"toBundle()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"toBundle()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"toBundle()"},{"p":"com.google.android.exoplayer2.video","c":"VideoSize","l":"toBundle()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"toByteArray(InputStream)","url":"toByteArray(java.io.InputStream)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"MediaParserUtil","l":"toCaptionsMediaFormat(Format)","url":"toCaptionsMediaFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"toHexString(byte[])"},{"p":"com.google.android.exoplayer2","c":"SeekParameters","l":"toleranceAfterUs"},{"p":"com.google.android.exoplayer2","c":"SeekParameters","l":"toleranceBeforeUs"},{"p":"com.google.android.exoplayer2","c":"Format","l":"toLogString(Format)","url":"toLogString(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"toLong(int, int)","url":"toLong(int,int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"toMediaItem()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"DefaultMediaItemConverter","l":"toMediaItem(MediaQueueItem)","url":"toMediaItem(com.google.android.gms.cast.MediaQueueItem)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"MediaItemConverter","l":"toMediaItem(MediaQueueItem)","url":"toMediaItem(com.google.android.gms.cast.MediaQueueItem)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"DefaultMediaItemConverter","l":"toMediaQueueItem(MediaItem)","url":"toMediaQueueItem(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"MediaItemConverter","l":"toMediaQueueItem(MediaItem)","url":"toMediaQueueItem(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"toString()"},{"p":"com.google.android.exoplayer2","c":"PlaybackParameters","l":"toString()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioCapabilities","l":"toString()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor.AudioFormat","l":"toString()"},{"p":"com.google.android.exoplayer2.extractor","c":"ChunkIndex","l":"toString()"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap.SeekPoints","l":"toString()"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekPoint","l":"toString()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","c":"AppInfoTable","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"VorbisComment","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyInfo","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ApicFrame","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"CommentFrame","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"GeobFrame","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"Id3Frame","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"InternalFrame","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"PrivFrame","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"TextInformationFrame","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"UrlLinkFrame","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MdtaMetadataEntry","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MotionPhotoMetadata","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData.Segment","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SmtaMetadataEntry","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceCommand","l":"toString()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"toString()"},{"p":"com.google.android.exoplayer2.offline","c":"StreamKey","l":"toString()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"toString()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"RangedUri","l":"toString()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"UtcTimingElement","l":"toString()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry","l":"toString()"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"toString()"},{"p":"com.google.android.exoplayer2.testutil","c":"Dumper","l":"toString()"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts.SimulationConfig","l":"toString()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"toString()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheSpan","l":"toString()"},{"p":"com.google.android.exoplayer2.video","c":"ColorInfo","l":"toString()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalAudioFormatBitrateTimeProduct"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalAudioFormatTimeMs"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalAudioUnderruns"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection.AdaptationCheckpoint","l":"totalBandwidth"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalBandwidthBytes"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalBandwidthTimeMs"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"totalBufferedDurationMs"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalDroppedFrames"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalInitialAudioFormatBitrate"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalInitialVideoFormatBitrate"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalInitialVideoFormatHeight"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalPauseBufferCount"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalPauseCount"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalRebufferCount"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"totalSamples"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalSeekCount"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"totalTrackCount"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalValidJoinTimeMs"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalVideoFormatBitrateTimeMs"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalVideoFormatBitrateTimeProduct"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalVideoFormatHeightTimeMs"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalVideoFormatHeightTimeProduct"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"totalVideoFrameProcessingOffsetUs"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"toUnsignedLong(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayerLibraryInfo","l":"TRACE_ENABLED"},{"p":"com.google.android.exoplayer2","c":"C","l":"TRACK_TYPE_AUDIO"},{"p":"com.google.android.exoplayer2","c":"C","l":"TRACK_TYPE_CAMERA_MOTION"},{"p":"com.google.android.exoplayer2","c":"C","l":"TRACK_TYPE_CUSTOM_BASE"},{"p":"com.google.android.exoplayer2","c":"C","l":"TRACK_TYPE_DEFAULT"},{"p":"com.google.android.exoplayer2","c":"C","l":"TRACK_TYPE_IMAGE"},{"p":"com.google.android.exoplayer2","c":"C","l":"TRACK_TYPE_METADATA"},{"p":"com.google.android.exoplayer2","c":"C","l":"TRACK_TYPE_NONE"},{"p":"com.google.android.exoplayer2","c":"C","l":"TRACK_TYPE_TEXT"},{"p":"com.google.android.exoplayer2","c":"C","l":"TRACK_TYPE_UNKNOWN"},{"p":"com.google.android.exoplayer2","c":"C","l":"TRACK_TYPE_VIDEO"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"Track(int, int, long, long, long, Format, int, TrackEncryptionBox[], int, long[], long[])","url":"%3Cinit%3E(int,int,long,long,long,com.google.android.exoplayer2.Format,int,com.google.android.exoplayer2.extractor.mp4.TrackEncryptionBox[],int,long[],long[])"},{"p":"com.google.android.exoplayer2.extractor","c":"DummyExtractorOutput","l":"track(int, int)","url":"track(int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorOutput","l":"track(int, int)","url":"track(int,int)"},{"p":"com.google.android.exoplayer2.extractor.jpeg","c":"StartOffsetExtractorOutput","l":"track(int, int)","url":"track(int,int)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunkOutput","l":"track(int, int)","url":"track(int,int)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BundledChunkExtractor","l":"track(int, int)","url":"track(int,int)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkExtractor.TrackOutputProvider","l":"track(int, int)","url":"track(int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorOutput","l":"track(int, int)","url":"track(int,int)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"TrackEncryptionBox","l":"TrackEncryptionBox(boolean, String, int, byte[], int, int, byte[])","url":"%3Cinit%3E(boolean,java.lang.String,int,byte[],int,int,byte[])"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.ProtectionElement","l":"trackEncryptionBoxes"},{"p":"com.google.android.exoplayer2.source","c":"MediaLoadData","l":"trackFormat"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"trackFormat"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroup","l":"TrackGroup(Format...)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format...)"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroupArray","l":"TrackGroupArray(TrackGroup...)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroup...)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.TrackIdGenerator","l":"TrackIdGenerator(int, int, int)","url":"%3Cinit%3E(int,int,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.TrackIdGenerator","l":"TrackIdGenerator(int, int)","url":"%3Cinit%3E(int,int)"},{"p":"com.google.android.exoplayer2.offline","c":"StreamKey","l":"trackIndex"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"trackNumber"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorOutput","l":"trackOutputs"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"tracks"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.SelectionOverride","l":"tracks"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection.Definition","l":"tracks"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionArray","l":"TrackSelectionArray(TrackSelection...)","url":"%3Cinit%3E(com.google.android.exoplayer2.trackselection.TrackSelection...)"},{"p":"com.google.android.exoplayer2.source","c":"MediaLoadData","l":"trackSelectionData"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"trackSelectionData"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder","l":"TrackSelectionDialogBuilder(Context, CharSequence, DefaultTrackSelector, int)","url":"%3Cinit%3E(android.content.Context,java.lang.CharSequence,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,int)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder","l":"TrackSelectionDialogBuilder(Context, CharSequence, MappingTrackSelector.MappedTrackInfo, int, TrackSelectionDialogBuilder.DialogCallback)","url":"%3Cinit%3E(android.content.Context,java.lang.CharSequence,com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo,int,com.google.android.exoplayer2.ui.TrackSelectionDialogBuilder.DialogCallback)"},{"p":"com.google.android.exoplayer2.source","c":"MediaLoadData","l":"trackSelectionReason"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"trackSelectionReason"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionView","l":"TrackSelectionView(Context, AttributeSet, int)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet,int)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionView","l":"TrackSelectionView(Context, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionView","l":"TrackSelectionView(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelector","l":"TrackSelector()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectorResult","l":"TrackSelectorResult(RendererConfiguration[], ExoTrackSelection[], Object)","url":"%3Cinit%3E(com.google.android.exoplayer2.RendererConfiguration[],com.google.android.exoplayer2.trackselection.ExoTrackSelection[],java.lang.Object)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorOutput","l":"tracksEnded"},{"p":"com.google.android.exoplayer2.source","c":"MediaLoadData","l":"trackType"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"trailingParts"},{"p":"com.google.android.exoplayer2.upstream","c":"BaseDataSource","l":"transferEnded()"},{"p":"com.google.android.exoplayer2.upstream","c":"BaseDataSource","l":"transferInitializing(DataSpec)","url":"transferInitializing(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"transferListenerCallbacks()"},{"p":"com.google.android.exoplayer2.upstream","c":"BaseDataSource","l":"transferStarted(DataSpec)","url":"transferStarted(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"TRANSFORMATION_CEA608_CDAT"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"TRANSFORMATION_NONE"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.Mode","l":"transformType"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"triggerEvent(Predicate, int, int, byte[])","url":"triggerEvent(com.google.common.base.Predicate,int,int,byte[])"},{"p":"com.google.android.exoplayer2.upstream","c":"Allocator","l":"trim()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultAllocator","l":"trim()"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"TRUEHD_MAX_RATE_BYTES_PER_SECOND"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"TRUEHD_RECHUNK_SAMPLE_COUNT"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"TRUEHD_SYNCFRAME_PREFIX_LENGTH"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"truncateAscii(CharSequence, int)","url":"truncateAscii(java.lang.CharSequence,int)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"TS"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_PACKET_SIZE"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_AAC_ADTS"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_AAC_LATM"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_AC3"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_AC4"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_AIT"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_DTS"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_DVBSUBS"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_E_AC3"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_H262"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_H263"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_H264"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_H265"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_HDMV_DTS"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_ID3"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_MPA"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_MPA_LSF"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_SPLICE_INFO"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_SYNC_BYTE"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TsExtractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TsExtractor(int, int, int)","url":"%3Cinit%3E(int,int,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TsExtractor(int, TimestampAdjuster, TsPayloadReader.Factory, int)","url":"%3Cinit%3E(int,com.google.android.exoplayer2.util.TimestampAdjuster,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.Factory,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TsExtractor(int, TimestampAdjuster, TsPayloadReader.Factory)","url":"%3Cinit%3E(int,com.google.android.exoplayer2.util.TimestampAdjuster,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.Factory)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TsExtractor(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.text.ttml","c":"TtmlDecoder","l":"TtmlDecoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"RendererConfiguration","l":"tunneling"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"tunneling"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"TUNNELING_NOT_SUPPORTED"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"TUNNELING_SUPPORT_MASK"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"TUNNELING_SUPPORTED"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"tunnelingEnabled"},{"p":"com.google.android.exoplayer2.text.tx3g","c":"Tx3gDecoder","l":"Tx3gDecoder(List)","url":"%3Cinit%3E(java.util.List)"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"type"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"type"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.DvbSubtitleInfo","l":"type"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource.AdLoadException","l":"type"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"type"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"AdaptationSet","l":"type"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"type"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.SelectionOverride","l":"type"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection.Definition","l":"type"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.HttpDataSourceException","l":"type"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"type"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource.AdLoadException","l":"TYPE_AD"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource.AdLoadException","l":"TYPE_AD_GROUP"},{"p":"com.google.android.exoplayer2.audio","c":"WavUtil","l":"TYPE_ALAW"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource.AdLoadException","l":"TYPE_ALL_ADS"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.HttpDataSourceException","l":"TYPE_CLOSE"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelection","l":"TYPE_CUSTOM_BASE"},{"p":"com.google.android.exoplayer2","c":"C","l":"TYPE_DASH"},{"p":"com.google.android.exoplayer2.audio","c":"WavUtil","l":"TYPE_FLOAT"},{"p":"com.google.android.exoplayer2","c":"C","l":"TYPE_HLS"},{"p":"com.google.android.exoplayer2.audio","c":"WavUtil","l":"TYPE_IMA_ADPCM"},{"p":"com.google.android.exoplayer2.audio","c":"WavUtil","l":"TYPE_MLAW"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.TimestampSearchResult","l":"TYPE_NO_TIMESTAMP"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.HttpDataSourceException","l":"TYPE_OPEN"},{"p":"com.google.android.exoplayer2","c":"C","l":"TYPE_OTHER"},{"p":"com.google.android.exoplayer2.audio","c":"WavUtil","l":"TYPE_PCM"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.TimestampSearchResult","l":"TYPE_POSITION_OVERESTIMATED"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.TimestampSearchResult","l":"TYPE_POSITION_UNDERESTIMATED"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.HttpDataSourceException","l":"TYPE_READ"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"TYPE_REMOTE"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"TYPE_RENDERER"},{"p":"com.google.android.exoplayer2","c":"C","l":"TYPE_RTSP"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"TYPE_SOURCE"},{"p":"com.google.android.exoplayer2","c":"C","l":"TYPE_SS"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.TimestampSearchResult","l":"TYPE_TARGET_TIMESTAMP_FOUND"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"TYPE_UNEXPECTED"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource.AdLoadException","l":"TYPE_UNEXPECTED"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"TYPE_UNSET"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelection","l":"TYPE_UNSET"},{"p":"com.google.android.exoplayer2.audio","c":"WavUtil","l":"TYPE_WAVE_FORMAT_EXTENSIBLE"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"typeface"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MdtaMetadataEntry","l":"typeIndicator"},{"p":"com.google.android.exoplayer2.upstream","c":"UdpDataSource","l":"UDP_PORT_UNSET"},{"p":"com.google.android.exoplayer2.upstream","c":"UdpDataSource","l":"UdpDataSource()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"UdpDataSource","l":"UdpDataSource(int, int)","url":"%3Cinit%3E(int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"UdpDataSource","l":"UdpDataSource(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"UdpDataSource.UdpDataSourceException","l":"UdpDataSourceException(IOException)","url":"%3Cinit%3E(java.io.IOException)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"uid"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"uid"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"UID_UNSET"},{"p":"com.google.android.exoplayer2.video","c":"VideoSize","l":"unappliedRotationDegrees"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"unboundedDataSpec_readUntilEnd()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"unboundedDataSpecWithGzipFlag_readUntilEnd()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"unboundedReadsAreIndefinite()"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.TimestampSearchResult","l":"underestimatedResult(long, long)","url":"underestimatedResult(long,long)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener.EventDispatcher","l":"underrun(int, long, long)","url":"underrun(int,long,long)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"unescapeFileName(String)","url":"unescapeFileName(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil","l":"unescapeStream(byte[], int)","url":"unescapeStream(byte[],int)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.UnexpectedDiscontinuityException","l":"UnexpectedDiscontinuityException(long, long)","url":"%3Cinit%3E(long,long)"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader.UnexpectedLoaderException","l":"UnexpectedLoaderException(Throwable)","url":"%3Cinit%3E(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor.UnhandledAudioFormatException","l":"UnhandledAudioFormatException(AudioProcessor.AudioFormat)","url":"%3Cinit%3E(com.google.android.exoplayer2.audio.AudioProcessor.AudioFormat)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil.Uniform","l":"Uniform(int, int)","url":"%3Cinit%3E(int,int)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"uniqueProgramId"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.Event","l":"uniqueProgramId"},{"p":"com.google.android.exoplayer2.device","c":"DeviceInfo","l":"UNKNOWN"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"UNKNOWN"},{"p":"com.google.android.exoplayer2.video","c":"VideoSize","l":"UNKNOWN"},{"p":"com.google.android.exoplayer2.source","c":"UnrecognizedInputFormatException","l":"UnrecognizedInputFormatException(String, Uri)","url":"%3Cinit%3E(java.lang.String,android.net.Uri)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioCapabilitiesReceiver","l":"unregister()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"unregisterCustomCommandReceiver(MediaSessionConnector.CommandReceiver)","url":"unregisterCustomCommandReceiver(com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.CommandReceiver)"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap.Unseekable","l":"Unseekable(long, long)","url":"%3Cinit%3E(long,long)"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap.Unseekable","l":"Unseekable(long)","url":"%3Cinit%3E(long)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.LiveConfiguration","l":"UNSET"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest","l":"UNSET_LOOKAHEAD"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.UnshuffledShuffleOrder","l":"UnshuffledShuffleOrder(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"UNSPECIFIED"},{"p":"com.google.android.exoplayer2.drm","c":"UnsupportedDrmException","l":"UnsupportedDrmException(int, Exception)","url":"%3Cinit%3E(int,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.drm","c":"UnsupportedDrmException","l":"UnsupportedDrmException(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.drm","c":"UnsupportedMediaCrypto","l":"UnsupportedMediaCrypto()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest.UnsupportedRequestException","l":"UnsupportedRequestException()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesFlushingCipher","l":"update(byte[], int, int, byte[], int)","url":"update(byte[],int,int,byte[],int)"},{"p":"com.google.android.exoplayer2.util","c":"DebugTextViewHelper","l":"updateAndPost()"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"updateClipping(long, long)","url":"updateClipping(long,long)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"updateCodecOperatingRate()"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"updateDroppedBufferCounters(int)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"updateDroppedBufferCounters(int)"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesFlushingCipher","l":"updateInPlace(byte[], int, int)","url":"updateInPlace(byte[],int,int)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashChunkSource","l":"updateManifest(DashManifest, int)","url":"updateManifest(com.google.android.exoplayer2.source.dash.manifest.DashManifest,int)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"updateManifest(DashManifest, int)","url":"updateManifest(com.google.android.exoplayer2.source.dash.manifest.DashManifest,int)"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler","l":"updateManifest(DashManifest)","url":"updateManifest(com.google.android.exoplayer2.source.dash.manifest.DashManifest)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource","l":"updateManifest(SsManifest)","url":"updateManifest(com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsChunkSource","l":"updateManifest(SsManifest)","url":"updateManifest(com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"updateMediaPeriodQueueInfo(List, MediaSource.MediaPeriodId)","url":"updateMediaPeriodQueueInfo(java.util.List,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.ext.gvr","c":"GvrAudioProcessor","l":"updateOrientation(float, float, float, float)","url":"updateOrientation(float,float,float,float)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"updateOutputFormatForTime(long)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionUtil","l":"updateParametersWithOverride(DefaultTrackSelector.Parameters, int, TrackGroupArray, boolean, DefaultTrackSelector.SelectionOverride)","url":"updateParametersWithOverride(com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters,int,com.google.android.exoplayer2.source.TrackGroupArray,boolean,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"updatePlaylistMetadata(MediaMetadata)","url":"updatePlaylistMetadata(androidx.media2.common.MediaMetadata)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"updateSelectedTrack(long, long, long, List, MediaChunkIterator[])","url":"updateSelectedTrack(long,long,long,java.util.List,com.google.android.exoplayer2.source.chunk.MediaChunkIterator[])"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"updateSelectedTrack(long, long, long, List, MediaChunkIterator[])","url":"updateSelectedTrack(long,long,long,java.util.List,com.google.android.exoplayer2.source.chunk.MediaChunkIterator[])"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"updateSelectedTrack(long, long, long, List, MediaChunkIterator[])","url":"updateSelectedTrack(long,long,long,java.util.List,com.google.android.exoplayer2.source.chunk.MediaChunkIterator[])"},{"p":"com.google.android.exoplayer2.trackselection","c":"FixedTrackSelection","l":"updateSelectedTrack(long, long, long, List, MediaChunkIterator[])","url":"updateSelectedTrack(long,long,long,java.util.List,com.google.android.exoplayer2.source.chunk.MediaChunkIterator[])"},{"p":"com.google.android.exoplayer2.trackselection","c":"RandomTrackSelection","l":"updateSelectedTrack(long, long, long, List, MediaChunkIterator[])","url":"updateSelectedTrack(long,long,long,java.util.List,com.google.android.exoplayer2.source.chunk.MediaChunkIterator[])"},{"p":"com.google.android.exoplayer2.analytics","c":"DefaultPlaybackSessionManager","l":"updateSessions(AnalyticsListener.EventTime)","url":"updateSessions(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackSessionManager","l":"updateSessions(AnalyticsListener.EventTime)","url":"updateSessions(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.analytics","c":"DefaultPlaybackSessionManager","l":"updateSessionsWithDiscontinuity(AnalyticsListener.EventTime, int)","url":"updateSessionsWithDiscontinuity(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackSessionManager","l":"updateSessionsWithDiscontinuity(AnalyticsListener.EventTime, int)","url":"updateSessionsWithDiscontinuity(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"DefaultPlaybackSessionManager","l":"updateSessionsWithTimelineChange(AnalyticsListener.EventTime)","url":"updateSessionsWithTimelineChange(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackSessionManager","l":"updateSessionsWithTimelineChange(AnalyticsListener.EventTime)","url":"updateSessionsWithTimelineChange(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"updateTimeMs"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashChunkSource","l":"updateTrackSelection(ExoTrackSelection)","url":"updateTrackSelection(com.google.android.exoplayer2.trackselection.ExoTrackSelection)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"updateTrackSelection(ExoTrackSelection)","url":"updateTrackSelection(com.google.android.exoplayer2.trackselection.ExoTrackSelection)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource","l":"updateTrackSelection(ExoTrackSelection)","url":"updateTrackSelection(com.google.android.exoplayer2.trackselection.ExoTrackSelection)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsChunkSource","l":"updateTrackSelection(ExoTrackSelection)","url":"updateTrackSelection(com.google.android.exoplayer2.trackselection.ExoTrackSelection)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"updateVideoFrameProcessingOffsetCounters(long)"},{"p":"com.google.android.exoplayer2.offline","c":"ActionFileUpgradeUtil","l":"upgradeAndDelete(File, ActionFileUpgradeUtil.DownloadIdProvider, DefaultDownloadIndex, boolean, boolean)","url":"upgradeAndDelete(java.io.File,com.google.android.exoplayer2.offline.ActionFileUpgradeUtil.DownloadIdProvider,com.google.android.exoplayer2.offline.DefaultDownloadIndex,boolean,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"upstreamDiscarded(int, long, long)","url":"upstreamDiscarded(int,long,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"upstreamDiscarded(MediaLoadData)","url":"upstreamDiscarded(com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock","l":"uptimeMillis()"},{"p":"com.google.android.exoplayer2.util","c":"Clock","l":"uptimeMillis()"},{"p":"com.google.android.exoplayer2.util","c":"SystemClock","l":"uptimeMillis()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.PlaybackProperties","l":"uri"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Subtitle","l":"uri"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"uri"},{"p":"com.google.android.exoplayer2.source","c":"LoadEventInfo","l":"uri"},{"p":"com.google.android.exoplayer2.source","c":"UnrecognizedInputFormatException","l":"uri"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.SingleSegmentRepresentation","l":"uri"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData","l":"uri"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"uri"},{"p":"com.google.android.exoplayer2.drm","c":"MediaDrmCallbackException","l":"uriAfterRedirects"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"uriPositionOffset"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"uris"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","c":"AppInfoTable","l":"url"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"url"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyInfo","l":"url"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"UrlLinkFrame","l":"url"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Rendition","l":"url"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Variant","l":"url"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.SegmentBase","l":"url"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker.PlaylistResetException","l":"url"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker.PlaylistStuckException","l":"url"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"UrlLinkFrame","l":"UrlLinkFrame(String, String, String)","url":"%3Cinit%3E(java.lang.String,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes","l":"usage"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_ALARM"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_ASSISTANCE_ACCESSIBILITY"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_ASSISTANCE_SONIFICATION"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_ASSISTANT"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_GAME"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_MEDIA"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_NOTIFICATION"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_NOTIFICATION_COMMUNICATION_DELAYED"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_NOTIFICATION_COMMUNICATION_INSTANT"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_NOTIFICATION_COMMUNICATION_REQUEST"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_NOTIFICATION_EVENT"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_NOTIFICATION_RINGTONE"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_UNKNOWN"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_VOICE_COMMUNICATION"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_VOICE_COMMUNICATION_SIGNALLING"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"USE_TRACK_COLOR_SETTINGS"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts.RequestSet","l":"useBoundedDataSpecFor(String)","url":"useBoundedDataSpecFor(java.lang.String)"},{"p":"com.google.android.exoplayer2.extractor","c":"CeaUtil","l":"USER_DATA_IDENTIFIER_GA94"},{"p":"com.google.android.exoplayer2.extractor","c":"CeaUtil","l":"USER_DATA_TYPE_CODE_MPEG_CC"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"userRating"},{"p":"com.google.android.exoplayer2","c":"C","l":"usToMs(long)"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"usToNonWrappedPts(long)"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"usToWrappedPts(long)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.ComponentSplice","l":"utcSpliceTime"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.Event","l":"utcSpliceTime"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"utcTiming"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"UtcTimingElement","l":"UtcTimingElement(String, String)","url":"%3Cinit%3E(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"C","l":"UTF16_NAME"},{"p":"com.google.android.exoplayer2","c":"C","l":"UTF16LE_NAME"},{"p":"com.google.android.exoplayer2","c":"C","l":"UTF8_NAME"},{"p":"com.google.android.exoplayer2","c":"MediaItem.DrmConfiguration","l":"uuid"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"uuid"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaCrypto","l":"uuid"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.ProtectionElement","l":"uuid"},{"p":"com.google.android.exoplayer2","c":"C","l":"UUID_NIL"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"VALID_PROVISION_RESPONSE"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttParserUtil","l":"validateWebvttHeaderLine(ParsableByteArray)","url":"validateWebvttHeaderLine(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"validJoinTimeCount"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"value"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"VorbisComment","l":"value"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"TextInformationFrame","l":"value"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MdtaMetadataEntry","l":"value"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Descriptor","l":"value"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"EventStream","l":"value"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"UtcTimingElement","l":"value"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"variableDefinitions"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Variant","l":"Variant(Uri, Format, String, String, String, String)","url":"%3Cinit%3E(android.net.Uri,com.google.android.exoplayer2.Format,java.lang.String,java.lang.String,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry.VariantInfo","l":"VariantInfo(int, int, String, String, String, String)","url":"%3Cinit%3E(int,int,java.lang.String,java.lang.String,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry","l":"variantInfos"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"variants"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.CommentHeader","l":"vendor"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"vendor"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil","l":"verifyVorbisHeaderCapturePattern(int, ParsableByteArray, boolean)","url":"verifyVorbisHeaderCapturePattern(int,com.google.android.exoplayer2.util.ParsableByteArray,boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil.Header","l":"version"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.VorbisIdHeader","l":"version"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"version"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"version"},{"p":"com.google.android.exoplayer2","c":"ExoPlayerLibraryInfo","l":"VERSION"},{"p":"com.google.android.exoplayer2","c":"ExoPlayerLibraryInfo","l":"VERSION_INT"},{"p":"com.google.android.exoplayer2","c":"ExoPlayerLibraryInfo","l":"VERSION_SLASHY"},{"p":"com.google.android.exoplayer2.database","c":"VersionTable","l":"VERSION_UNSET"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"VERTICAL_TYPE_LR"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"VERTICAL_TYPE_RL"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"verticalType"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_AV1"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_DIVX"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_DOLBY_VISION"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_FLV"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"VIDEO_FORMAT"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_H263"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_H264"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_H265"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_MATROSKA"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_MP2T"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_MP4"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_MP4V"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_MPEG"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_MPEG2"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_OGG"},{"p":"com.google.android.exoplayer2","c":"C","l":"VIDEO_OUTPUT_MODE_NONE"},{"p":"com.google.android.exoplayer2","c":"C","l":"VIDEO_OUTPUT_MODE_SURFACE_YUV"},{"p":"com.google.android.exoplayer2","c":"C","l":"VIDEO_OUTPUT_MODE_YUV"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_PS"},{"p":"com.google.android.exoplayer2","c":"C","l":"VIDEO_SCALING_MODE_DEFAULT"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"VIDEO_SCALING_MODE_DEFAULT"},{"p":"com.google.android.exoplayer2","c":"C","l":"VIDEO_SCALING_MODE_SCALE_TO_FIT"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"VIDEO_SCALING_MODE_SCALE_TO_FIT"},{"p":"com.google.android.exoplayer2","c":"C","l":"VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"VIDEO_STREAM"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"VIDEO_STREAM_MASK"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_UNKNOWN"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_VC1"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_VP8"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_VP9"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_WEBM"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener.EventDispatcher","l":"videoCodecError(Exception)","url":"videoCodecError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderGLSurfaceView","l":"VideoDecoderGLSurfaceView(Context, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderGLSurfaceView","l":"VideoDecoderGLSurfaceView(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderInputBuffer","l":"VideoDecoderInputBuffer(int, int)","url":"%3Cinit%3E(int,int)"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderInputBuffer","l":"VideoDecoderInputBuffer(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"VideoDecoderOutputBuffer(OutputBuffer.Owner)","url":"%3Cinit%3E(com.google.android.exoplayer2.decoder.OutputBuffer.Owner)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"videoFormatHistory"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"videoFrameProcessingOffsetCount"},{"p":"com.google.android.exoplayer2.video","c":"VideoFrameReleaseHelper","l":"VideoFrameReleaseHelper(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry.VariantInfo","l":"videoGroupId"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Variant","l":"videoGroupId"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"videos"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MotionPhotoMetadata","l":"videoSize"},{"p":"com.google.android.exoplayer2.video","c":"VideoSize","l":"VideoSize(int, int, int, float)","url":"%3Cinit%3E(int,int,int,float)"},{"p":"com.google.android.exoplayer2.video","c":"VideoSize","l":"VideoSize(int, int)","url":"%3Cinit%3E(int,int)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener.EventDispatcher","l":"videoSizeChanged(VideoSize)","url":"videoSizeChanged(com.google.android.exoplayer2.video.VideoSize)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MotionPhotoMetadata","l":"videoStartPosition"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.VideoTrackScore","l":"VideoTrackScore(Format, DefaultTrackSelector.Parameters, int, boolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters,int,boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"AdOverlayInfo","l":"view"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"VIEW_TYPE_CANVAS"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"VIEW_TYPE_WEB"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"viewportHeight"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"viewportOrientationMayChange"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"viewportWidth"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisBitArray","l":"VorbisBitArray(byte[])","url":"%3Cinit%3E(byte[])"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"VorbisComment","l":"VorbisComment(String, String)","url":"%3Cinit%3E(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.VorbisIdHeader","l":"VorbisIdHeader(int, int, int, int, int, int, int, int, boolean, byte[])","url":"%3Cinit%3E(int,int,int,int,int,int,int,int,boolean,byte[])"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxDecoder","l":"VpxDecoder(int, int, int, ExoMediaCrypto, int)","url":"%3Cinit%3E(int,int,int,com.google.android.exoplayer2.drm.ExoMediaCrypto,int)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxLibrary","l":"vpxIsSecureDecodeSupported()"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxOutputBuffer","l":"VpxOutputBuffer(OutputBuffer.Owner)","url":"%3Cinit%3E(com.google.android.exoplayer2.decoder.OutputBuffer.Owner)"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"w(String, String, Throwable)","url":"w(java.lang.String,java.lang.String,java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"w(String, String)","url":"w(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"waitForIsLoading(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForIsLoading","l":"WaitForIsLoading(String, boolean)","url":"%3Cinit%3E(java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"waitForMessage(ActionSchedule.PlayerTarget)","url":"waitForMessage(com.google.android.exoplayer2.testutil.ActionSchedule.PlayerTarget)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForMessage","l":"WaitForMessage(String, ActionSchedule.PlayerTarget)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.testutil.ActionSchedule.PlayerTarget)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"waitForPendingPlayerCommands()"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForPendingPlayerCommands","l":"WaitForPendingPlayerCommands(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"waitForPlaybackState(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForPlaybackState","l":"WaitForPlaybackState(String, int)","url":"%3Cinit%3E(java.lang.String,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"waitForPlayWhenReady(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForPlayWhenReady","l":"WaitForPlayWhenReady(String, boolean)","url":"%3Cinit%3E(java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"waitForPositionDiscontinuity()"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForPositionDiscontinuity","l":"WaitForPositionDiscontinuity(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"waitForTimelineChanged()"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForTimelineChanged","l":"WaitForTimelineChanged(String, Timeline, int)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.Timeline,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForTimelineChanged","l":"WaitForTimelineChanged(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"waitForTimelineChanged(Timeline, int)","url":"waitForTimelineChanged(com.google.android.exoplayer2.Timeline,int)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"waitingForKeys"},{"p":"com.google.android.exoplayer2","c":"C","l":"WAKE_MODE_LOCAL"},{"p":"com.google.android.exoplayer2","c":"C","l":"WAKE_MODE_NETWORK"},{"p":"com.google.android.exoplayer2","c":"C","l":"WAKE_MODE_NONE"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecUtil","l":"warmDecoderInfoCache(String, boolean, boolean)","url":"warmDecoderInfoCache(java.lang.String,boolean,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"WAV"},{"p":"com.google.android.exoplayer2.audio","c":"WavUtil","l":"WAVE_FOURCC"},{"p":"com.google.android.exoplayer2.extractor.wav","c":"WavExtractor","l":"WavExtractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.audio","c":"TeeAudioProcessor.WavFileAudioBufferSink","l":"WavFileAudioBufferSink(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"WEBVTT"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"WebvttCssStyle()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCueInfo","l":"WebvttCueInfo(Cue, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.text.Cue,long,long)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCueParser","l":"WebvttCueParser()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttDecoder","l":"WebvttDecoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.hls","c":"WebvttExtractor","l":"WebvttExtractor(String, TimestampAdjuster)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.util.TimestampAdjuster)"},{"p":"com.google.android.exoplayer2","c":"C","l":"WIDEVINE_UUID"},{"p":"com.google.android.exoplayer2","c":"Format","l":"width"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"width"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"width"},{"p":"com.google.android.exoplayer2.video","c":"AvcConfig","l":"width"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer.CodecMaxValues","l":"width"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"width"},{"p":"com.google.android.exoplayer2.video","c":"VideoSize","l":"width"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"window"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"Window()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"windowColor"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"windowColor"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"windowColorSet"},{"p":"com.google.android.exoplayer2","c":"IllegalSeekPositionException","l":"windowIndex"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"windowIndex"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"windowIndex"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"windowIndex"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener.EventDispatcher","l":"windowIndex"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"windowIndex"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"windowOffsetInFirstPeriodUs"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"windowSequenceNumber"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"windowStartTimeMs"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.Mode","l":"windowType"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"windowUid"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject.AbsoluteSized","l":"withAbsoluteSize(int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"withAdCount(int, int)","url":"withAdCount(int,int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"withAdCount(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"withAdditionalHeaders(Map)","url":"withAdditionalHeaders(java.util.Map)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"withAdDurationsUs(long[])"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"withAdDurationsUs(long[][])"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"withAdLoadError(int, int)","url":"withAdLoadError(int,int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"withAdResumePositionUs(long)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"withAdState(int, int)","url":"withAdState(int,int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"withAdUri(int, int, Uri)","url":"withAdUri(int,int,android.net.Uri)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"withAdUri(Uri, int)","url":"withAdUri(android.net.Uri,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject.Aligned","l":"withAlignment(Layout.Alignment)","url":"withAlignment(android.text.Layout.Alignment)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"withAllAdsSkipped()"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject.Colored","l":"withColor(int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"withContentDurationUs(long)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject.Typefaced","l":"withFamily(String)","url":"withFamily(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject.WithSpanFlags","l":"withFlags(int)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"withManifestFormatInfo(Format)","url":"withManifestFormatInfo(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject.EmphasizedText","l":"withMarkAndPosition(int, int, int)","url":"withMarkAndPosition(int,int,int)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"withParameters(int, MediaSource.MediaPeriodId, long)","url":"withParameters(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,long)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener.EventDispatcher","l":"withParameters(int, MediaSource.MediaPeriodId)","url":"withParameters(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"withPlayedAd(int, int)","url":"withPlayedAd(int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"withRequestHeaders(Map)","url":"withRequestHeaders(java.util.Map)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject.RelativeSized","l":"withSizeChange(float)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"withSkippedAd(int, int)","url":"withSkippedAd(int,int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"withSkippedAdGroup(int)"},{"p":"com.google.android.exoplayer2","c":"PlaybackParameters","l":"withSpeed(float)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject.RubyText","l":"withTextAndPosition(String, int)","url":"withTextAndPosition(java.lang.String,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"withUri(Uri)","url":"withUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaCrypto","l":"WORKAROUND_DEVICE_NEEDS_KEYS_TO_CONFIGURE_CODEC"},{"p":"com.google.android.exoplayer2.ext.workmanager","c":"WorkManagerScheduler","l":"WorkManagerScheduler(Context, String)","url":"%3Cinit%3E(android.content.Context,java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.workmanager","c":"WorkManagerScheduler","l":"WorkManagerScheduler(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"FailOnCloseDataSink","l":"write(byte[], int, int)","url":"write(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"ByteArrayDataSink","l":"write(byte[], int, int)","url":"write(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSink","l":"write(byte[], int, int)","url":"write(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink","l":"write(byte[], int, int)","url":"write(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesCipherDataSink","l":"write(byte[], int, int)","url":"write(byte[],int,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"writeBoolean(Parcel, boolean)","url":"writeBoolean(android.os.Parcel,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"writeData(long)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.WriteException","l":"WriteException(int, Format, boolean)","url":"%3Cinit%3E(int,com.google.android.exoplayer2.Format,boolean)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"writeToBuffer(byte[], int, int)","url":"writeToBuffer(byte[],int,int)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","c":"AppInfoTable","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"VorbisComment","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyInfo","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ApicFrame","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"BinaryFrame","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterTocFrame","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"CommentFrame","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"GeobFrame","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"InternalFrame","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"MlltFrame","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"PrivFrame","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"TextInformationFrame","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"UrlLinkFrame","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MdtaMetadataEntry","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MotionPhotoMetadata","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData.Segment","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SmtaMetadataEntry","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"PrivateCommand","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceNullCommand","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"TimeSignalCommand","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.offline","c":"StreamKey","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroup","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroupArray","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry.VariantInfo","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.SelectionOverride","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.video","c":"ColorInfo","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand.ComponentSplice","l":"writeToParcel(Parcel)","url":"writeToParcel(android.os.Parcel)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"year"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"yuvPlanes"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"yuvStrides"}] \ No newline at end of file +memberSearchIndex = [{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AAC_ELD_MAX_RATE_BYTES_PER_SECOND"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AAC_HE_AUDIO_SAMPLE_COUNT"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AAC_HE_V1_MAX_RATE_BYTES_PER_SECOND"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AAC_HE_V2_MAX_RATE_BYTES_PER_SECOND"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AAC_LC_AUDIO_SAMPLE_COUNT"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AAC_LC_MAX_RATE_BYTES_PER_SECOND"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AAC_LD_AUDIO_SAMPLE_COUNT"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AAC_XHE_AUDIO_SAMPLE_COUNT"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AAC_XHE_MAX_RATE_BYTES_PER_SECOND"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"abandonedBeforeReadyCount"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"absoluteStreamPosition"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"AbstractConcatenatedTimeline(boolean, ShuffleOrder)","url":"%3Cinit%3E(boolean,com.google.android.exoplayer2.source.ShuffleOrder)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"AC3"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"AC3_MAX_RATE_BYTES_PER_SECOND"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Extractor","l":"Ac3Extractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Reader","l":"Ac3Reader()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Reader","l":"Ac3Reader(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"AC4"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util","l":"AC40_SYNCWORD"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util","l":"AC41_SYNCWORD"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Extractor","l":"Ac4Extractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Reader","l":"Ac4Reader()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Reader","l":"Ac4Reader(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"Consumer","l":"accept(T)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.AllowedCommandProvider","l":"acceptConnection(MediaSession, MediaSession.ControllerInfo)","url":"acceptConnection(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.DefaultAllowedCommandProvider","l":"acceptConnection(MediaSession, MediaSession.ControllerInfo)","url":"acceptConnection(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"accessibilityChannel"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"AdaptationSet","l":"accessibilityDescriptors"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"acquire()"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"acquire()"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"acquire()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"acquire()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"acquire(DrmSessionEventListener.EventDispatcher)","url":"acquire(com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2.drm","c":"ErrorStateDrmSession","l":"acquire(DrmSessionEventListener.EventDispatcher)","url":"acquire(com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.AppManagedProvider","l":"acquireExoMediaDrm(UUID)","url":"acquireExoMediaDrm(java.util.UUID)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.Provider","l":"acquireExoMediaDrm(UUID)","url":"acquireExoMediaDrm(java.util.UUID)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"acquireSession(Looper, DrmSessionEventListener.EventDispatcher, Format)","url":"acquireSession(android.os.Looper,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionManager","l":"acquireSession(Looper, DrmSessionEventListener.EventDispatcher, Format)","url":"acquireSession(android.os.Looper,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData.Segment","l":"action"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"ACTION_ADD_DOWNLOAD"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"ACTION_FAST_FORWARD"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"ACTION_INIT"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"ACTION_NEXT"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"ACTION_PAUSE"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"ACTION_PAUSE_DOWNLOADS"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"ACTION_PLAY"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"ACTION_PREVIOUS"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"ACTION_REMOVE_ALL_DOWNLOADS"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"ACTION_REMOVE_DOWNLOAD"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"ACTION_RESUME_DOWNLOADS"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"ACTION_REWIND"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"ACTION_SET_REQUIREMENTS"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"ACTION_SET_STOP_REASON"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"ACTION_STOP"},{"p":"com.google.android.exoplayer2.testutil","c":"Action","l":"Action(String, String)","url":"%3Cinit%3E(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.PlaybackPreparer","l":"ACTIONS"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.QueueNavigator","l":"ACTIONS"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.UnexpectedDiscontinuityException","l":"actualPresentationTimeUs"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"AD_STATE_AVAILABLE"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"AD_STATE_ERROR"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"AD_STATE_PLAYED"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"AD_STATE_SKIPPED"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"AD_STATE_UNAVAILABLE"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection.AdaptationCheckpoint","l":"AdaptationCheckpoint(long, long)","url":"%3Cinit%3E(long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"AdaptationSet","l":"AdaptationSet(int, int, List, List, List, List)","url":"%3Cinit%3E(int,int,java.util.List,java.util.List,java.util.List,java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Period","l":"adaptationSets"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"adaptive"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"ADAPTIVE_NOT_SEAMLESS"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"ADAPTIVE_NOT_SUPPORTED"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"ADAPTIVE_SEAMLESS"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"ADAPTIVE_SUPPORT_MASK"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"AdaptiveTrackSelection(TrackGroup, int[], BandwidthMeter)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroup,int[],com.google.android.exoplayer2.upstream.BandwidthMeter)"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"AdaptiveTrackSelection(TrackGroup, int[], int, BandwidthMeter, long, long, long, float, float, List, Clock)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroup,int[],int,com.google.android.exoplayer2.upstream.BandwidthMeter,long,long,long,float,float,java.util.List,com.google.android.exoplayer2.util.Clock)"},{"p":"com.google.android.exoplayer2.testutil","c":"Dumper","l":"add(Dumper.Dumpable)","url":"add(com.google.android.exoplayer2.testutil.Dumper.Dumpable)"},{"p":"com.google.android.exoplayer2.util","c":"CopyOnWriteMultiset","l":"add(E)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor.QueueDataAdapter","l":"add(int, MediaDescriptionCompat)","url":"add(int,android.support.v4.media.MediaDescriptionCompat)"},{"p":"com.google.android.exoplayer2","c":"Player.Commands.Builder","l":"add(int)"},{"p":"com.google.android.exoplayer2.util","c":"FlagSet.Builder","l":"add(int)"},{"p":"com.google.android.exoplayer2.util","c":"IntArrayQueue","l":"add(int)"},{"p":"com.google.android.exoplayer2.util","c":"PriorityTaskManager","l":"add(int)"},{"p":"com.google.android.exoplayer2.util","c":"TimedValueQueue","l":"add(long, V)","url":"add(long,V)"},{"p":"com.google.android.exoplayer2.util","c":"LongArray","l":"add(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"Dumper","l":"add(String, byte[])","url":"add(java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"Dumper","l":"add(String, Object)","url":"add(java.lang.String,java.lang.Object)"},{"p":"com.google.android.exoplayer2.util","c":"ListenerSet","l":"add(T)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsUtil","l":"addAdGroupToAdPlaybackState(AdPlaybackState, long, long, long)","url":"addAdGroupToAdPlaybackState(com.google.android.exoplayer2.source.ads.AdPlaybackState,long,long,long)"},{"p":"com.google.android.exoplayer2.util","c":"FlagSet.Builder","l":"addAll(FlagSet)","url":"addAll(com.google.android.exoplayer2.util.FlagSet)"},{"p":"com.google.android.exoplayer2","c":"Player.Commands.Builder","l":"addAll(int...)"},{"p":"com.google.android.exoplayer2.util","c":"FlagSet.Builder","l":"addAll(int...)"},{"p":"com.google.android.exoplayer2","c":"Player.Commands.Builder","l":"addAll(Player.Commands)","url":"addAll(com.google.android.exoplayer2.Player.Commands)"},{"p":"com.google.android.exoplayer2","c":"Player.Commands.Builder","l":"addAllCommands()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addAnalyticsListener(AnalyticsListener)","url":"addAnalyticsListener(com.google.android.exoplayer2.analytics.AnalyticsListener)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"addAudioLanguagesToSelection(String...)","url":"addAudioLanguagesToSelection(java.lang.String...)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioComponent","l":"addAudioListener(AudioListener)","url":"addAudioListener(com.google.android.exoplayer2.audio.AudioListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addAudioListener(AudioListener)","url":"addAudioListener(com.google.android.exoplayer2.audio.AudioListener)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"addAudioOffloadListener(ExoPlayer.AudioOffloadListener)","url":"addAudioOffloadListener(com.google.android.exoplayer2.ExoPlayer.AudioOffloadListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addAudioOffloadListener(ExoPlayer.AudioOffloadListener)","url":"addAudioOffloadListener(com.google.android.exoplayer2.ExoPlayer.AudioOffloadListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"addAudioOffloadListener(ExoPlayer.AudioOffloadListener)","url":"addAudioOffloadListener(com.google.android.exoplayer2.ExoPlayer.AudioOffloadListener)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.DeviceComponent","l":"addDeviceListener(DeviceListener)","url":"addDeviceListener(com.google.android.exoplayer2.device.DeviceListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addDeviceListener(DeviceListener)","url":"addDeviceListener(com.google.android.exoplayer2.device.DeviceListener)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"addDownload(DownloadRequest, int)","url":"addDownload(com.google.android.exoplayer2.offline.DownloadRequest,int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"addDownload(DownloadRequest)","url":"addDownload(com.google.android.exoplayer2.offline.DownloadRequest)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"addDrmEventListener(Handler, DrmSessionEventListener)","url":"addDrmEventListener(android.os.Handler,com.google.android.exoplayer2.drm.DrmSessionEventListener)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"addDrmEventListener(Handler, DrmSessionEventListener)","url":"addDrmEventListener(android.os.Handler,com.google.android.exoplayer2.drm.DrmSessionEventListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"BandwidthMeter","l":"addEventListener(Handler, BandwidthMeter.EventListener)","url":"addEventListener(android.os.Handler,com.google.android.exoplayer2.upstream.BandwidthMeter.EventListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"addEventListener(Handler, BandwidthMeter.EventListener)","url":"addEventListener(android.os.Handler,com.google.android.exoplayer2.upstream.BandwidthMeter.EventListener)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener.EventDispatcher","l":"addEventListener(Handler, DrmSessionEventListener)","url":"addEventListener(android.os.Handler,com.google.android.exoplayer2.drm.DrmSessionEventListener)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"addEventListener(Handler, MediaSourceEventListener)","url":"addEventListener(android.os.Handler,com.google.android.exoplayer2.source.MediaSourceEventListener)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"addEventListener(Handler, MediaSourceEventListener)","url":"addEventListener(android.os.Handler,com.google.android.exoplayer2.source.MediaSourceEventListener)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"addEventListener(Handler, MediaSourceEventListener)","url":"addEventListener(android.os.Handler,com.google.android.exoplayer2.source.MediaSourceEventListener)"},{"p":"com.google.android.exoplayer2.decoder","c":"Buffer","l":"addFlag(int)"},{"p":"com.google.android.exoplayer2","c":"Player.Commands.Builder","l":"addIf(int, boolean)","url":"addIf(int,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"FlagSet.Builder","l":"addIf(int, boolean)","url":"addIf(int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"additionalFailureInfo"},{"p":"com.google.android.exoplayer2.testutil","c":"AdditionalFailureInfo","l":"AdditionalFailureInfo()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"addListener(AnalyticsListener)","url":"addListener(com.google.android.exoplayer2.analytics.AnalyticsListener)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"addListener(DownloadManager.Listener)","url":"addListener(com.google.android.exoplayer2.offline.DownloadManager.Listener)"},{"p":"com.google.android.exoplayer2.upstream","c":"BandwidthMeter.EventListener.EventDispatcher","l":"addListener(Handler, BandwidthMeter.EventListener)","url":"addListener(android.os.Handler,com.google.android.exoplayer2.upstream.BandwidthMeter.EventListener)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"addListener(HlsPlaylistTracker.PlaylistEventListener)","url":"addListener(com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker.PlaylistEventListener)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"addListener(HlsPlaylistTracker.PlaylistEventListener)","url":"addListener(com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker.PlaylistEventListener)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"addListener(Player.EventListener)","url":"addListener(com.google.android.exoplayer2.Player.EventListener)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"addListener(Player.EventListener)","url":"addListener(com.google.android.exoplayer2.Player.EventListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addListener(Player.EventListener)","url":"addListener(com.google.android.exoplayer2.Player.EventListener)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"addListener(Player.EventListener)","url":"addListener(com.google.android.exoplayer2.Player.EventListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"addListener(Player.EventListener)","url":"addListener(com.google.android.exoplayer2.Player.EventListener)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"addListener(Player.Listener)","url":"addListener(com.google.android.exoplayer2.Player.Listener)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"addListener(Player.Listener)","url":"addListener(com.google.android.exoplayer2.Player.Listener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addListener(Player.Listener)","url":"addListener(com.google.android.exoplayer2.Player.Listener)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"addListener(Player.Listener)","url":"addListener(com.google.android.exoplayer2.Player.Listener)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"addListener(Player.Listener)","url":"addListener(com.google.android.exoplayer2.Player.Listener)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"addListener(String, Cache.Listener)","url":"addListener(java.lang.String,com.google.android.exoplayer2.upstream.cache.Cache.Listener)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"addListener(String, Cache.Listener)","url":"addListener(java.lang.String,com.google.android.exoplayer2.upstream.cache.Cache.Listener)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"addListener(TimeBar.OnScrubListener)","url":"addListener(com.google.android.exoplayer2.ui.TimeBar.OnScrubListener)"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar","l":"addListener(TimeBar.OnScrubListener)","url":"addListener(com.google.android.exoplayer2.ui.TimeBar.OnScrubListener)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"addMediaItem(int, MediaItem)","url":"addMediaItem(int,com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"addMediaItem(int, MediaItem)","url":"addMediaItem(int,com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"addMediaItem(int, MediaItem)","url":"addMediaItem(int,com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"addMediaItem(MediaItem)","url":"addMediaItem(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"addMediaItem(MediaItem)","url":"addMediaItem(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"addMediaItem(MediaItem)","url":"addMediaItem(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"addMediaItems(int, List)","url":"addMediaItems(int,java.util.List)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"addMediaItems(int, List)","url":"addMediaItems(int,java.util.List)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addMediaItems(int, List)","url":"addMediaItems(int,java.util.List)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"addMediaItems(int, List)","url":"addMediaItems(int,java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"addMediaItems(int, List)","url":"addMediaItems(int,java.util.List)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"addMediaItems(List)","url":"addMediaItems(java.util.List)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"addMediaItems(List)","url":"addMediaItems(java.util.List)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"addMediaItems(List)","url":"addMediaItems(java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.AddMediaItems","l":"AddMediaItems(String, MediaSource...)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"addMediaSource(int, MediaSource, Handler, Runnable)","url":"addMediaSource(int,com.google.android.exoplayer2.source.MediaSource,android.os.Handler,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"addMediaSource(int, MediaSource)","url":"addMediaSource(int,com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addMediaSource(int, MediaSource)","url":"addMediaSource(int,com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"addMediaSource(int, MediaSource)","url":"addMediaSource(int,com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"addMediaSource(int, MediaSource)","url":"addMediaSource(int,com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"addMediaSource(MediaSource, Handler, Runnable)","url":"addMediaSource(com.google.android.exoplayer2.source.MediaSource,android.os.Handler,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"addMediaSource(MediaSource)","url":"addMediaSource(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addMediaSource(MediaSource)","url":"addMediaSource(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"addMediaSource(MediaSource)","url":"addMediaSource(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"addMediaSource(MediaSource)","url":"addMediaSource(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"addMediaSources(Collection, Handler, Runnable)","url":"addMediaSources(java.util.Collection,android.os.Handler,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"addMediaSources(Collection)","url":"addMediaSources(java.util.Collection)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"addMediaSources(int, Collection, Handler, Runnable)","url":"addMediaSources(int,java.util.Collection,android.os.Handler,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"addMediaSources(int, Collection)","url":"addMediaSources(int,java.util.Collection)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"addMediaSources(int, List)","url":"addMediaSources(int,java.util.List)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addMediaSources(int, List)","url":"addMediaSources(int,java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"addMediaSources(int, List)","url":"addMediaSources(int,java.util.List)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"addMediaSources(List)","url":"addMediaSources(java.util.List)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addMediaSources(List)","url":"addMediaSources(java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"addMediaSources(List)","url":"addMediaSources(java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"addMediaSources(MediaSource...)","url":"addMediaSources(com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.MetadataComponent","l":"addMetadataOutput(MetadataOutput)","url":"addMetadataOutput(com.google.android.exoplayer2.metadata.MetadataOutput)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addMetadataOutput(MetadataOutput)","url":"addMetadataOutput(com.google.android.exoplayer2.metadata.MetadataOutput)"},{"p":"com.google.android.exoplayer2.text.span","c":"SpanUtil","l":"addOrReplaceSpan(Spannable, Object, int, int, int)","url":"addOrReplaceSpan(android.text.Spannable,java.lang.Object,int,int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock","l":"addPendingHandlerMessage(FakeClock.HandlerMessage)","url":"addPendingHandlerMessage(com.google.android.exoplayer2.testutil.FakeClock.HandlerMessage)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"addPlaylistItem(int, MediaItem)","url":"addPlaylistItem(int,androidx.media2.common.MediaItem)"},{"p":"com.google.android.exoplayer2.util","c":"SlidingPercentile","l":"addSample(int, float)","url":"addSample(int,float)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"addTextLanguagesToSelection(boolean, String...)","url":"addTextLanguagesToSelection(boolean,java.lang.String...)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.TextComponent","l":"addTextOutput(TextOutput)","url":"addTextOutput(com.google.android.exoplayer2.text.TextOutput)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addTextOutput(TextOutput)","url":"addTextOutput(com.google.android.exoplayer2.text.TextOutput)"},{"p":"com.google.android.exoplayer2.testutil","c":"Dumper","l":"addTime(String, long)","url":"addTime(java.lang.String,long)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"addTrackSelection(int, DefaultTrackSelector.Parameters)","url":"addTrackSelection(int,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"addTrackSelectionForSingleRenderer(int, int, DefaultTrackSelector.Parameters, List)","url":"addTrackSelectionForSingleRenderer(int,int,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters,java.util.List)"},{"p":"com.google.android.exoplayer2.upstream","c":"BaseDataSource","l":"addTransferListener(TransferListener)","url":"addTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSource","l":"addTransferListener(TransferListener)","url":"addTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSource","l":"addTransferListener(TransferListener)","url":"addTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"DummyDataSource","l":"addTransferListener(TransferListener)","url":"addTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"PriorityDataSource","l":"addTransferListener(TransferListener)","url":"addTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"ResolvingDataSource","l":"addTransferListener(TransferListener)","url":"addTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"StatsDataSource","l":"addTransferListener(TransferListener)","url":"addTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"TeeDataSource","l":"addTransferListener(TransferListener)","url":"addTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"addTransferListener(TransferListener)","url":"addTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesCipherDataSource","l":"addTransferListener(TransferListener)","url":"addTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"addVideoFrameProcessingOffset(long)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"addVideoListener(VideoListener)","url":"addVideoListener(com.google.android.exoplayer2.video.VideoListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"addVideoListener(VideoListener)","url":"addVideoListener(com.google.android.exoplayer2.video.VideoListener)"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView","l":"addVideoSurfaceListener(SphericalGLSurfaceView.VideoSurfaceListener)","url":"addVideoSurfaceListener(com.google.android.exoplayer2.video.spherical.SphericalGLSurfaceView.VideoSurfaceListener)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"addVisibilityListener(PlayerControlView.VisibilityListener)","url":"addVisibilityListener(com.google.android.exoplayer2.ui.PlayerControlView.VisibilityListener)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"addVisibilityListener(StyledPlayerControlView.VisibilityListener)","url":"addVisibilityListener(com.google.android.exoplayer2.ui.StyledPlayerControlView.VisibilityListener)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"addWithOverflowDefault(long, long, long)","url":"addWithOverflowDefault(long,long,long)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"AdGroup(long)","url":"%3Cinit%3E(long)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"adGroupCount"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"adGroupIndex"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"adGroupIndex"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"adIndexInAdGroup"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"adIndexInAdGroup"},{"p":"com.google.android.exoplayer2.video","c":"VideoFrameReleaseHelper","l":"adjustReleaseTime(long)"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"adjustSampleTimestamp(long)"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"adjustTsTimestamp(long)"},{"p":"com.google.android.exoplayer2.ui","c":"AdOverlayInfo","l":"AdOverlayInfo(View, int, String)","url":"%3Cinit%3E(android.view.View,int,java.lang.String)"},{"p":"com.google.android.exoplayer2.ui","c":"AdOverlayInfo","l":"AdOverlayInfo(View, int)","url":"%3Cinit%3E(android.view.View,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"adPlaybackCount"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"adPlaybackState"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"AdPlaybackState(Object, long...)","url":"%3Cinit%3E(java.lang.Object,long...)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"adResumePositionUs"},{"p":"com.google.android.exoplayer2","c":"MediaItem.PlaybackProperties","l":"adsConfiguration"},{"p":"com.google.android.exoplayer2","c":"MediaItem.AdsConfiguration","l":"adsId"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"adsId"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource","l":"AdsMediaSource(MediaSource, DataSpec, Object, MediaSourceFactory, AdsLoader, AdViewProvider)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaSource,com.google.android.exoplayer2.upstream.DataSpec,java.lang.Object,com.google.android.exoplayer2.source.MediaSourceFactory,com.google.android.exoplayer2.source.ads.AdsLoader,com.google.android.exoplayer2.ui.AdViewProvider)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.AdsConfiguration","l":"adTagUri"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"ADTS"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsExtractor","l":"AdtsExtractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsExtractor","l":"AdtsExtractor(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsReader","l":"AdtsReader(boolean, String)","url":"%3Cinit%3E(boolean,java.lang.String)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsReader","l":"AdtsReader(boolean)","url":"%3Cinit%3E(boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"advancePeekPosition(int, boolean)","url":"advancePeekPosition(int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"advancePeekPosition(int, boolean)","url":"advancePeekPosition(int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"advancePeekPosition(int, boolean)","url":"advancePeekPosition(int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"advancePeekPosition(int, boolean)","url":"advancePeekPosition(int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"advancePeekPosition(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"advancePeekPosition(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"advancePeekPosition(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"advancePeekPosition(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock","l":"advanceTime(long)"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesCipherDataSink","l":"AesCipherDataSink(byte[], DataSink, byte[])","url":"%3Cinit%3E(byte[],com.google.android.exoplayer2.upstream.DataSink,byte[])"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesCipherDataSink","l":"AesCipherDataSink(byte[], DataSink)","url":"%3Cinit%3E(byte[],com.google.android.exoplayer2.upstream.DataSink)"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesCipherDataSource","l":"AesCipherDataSource(byte[], DataSource)","url":"%3Cinit%3E(byte[],com.google.android.exoplayer2.upstream.DataSource)"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesFlushingCipher","l":"AesFlushingCipher(int, byte[], long, long)","url":"%3Cinit%3E(int,byte[],long,long)"},{"p":"com.google.android.exoplayer2.robolectric","c":"ShadowMediaCodecConfig","l":"after()"},{"p":"com.google.android.exoplayer2.testutil","c":"HttpDataSourceTestEnv","l":"after()"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"albumArtist"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"albumTitle"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"alignVideoSizeV21(int, int)","url":"alignVideoSizeV21(int,int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"ALL_PLAYBACK_ACTIONS"},{"p":"com.google.android.exoplayer2.upstream","c":"Allocator","l":"allocate()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultAllocator","l":"allocate()"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection.AdaptationCheckpoint","l":"allocatedBandwidth"},{"p":"com.google.android.exoplayer2.upstream","c":"Allocation","l":"Allocation(byte[], int)","url":"%3Cinit%3E(byte[],int)"},{"p":"com.google.android.exoplayer2","c":"C","l":"ALLOW_CAPTURE_BY_ALL"},{"p":"com.google.android.exoplayer2","c":"C","l":"ALLOW_CAPTURE_BY_NONE"},{"p":"com.google.android.exoplayer2","c":"C","l":"ALLOW_CAPTURE_BY_SYSTEM"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"allowAudioMixedChannelCountAdaptiveness"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"allowAudioMixedMimeTypeAdaptiveness"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"allowAudioMixedSampleRateAdaptiveness"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes","l":"allowedCapturePolicy"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm.LicenseServer","l":"allowingSchemeDatas(List...)","url":"allowingSchemeDatas(java.util.List...)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"allowMultipleAdaptiveSelections"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"allowVideoMixedMimeTypeAdaptiveness"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"allowVideoNonSeamlessAdaptiveness"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"allSamplesAreSyncSamples(String, String)","url":"allSamplesAreSyncSamples(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"AMR"},{"p":"com.google.android.exoplayer2.extractor.amr","c":"AmrExtractor","l":"AmrExtractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.amr","c":"AmrExtractor","l":"AmrExtractor(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"AnalyticsCollector(Clock)","url":"%3Cinit%3E(com.google.android.exoplayer2.util.Clock)"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"ANCHOR_TYPE_END"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"ANCHOR_TYPE_MIDDLE"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"ANCHOR_TYPE_START"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject.AndSpanFlags","l":"andFlags(int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ApicFrame","l":"ApicFrame(String, String, int, byte[])","url":"%3Cinit%3E(java.lang.String,java.lang.String,int,byte[])"},{"p":"com.google.android.exoplayer2.ext.cast","c":"DefaultCastOptionsProvider","l":"APP_ID_DEFAULT_RECEIVER_WITH_DRM"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"append(List)","url":"append(java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData","l":"appendReadAction(Runnable)","url":"appendReadAction(java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData","l":"appendReadData(byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData","l":"appendReadData(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData","l":"appendReadError(IOException)","url":"appendReadError(java.io.IOException)"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","c":"AppInfoTable","l":"AppInfoTable(int, String)","url":"%3Cinit%3E(int,java.lang.String)"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","c":"AppInfoTableDecoder","l":"AppInfoTableDecoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_AIT"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_CAMERA_MOTION"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_CEA608"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_CEA708"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_DVBSUBS"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_EMSG"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_EXIF"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_ICY"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_ID3"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","c":"AppInfoTableDecoder","l":"APPLICATION_INFORMATION_TABLE_ID"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_M3U8"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_MATROSKA"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_MP4"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_MP4CEA608"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_MP4VTT"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_MPD"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_PGS"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_RAWCC"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_RTSP"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_SCTE35"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_SS"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_SUBRIP"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_TTML"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_TX3G"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_VOBSUB"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"APPLICATION_WEBM"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"apply(Action)","url":"apply(com.google.android.exoplayer2.testutil.Action)"},{"p":"com.google.android.exoplayer2.testutil","c":"AdditionalFailureInfo","l":"apply(Statement, Description)","url":"apply(org.junit.runners.model.Statement,org.junit.runner.Description)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"applyContentMetadataMutations(String, ContentMetadataMutations)","url":"applyContentMetadataMutations(java.lang.String,com.google.android.exoplayer2.upstream.cache.ContentMetadataMutations)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"applyContentMetadataMutations(String, ContentMetadataMutations)","url":"applyContentMetadataMutations(java.lang.String,com.google.android.exoplayer2.upstream.cache.ContentMetadataMutations)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink.AudioProcessorChain","l":"applyPlaybackParameters(PlaybackParameters)","url":"applyPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink.DefaultAudioProcessorChain","l":"applyPlaybackParameters(PlaybackParameters)","url":"applyPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink.AudioProcessorChain","l":"applySkipSilenceEnabled(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink.DefaultAudioProcessorChain","l":"applySkipSilenceEnabled(boolean)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.AppManagedProvider","l":"AppManagedProvider(ExoMediaDrm)","url":"%3Cinit%3E(com.google.android.exoplayer2.drm.ExoMediaDrm)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"areEqual(Object, Object)","url":"areEqual(java.lang.Object,java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"artist"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"artworkData"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"artworkDataType"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"artworkUri"},{"p":"com.google.android.exoplayer2","c":"C","l":"ASCII_NAME"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil","l":"ASPECT_RATIO_IDC_VALUES"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout","l":"AspectRatioFrameLayout(Context, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout","l":"AspectRatioFrameLayout(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertAdGroupCounts(Timeline, int...)","url":"assertAdGroupCounts(com.google.android.exoplayer2.Timeline,int...)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts","l":"assertAllBehaviors(ExtractorAsserts.ExtractorFactory, String, String)","url":"assertAllBehaviors(com.google.android.exoplayer2.testutil.ExtractorAsserts.ExtractorFactory,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts","l":"assertAllBehaviors(ExtractorAsserts.ExtractorFactory, String)","url":"assertAllBehaviors(com.google.android.exoplayer2.testutil.ExtractorAsserts.ExtractorFactory,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts","l":"assertBehavior(ExtractorAsserts.ExtractorFactory, String, ExtractorAsserts.AssertionConfig, ExtractorAsserts.SimulationConfig)","url":"assertBehavior(com.google.android.exoplayer2.testutil.ExtractorAsserts.ExtractorFactory,java.lang.String,com.google.android.exoplayer2.testutil.ExtractorAsserts.AssertionConfig,com.google.android.exoplayer2.testutil.ExtractorAsserts.SimulationConfig)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts","l":"assertBehavior(ExtractorAsserts.ExtractorFactory, String, ExtractorAsserts.SimulationConfig)","url":"assertBehavior(com.google.android.exoplayer2.testutil.ExtractorAsserts.ExtractorFactory,java.lang.String,com.google.android.exoplayer2.testutil.ExtractorAsserts.SimulationConfig)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"assertBitmapsAreSimilar(Bitmap, Bitmap, double)","url":"assertBitmapsAreSimilar(android.graphics.Bitmap,android.graphics.Bitmap,double)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"assertBufferInfosEqual(MediaCodec.BufferInfo, MediaCodec.BufferInfo)","url":"assertBufferInfosEqual(android.media.MediaCodec.BufferInfo,android.media.MediaCodec.BufferInfo)"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts","l":"assertCachedData(Cache, CacheAsserts.RequestSet)","url":"assertCachedData(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.testutil.CacheAsserts.RequestSet)"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts","l":"assertCachedData(Cache, FakeDataSet)","url":"assertCachedData(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.testutil.FakeDataSet)"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts","l":"assertCacheEmpty(Cache)","url":"assertCacheEmpty(com.google.android.exoplayer2.upstream.cache.Cache)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"assertCompletedManifestLoads(Integer...)","url":"assertCompletedManifestLoads(java.lang.Integer...)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"assertCompletedMediaPeriodLoads(MediaSource.MediaPeriodId...)","url":"assertCompletedMediaPeriodLoads(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId...)"},{"p":"com.google.android.exoplayer2.testutil","c":"DecoderCountersUtil","l":"assertConsecutiveDroppedBufferLimit(String, DecoderCounters, int)","url":"assertConsecutiveDroppedBufferLimit(java.lang.String,com.google.android.exoplayer2.decoder.DecoderCounters,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts","l":"assertDataCached(Cache, DataSpec, byte[])","url":"assertDataCached(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.DataSpec,byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"assertDataSourceContent(DataSource, DataSpec, byte[], boolean)","url":"assertDataSourceContent(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,byte[],boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"DecoderCountersUtil","l":"assertDroppedBufferLimit(String, DecoderCounters, int)","url":"assertDroppedBufferLimit(java.lang.String,com.google.android.exoplayer2.decoder.DecoderCounters,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertEmpty(Timeline)","url":"assertEmpty(com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertEqualNextWindowIndices(Timeline, Timeline, int, boolean)","url":"assertEqualNextWindowIndices(com.google.android.exoplayer2.Timeline,com.google.android.exoplayer2.Timeline,int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertEqualPreviousWindowIndices(Timeline, Timeline, int, boolean)","url":"assertEqualPreviousWindowIndices(com.google.android.exoplayer2.Timeline,com.google.android.exoplayer2.Timeline,int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertEqualsExceptIdsAndManifest(Timeline, Timeline)","url":"assertEqualsExceptIdsAndManifest(com.google.android.exoplayer2.Timeline,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.testutil","c":"DefaultRenderersFactoryAsserts","l":"assertExtensionRendererCreated(Class, int)","url":"assertExtensionRendererCreated(java.lang.Class,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaPeriodAsserts","l":"assertGetStreamKeysAndManifestFilterIntegration(MediaPeriodAsserts.FilterableManifestMediaPeriodFactory, T, int, String)","url":"assertGetStreamKeysAndManifestFilterIntegration(com.google.android.exoplayer2.testutil.MediaPeriodAsserts.FilterableManifestMediaPeriodFactory,T,int,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaPeriodAsserts","l":"assertGetStreamKeysAndManifestFilterIntegration(MediaPeriodAsserts.FilterableManifestMediaPeriodFactory, T)","url":"assertGetStreamKeysAndManifestFilterIntegration(com.google.android.exoplayer2.testutil.MediaPeriodAsserts.FilterableManifestMediaPeriodFactory,T)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayerLibraryInfo","l":"ASSERTIONS_ENABLED"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"assertMediaItemsTransitionedSame(MediaItem...)","url":"assertMediaItemsTransitionedSame(com.google.android.exoplayer2.MediaItem...)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"assertMediaItemsTransitionReasonsEqual(Integer...)","url":"assertMediaItemsTransitionReasonsEqual(java.lang.Integer...)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"assertMediaPeriodCreated(MediaSource.MediaPeriodId)","url":"assertMediaPeriodCreated(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertNextWindowIndices(Timeline, int, boolean, int...)","url":"assertNextWindowIndices(com.google.android.exoplayer2.Timeline,int,boolean,int...)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"assertNoPositionDiscontinuities()"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"assertNoTimelineChange()"},{"p":"com.google.android.exoplayer2.testutil","c":"DumpFileAsserts","l":"assertOutput(Context, Dumper.Dumpable, String, String)","url":"assertOutput(android.content.Context,com.google.android.exoplayer2.testutil.Dumper.Dumpable,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"DumpFileAsserts","l":"assertOutput(Context, Dumper.Dumpable, String)","url":"assertOutput(android.content.Context,com.google.android.exoplayer2.testutil.Dumper.Dumpable,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"DumpFileAsserts","l":"assertOutput(Context, String, String, String)","url":"assertOutput(android.content.Context,java.lang.String,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"DumpFileAsserts","l":"assertOutput(Context, String, String)","url":"assertOutput(android.content.Context,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"assertPassed(DecoderCounters, DecoderCounters)","url":"assertPassed(com.google.android.exoplayer2.decoder.DecoderCounters,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertPeriodCounts(Timeline, int...)","url":"assertPeriodCounts(com.google.android.exoplayer2.Timeline,int...)"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertPeriodDurations(Timeline, long...)","url":"assertPeriodDurations(com.google.android.exoplayer2.Timeline,long...)"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertPeriodEqualsExceptIds(Timeline.Period, Timeline.Period)","url":"assertPeriodEqualsExceptIds(com.google.android.exoplayer2.Timeline.Period,com.google.android.exoplayer2.Timeline.Period)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"assertPlaybackStatesEqual(Integer...)","url":"assertPlaybackStatesEqual(java.lang.Integer...)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"assertPlayedPeriodIndices(Integer...)","url":"assertPlayedPeriodIndices(java.lang.Integer...)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"assertPositionDiscontinuityReasonsEqual(Integer...)","url":"assertPositionDiscontinuityReasonsEqual(java.lang.Integer...)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"assertPrepareAndReleaseAllPeriods()"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertPreviousWindowIndices(Timeline, int, boolean, int...)","url":"assertPreviousWindowIndices(com.google.android.exoplayer2.Timeline,int,boolean,int...)"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts","l":"assertReadData(DataSource, DataSpec, byte[])","url":"assertReadData(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"assertReleased()"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestDownloadManagerListener","l":"assertRemoved(String)","url":"assertRemoved(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"assertSample(int, byte[], long, int, TrackOutput.CryptoData)","url":"assertSample(int,byte[],long,int,com.google.android.exoplayer2.extractor.TrackOutput.CryptoData)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"assertSampleCount(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"DecoderCountersUtil","l":"assertSkippedOutputBufferCount(String, DecoderCounters, int)","url":"assertSkippedOutputBufferCount(java.lang.String,com.google.android.exoplayer2.decoder.DecoderCounters,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts","l":"assertSniff(Extractor, FakeExtractorInput, boolean)","url":"assertSniff(com.google.android.exoplayer2.extractor.Extractor,com.google.android.exoplayer2.testutil.FakeExtractorInput,boolean)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestDownloadManagerListener","l":"assertState(String, int)","url":"assertState(java.lang.String,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"assertThat(Spanned)","url":"assertThat(android.text.Spanned)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"assertTimelineChange()"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"assertTimelineChangeBlocking()"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"assertTimelineChangeReasonsEqual(Integer...)","url":"assertTimelineChangeReasonsEqual(java.lang.Integer...)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"assertTimelinesSame(Timeline...)","url":"assertTimelinesSame(com.google.android.exoplayer2.Timeline...)"},{"p":"com.google.android.exoplayer2.testutil","c":"DecoderCountersUtil","l":"assertTotalBufferCount(String, DecoderCounters, int, int)","url":"assertTotalBufferCount(java.lang.String,com.google.android.exoplayer2.decoder.DecoderCounters,int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaPeriodAsserts","l":"assertTrackGroups(MediaPeriod, TrackGroupArray)","url":"assertTrackGroups(com.google.android.exoplayer2.source.MediaPeriod,com.google.android.exoplayer2.source.TrackGroupArray)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"assertTrackGroupsEqual(TrackGroupArray)","url":"assertTrackGroupsEqual(com.google.android.exoplayer2.source.TrackGroupArray)"},{"p":"com.google.android.exoplayer2.testutil","c":"DecoderCountersUtil","l":"assertVideoFrameProcessingOffsetSampleCount(String, DecoderCounters, int, int)","url":"assertVideoFrameProcessingOffsetSampleCount(java.lang.String,com.google.android.exoplayer2.decoder.DecoderCounters,int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertWindowEqualsExceptUidAndManifest(Timeline.Window, Timeline.Window)","url":"assertWindowEqualsExceptUidAndManifest(com.google.android.exoplayer2.Timeline.Window,com.google.android.exoplayer2.Timeline.Window)"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertWindowIsDynamic(Timeline, boolean...)","url":"assertWindowIsDynamic(com.google.android.exoplayer2.Timeline,boolean...)"},{"p":"com.google.android.exoplayer2.testutil","c":"TimelineAsserts","l":"assertWindowTags(Timeline, Object...)","url":"assertWindowTags(com.google.android.exoplayer2.Timeline,java.lang.Object...)"},{"p":"com.google.android.exoplayer2.upstream","c":"AssetDataSource","l":"AssetDataSource(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.upstream","c":"AssetDataSource.AssetDataSourceException","l":"AssetDataSourceException(IOException)","url":"%3Cinit%3E(java.io.IOException)"},{"p":"com.google.android.exoplayer2.upstream","c":"AssetDataSource.AssetDataSourceException","l":"AssetDataSourceException(Throwable, int)","url":"%3Cinit%3E(java.lang.Throwable,int)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Period","l":"assetIdentifier"},{"p":"com.google.android.exoplayer2.util","c":"AtomicFile","l":"AtomicFile(File)","url":"%3Cinit%3E(java.io.File)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"RangedUri","l":"attemptMerge(RangedUri, String)","url":"attemptMerge(com.google.android.exoplayer2.source.dash.manifest.RangedUri,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil.Attribute","l":"Attribute(int, int)","url":"%3Cinit%3E(int,int)"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_AAC"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_AC3"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_AC4"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_ALAC"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_ALAW"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_AMR"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_AMR_NB"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_AMR_WB"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_DTS"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_DTS_EXPRESS"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_DTS_HD"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_DTS_UHD"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_E_AC3"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_E_AC3_JOC"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_FLAC"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"AUDIO_FORMAT"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_MATROSKA"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_MLAW"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_MP4"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_MPEG"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_MPEG_L1"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_MPEG_L2"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_MPEGH_MHA1"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_MPEGH_MHM1"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_MSGSM"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AUDIO_OBJECT_TYPE_AAC_ELD"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AUDIO_OBJECT_TYPE_AAC_ER_BSAC"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AUDIO_OBJECT_TYPE_AAC_LC"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AUDIO_OBJECT_TYPE_AAC_PS"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AUDIO_OBJECT_TYPE_AAC_SBR"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"AUDIO_OBJECT_TYPE_AAC_XHE"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_OGG"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_OPUS"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_RAW"},{"p":"com.google.android.exoplayer2","c":"C","l":"AUDIO_SESSION_ID_UNSET"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"AUDIO_STREAM"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"AUDIO_STREAM_MASK"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_TRUEHD"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_UNKNOWN"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_VORBIS"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_WAV"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"AUDIO_WEBM"},{"p":"com.google.android.exoplayer2.audio","c":"AudioCapabilities","l":"AudioCapabilities(int[], int)","url":"%3Cinit%3E(int[],int)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioCapabilitiesReceiver","l":"AudioCapabilitiesReceiver(Context, AudioCapabilitiesReceiver.Listener)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.audio.AudioCapabilitiesReceiver.Listener)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener.EventDispatcher","l":"audioCodecError(Exception)","url":"audioCodecError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2","c":"C","l":"AUDIOFOCUS_GAIN"},{"p":"com.google.android.exoplayer2","c":"C","l":"AUDIOFOCUS_GAIN_TRANSIENT"},{"p":"com.google.android.exoplayer2","c":"C","l":"AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE"},{"p":"com.google.android.exoplayer2","c":"C","l":"AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK"},{"p":"com.google.android.exoplayer2","c":"C","l":"AUDIOFOCUS_NONE"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor.AudioFormat","l":"AudioFormat(int, int, int)","url":"%3Cinit%3E(int,int,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"audioFormatHistory"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry.VariantInfo","l":"audioGroupId"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Variant","l":"audioGroupId"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"audios"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener.EventDispatcher","l":"audioSinkError(Exception)","url":"audioSinkError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.AudioTrackScore","l":"AudioTrackScore(Format, DefaultTrackSelector.Parameters, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters,int)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.InitializationException","l":"audioTrackState"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"autoReturn"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.Event","l":"autoReturn"},{"p":"com.google.android.exoplayer2.audio","c":"AuxEffectInfo","l":"AuxEffectInfo(int, float)","url":"%3Cinit%3E(int,float)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"availabilityStartTimeMs"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"availNum"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.Event","l":"availNum"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"availsExpected"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.Event","l":"availsExpected"},{"p":"com.google.android.exoplayer2","c":"Format","l":"averageBitrate"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry.VariantInfo","l":"averageBitrate"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"backgroundColor"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"backgroundJoiningCount"},{"p":"com.google.android.exoplayer2.upstream","c":"BandwidthMeter.EventListener.EventDispatcher","l":"bandwidthSample(int, long, long)","url":"bandwidthSample(int,long,long)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"BAR_GRAVITY_BOTTOM"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"BAR_GRAVITY_CENTER"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"BASE_TYPE_APPLICATION"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"BASE_TYPE_AUDIO"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"BASE_TYPE_IMAGE"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"BASE_TYPE_TEXT"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"BASE_TYPE_VIDEO"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"BaseAudioProcessor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"BaseDataSource","l":"BaseDataSource(boolean)","url":"%3Cinit%3E(boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.BaseFactory","l":"BaseFactory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunk","l":"BaseMediaChunk(DataSource, DataSpec, Format, int, Object, long, long, long, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,com.google.android.exoplayer2.Format,int,java.lang.Object,long,long,long,long,long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunkIterator","l":"BaseMediaChunkIterator(long, long)","url":"%3Cinit%3E(long,long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunkOutput","l":"BaseMediaChunkOutput(int[], SampleQueue[])","url":"%3Cinit%3E(int[],com.google.android.exoplayer2.source.SampleQueue[])"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"BaseMediaSource()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"BasePlayer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"BaseRenderer(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"BaseTrackSelection(TrackGroup, int...)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroup,int...)"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"BaseTrackSelection(TrackGroup, int[], int)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroup,int[],int)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylist","l":"baseUri"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"BaseUrl","l":"BaseUrl(String, String, int, int)","url":"%3Cinit%3E(java.lang.String,java.lang.String,int,int)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"BaseUrl","l":"BaseUrl(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash","c":"BaseUrlExclusionList","l":"BaseUrlExclusionList()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser.RepresentationInfo","l":"baseUrls"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"baseUrls"},{"p":"com.google.android.exoplayer2.robolectric","c":"ShadowMediaCodecConfig","l":"before()"},{"p":"com.google.android.exoplayer2.testutil","c":"HttpDataSourceTestEnv","l":"before()"},{"p":"com.google.android.exoplayer2.util","c":"TraceUtil","l":"beginSection(String)","url":"beginSection(java.lang.String)"},{"p":"com.google.android.exoplayer2.source","c":"BehindLiveWindowException","l":"BehindLiveWindowException()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.analytics","c":"DefaultPlaybackSessionManager","l":"belongsToSession(AnalyticsListener.EventTime, String)","url":"belongsToSession(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackSessionManager","l":"belongsToSession(AnalyticsListener.EventTime, String)","url":"belongsToSession(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"binaryElement(int, int, ExtractorInput)","url":"binaryElement(int,int,com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"binaryElement(int, int, ExtractorInput)","url":"binaryElement(int,int,com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"BinaryFrame","l":"BinaryFrame(String, byte[])","url":"%3Cinit%3E(java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"binarySearchCeil(int[], int, boolean, boolean)","url":"binarySearchCeil(int[],int,boolean,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"binarySearchCeil(List>, T, boolean, boolean)","url":"binarySearchCeil(java.util.List,T,boolean,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"binarySearchCeil(long[], long, boolean, boolean)","url":"binarySearchCeil(long[],long,boolean,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"binarySearchFloor(int[], int, boolean, boolean)","url":"binarySearchFloor(int[],int,boolean,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"binarySearchFloor(List>, T, boolean, boolean)","url":"binarySearchFloor(java.util.List,T,boolean,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"binarySearchFloor(long[], long, boolean, boolean)","url":"binarySearchFloor(long[],long,boolean,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"binarySearchFloor(LongArray, long, boolean, boolean)","url":"binarySearchFloor(com.google.android.exoplayer2.util.LongArray,long,boolean,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"BinarySearchSeeker(BinarySearchSeeker.SeekTimestampConverter, BinarySearchSeeker.TimestampSeeker, long, long, long, long, long, long, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.BinarySearchSeeker.SeekTimestampConverter,com.google.android.exoplayer2.extractor.BinarySearchSeeker.TimestampSeeker,long,long,long,long,long,long,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.BinarySearchSeekMap","l":"BinarySearchSeekMap(BinarySearchSeeker.SeekTimestampConverter, long, long, long, long, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.BinarySearchSeeker.SeekTimestampConverter,long,long,long,long,long,long)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil.Attribute","l":"bind()"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil.Uniform","l":"bind()"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"bitmap"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"bitmapHeight"},{"p":"com.google.android.exoplayer2","c":"Format","l":"bitrate"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil.Header","l":"bitrate"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"bitrate"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.VorbisIdHeader","l":"bitrateMaximum"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.VorbisIdHeader","l":"bitrateMinimum"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.VorbisIdHeader","l":"bitrateNominal"},{"p":"com.google.android.exoplayer2","c":"C","l":"BITS_PER_BYTE"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisBitArray","l":"bitsLeft()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"bitsLeft()"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"bitsPerSample"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"bitsPerSampleLookupKey"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util.SyncFrameInfo","l":"bitstreamVersion"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"blacklist(int, long)","url":"blacklist(int,long)"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"blacklist(int, long)","url":"blacklist(int,long)"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"blacklist(int, long)","url":"blacklist(int,long)"},{"p":"com.google.android.exoplayer2.util","c":"ConditionVariable","l":"block()"},{"p":"com.google.android.exoplayer2.util","c":"ConditionVariable","l":"block(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.Mode","l":"blockFlag"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.VorbisIdHeader","l":"blockSize0"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.VorbisIdHeader","l":"blockSize1"},{"p":"com.google.android.exoplayer2.util","c":"ConditionVariable","l":"blockUninterruptible()"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"blockUntilActionScheduleFinished(long)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"blockUntilDelivered()"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"blockUntilDelivered(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"blockUntilEnded(long)"},{"p":"com.google.android.exoplayer2.util","c":"RunnableFutureTask","l":"blockUntilFinished()"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestDownloadManagerListener","l":"blockUntilIdle()"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestDownloadManagerListener","l":"blockUntilIdleAndThrowAnyFailure()"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestDownloadManagerListener","l":"blockUntilInitialized()"},{"p":"com.google.android.exoplayer2.util","c":"RunnableFutureTask","l":"blockUntilStarted()"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"blockUntilStopped(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity.HostedTest","l":"blockUntilStopped(long)"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.PpsData","l":"bottomFieldPicOrderInFramePresentFlag"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"breakDurationUs"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.Event","l":"breakDurationUs"},{"p":"com.google.android.exoplayer2","c":"C","l":"BUFFER_FLAG_DECODE_ONLY"},{"p":"com.google.android.exoplayer2","c":"C","l":"BUFFER_FLAG_ENCRYPTED"},{"p":"com.google.android.exoplayer2","c":"C","l":"BUFFER_FLAG_END_OF_STREAM"},{"p":"com.google.android.exoplayer2","c":"C","l":"BUFFER_FLAG_HAS_SUPPLEMENTAL_DATA"},{"p":"com.google.android.exoplayer2","c":"C","l":"BUFFER_FLAG_KEY_FRAME"},{"p":"com.google.android.exoplayer2","c":"C","l":"BUFFER_FLAG_LAST_SAMPLE"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"BUFFER_REPLACEMENT_MODE_DIRECT"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"BUFFER_REPLACEMENT_MODE_DISABLED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"BUFFER_REPLACEMENT_MODE_NORMAL"},{"p":"com.google.android.exoplayer2.decoder","c":"Buffer","l":"Buffer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl.Builder","l":"build()"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl.Builder","l":"build()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"build()"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"build()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"build()"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"build()"},{"p":"com.google.android.exoplayer2","c":"Player.Commands.Builder","l":"build()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"build()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.TestResource.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"build()"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts.AssertionConfig.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"build()"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"build()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder","l":"build()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.util","c":"FlagSet.Builder","l":"build()"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager.Builder","l":"build(MediaDrmCallback)","url":"build(com.google.android.exoplayer2.drm.MediaDrmCallback)"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"buildAacLcAudioSpecificConfig(int, int)","url":"buildAacLcAudioSpecificConfig(int,int)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildAdaptationSet(int, int, List, List, List, List)","url":"buildAdaptationSet(int,int,java.util.List,java.util.List,java.util.List,java.util.List)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"buildAddDownloadIntent(Context, Class, DownloadRequest, boolean)","url":"buildAddDownloadIntent(android.content.Context,java.lang.Class,com.google.android.exoplayer2.offline.DownloadRequest,boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"buildAddDownloadIntent(Context, Class, DownloadRequest, int, boolean)","url":"buildAddDownloadIntent(android.content.Context,java.lang.Class,com.google.android.exoplayer2.offline.DownloadRequest,int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"buildAssetUri(String)","url":"buildAssetUri(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"buildAudioRenderers(Context, int, MediaCodecSelector, boolean, AudioSink, Handler, AudioRendererEventListener, ArrayList)","url":"buildAudioRenderers(android.content.Context,int,com.google.android.exoplayer2.mediacodec.MediaCodecSelector,boolean,com.google.android.exoplayer2.audio.AudioSink,android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,java.util.ArrayList)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"buildAudioSink(Context, boolean, boolean, boolean)","url":"buildAudioSink(android.content.Context,boolean,boolean,boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"buildAudioSpecificConfig(int, int, int)","url":"buildAudioSpecificConfig(int,int,int)"},{"p":"com.google.android.exoplayer2.util","c":"CodecSpecificDataUtil","l":"buildAvcCodecString(int, int, int)","url":"buildAvcCodecString(int,int,int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheKeyFactory","l":"buildCacheKey(DataSpec)","url":"buildCacheKey(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"buildCameraMotionRenderers(Context, int, ArrayList)","url":"buildCameraMotionRenderers(android.content.Context,int,java.util.ArrayList)"},{"p":"com.google.android.exoplayer2.util","c":"CodecSpecificDataUtil","l":"buildCea708InitializationData(boolean)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetUtil","l":"buildCronetEngine(Context, String, boolean)","url":"buildCronetEngine(android.content.Context,java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashUtil","l":"buildDataSpec(Representation, RangedUri, int)","url":"buildDataSpec(com.google.android.exoplayer2.source.dash.manifest.Representation,com.google.android.exoplayer2.source.dash.manifest.RangedUri,int)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashUtil","l":"buildDataSpec(String, RangedUri, String, int)","url":"buildDataSpec(java.lang.String,com.google.android.exoplayer2.source.dash.manifest.RangedUri,java.lang.String,int)"},{"p":"com.google.android.exoplayer2.ui","c":"DownloadNotificationHelper","l":"buildDownloadCompletedNotification(Context, int, PendingIntent, String)","url":"buildDownloadCompletedNotification(android.content.Context,int,android.app.PendingIntent,java.lang.String)"},{"p":"com.google.android.exoplayer2.ui","c":"DownloadNotificationHelper","l":"buildDownloadFailedNotification(Context, int, PendingIntent, String)","url":"buildDownloadFailedNotification(android.content.Context,int,android.app.PendingIntent,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"buildDrmSessionManager()"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"Player.Commands.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.TestResource.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts.AssertionConfig.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.util","c":"FlagSet.Builder","l":"Builder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"Builder(Context, ExtractorsFactory)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.extractor.ExtractorsFactory)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"Builder(Context, int, String, PlayerNotificationManager.MediaDescriptionAdapter)","url":"%3Cinit%3E(android.content.Context,int,java.lang.String,com.google.android.exoplayer2.ui.PlayerNotificationManager.MediaDescriptionAdapter)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"Builder(Context, int, String)","url":"%3Cinit%3E(android.content.Context,int,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"Builder(Context, Renderer...)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.Renderer...)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"Builder(Context, RenderersFactory, ExtractorsFactory)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.RenderersFactory,com.google.android.exoplayer2.extractor.ExtractorsFactory)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"Builder(Context, RenderersFactory, TrackSelector, MediaSourceFactory, LoadControl, BandwidthMeter, AnalyticsCollector)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.RenderersFactory,com.google.android.exoplayer2.trackselection.TrackSelector,com.google.android.exoplayer2.source.MediaSourceFactory,com.google.android.exoplayer2.LoadControl,com.google.android.exoplayer2.upstream.BandwidthMeter,com.google.android.exoplayer2.analytics.AnalyticsCollector)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"Builder(Context, RenderersFactory)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.RenderersFactory)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"Builder(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"Builder(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"Builder(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"Builder(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter.Builder","l":"Builder(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"Builder(Renderer[], TrackSelector, MediaSourceFactory, LoadControl, BandwidthMeter)","url":"%3Cinit%3E(com.google.android.exoplayer2.Renderer[],com.google.android.exoplayer2.trackselection.TrackSelector,com.google.android.exoplayer2.source.MediaSourceFactory,com.google.android.exoplayer2.LoadControl,com.google.android.exoplayer2.upstream.BandwidthMeter)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest.Builder","l":"Builder(String, Uri)","url":"%3Cinit%3E(java.lang.String,android.net.Uri)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"Builder(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"Builder(TrackSelectionParameters)","url":"%3Cinit%3E(com.google.android.exoplayer2.trackselection.TrackSelectionParameters)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildEvent(String, String, long, long, byte[])","url":"buildEvent(java.lang.String,java.lang.String,long,long,byte[])"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildEventStream(String, String, long, long[], EventMessage[])","url":"buildEventStream(java.lang.String,java.lang.String,long,long[],com.google.android.exoplayer2.metadata.emsg.EventMessage[])"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"buildExoPlayer(HostActivity, Surface, MappingTrackSelector)","url":"buildExoPlayer(com.google.android.exoplayer2.testutil.HostActivity,android.view.Surface,com.google.android.exoplayer2.trackselection.MappingTrackSelector)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildFormat(String, String, int, int, float, int, int, int, String, List, List, String, List, List)","url":"buildFormat(java.lang.String,java.lang.String,int,int,float,int,int,int,java.lang.String,java.util.List,java.util.List,java.lang.String,java.util.List,java.util.List)"},{"p":"com.google.android.exoplayer2.util","c":"CodecSpecificDataUtil","l":"buildHevcCodecStringFromSps(ParsableNalUnitBitArray)","url":"buildHevcCodecStringFromSps(com.google.android.exoplayer2.util.ParsableNalUnitBitArray)"},{"p":"com.google.android.exoplayer2.audio","c":"OpusUtil","l":"buildInitializationData(byte[])"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildMediaPresentationDescription(long, long, long, boolean, long, long, long, long, ProgramInformation, UtcTimingElement, ServiceDescriptionElement, Uri, List)","url":"buildMediaPresentationDescription(long,long,long,boolean,long,long,long,long,com.google.android.exoplayer2.source.dash.manifest.ProgramInformation,com.google.android.exoplayer2.source.dash.manifest.UtcTimingElement,com.google.android.exoplayer2.source.dash.manifest.ServiceDescriptionElement,android.net.Uri,java.util.List)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"buildMetadataRenderers(Context, MetadataOutput, Looper, int, ArrayList)","url":"buildMetadataRenderers(android.content.Context,com.google.android.exoplayer2.metadata.MetadataOutput,android.os.Looper,int,java.util.ArrayList)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"buildMiscellaneousRenderers(Context, Handler, int, ArrayList)","url":"buildMiscellaneousRenderers(android.content.Context,android.os.Handler,int,java.util.ArrayList)"},{"p":"com.google.android.exoplayer2.util","c":"CodecSpecificDataUtil","l":"buildNalUnit(byte[], int, int)","url":"buildNalUnit(byte[],int,int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"buildPauseDownloadsIntent(Context, Class, boolean)","url":"buildPauseDownloadsIntent(android.content.Context,java.lang.Class,boolean)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildPeriod(String, long, List, List, Descriptor)","url":"buildPeriod(java.lang.String,long,java.util.List,java.util.List,com.google.android.exoplayer2.source.dash.manifest.Descriptor)"},{"p":"com.google.android.exoplayer2.ui","c":"DownloadNotificationHelper","l":"buildProgressNotification(Context, int, PendingIntent, String, List)","url":"buildProgressNotification(android.content.Context,int,android.app.PendingIntent,java.lang.String,java.util.List)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"PsshAtomUtil","l":"buildPsshAtom(UUID, byte[])","url":"buildPsshAtom(java.util.UUID,byte[])"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"PsshAtomUtil","l":"buildPsshAtom(UUID, UUID[], byte[])","url":"buildPsshAtom(java.util.UUID,java.util.UUID[],byte[])"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildRangedUri(String, long, long)","url":"buildRangedUri(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpUtil","l":"buildRangeRequestHeader(long, long)","url":"buildRangeRequestHeader(long,long)"},{"p":"com.google.android.exoplayer2.upstream","c":"RawResourceDataSource","l":"buildRawResourceUri(int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"buildRemoveAllDownloadsIntent(Context, Class, boolean)","url":"buildRemoveAllDownloadsIntent(android.content.Context,java.lang.Class,boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"buildRemoveDownloadIntent(Context, Class, String, boolean)","url":"buildRemoveDownloadIntent(android.content.Context,java.lang.Class,java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildRepresentation(DashManifestParser.RepresentationInfo, String, String, ArrayList, ArrayList)","url":"buildRepresentation(com.google.android.exoplayer2.source.dash.manifest.DashManifestParser.RepresentationInfo,java.lang.String,java.lang.String,java.util.ArrayList,java.util.ArrayList)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"buildRequestBuilder(DataSpec)","url":"buildRequestBuilder(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"buildRequestUri(int, int)","url":"buildRequestUri(int,int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"buildResumeDownloadsIntent(Context, Class, boolean)","url":"buildResumeDownloadsIntent(android.content.Context,java.lang.Class,boolean)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildSegmentList(RangedUri, long, long, long, long, List, long, List, long, long)","url":"buildSegmentList(com.google.android.exoplayer2.source.dash.manifest.RangedUri,long,long,long,long,java.util.List,long,java.util.List,long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildSegmentTemplate(RangedUri, long, long, long, long, long, List, long, UrlTemplate, UrlTemplate, long, long)","url":"buildSegmentTemplate(com.google.android.exoplayer2.source.dash.manifest.RangedUri,long,long,long,long,long,java.util.List,long,com.google.android.exoplayer2.source.dash.manifest.UrlTemplate,com.google.android.exoplayer2.source.dash.manifest.UrlTemplate,long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildSegmentTimelineElement(long, long)","url":"buildSegmentTimelineElement(long,long)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"buildSetRequirementsIntent(Context, Class, Requirements, boolean)","url":"buildSetRequirementsIntent(android.content.Context,java.lang.Class,com.google.android.exoplayer2.scheduler.Requirements,boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"buildSetStopReasonIntent(Context, Class, String, int, boolean)","url":"buildSetStopReasonIntent(android.content.Context,java.lang.Class,java.lang.String,int,boolean)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildSingleSegmentBase(RangedUri, long, long, long, long)","url":"buildSingleSegmentBase(com.google.android.exoplayer2.source.dash.manifest.RangedUri,long,long,long,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"buildSource(HostActivity, DrmSessionManager, FrameLayout)","url":"buildSource(com.google.android.exoplayer2.testutil.HostActivity,com.google.android.exoplayer2.drm.DrmSessionManager,android.widget.FrameLayout)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"buildTestData(int, int)","url":"buildTestData(int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"buildTestData(int, Random)","url":"buildTestData(int,java.util.Random)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"buildTestData(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"buildTestString(int, Random)","url":"buildTestString(int,java.util.Random)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"buildTextRenderers(Context, TextOutput, Looper, int, ArrayList)","url":"buildTextRenderers(android.content.Context,com.google.android.exoplayer2.text.TextOutput,android.os.Looper,int,java.util.ArrayList)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"buildTrackSelector(HostActivity)","url":"buildTrackSelector(com.google.android.exoplayer2.testutil.HostActivity)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"buildUpon()"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"buildUpon()"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"buildUpon()"},{"p":"com.google.android.exoplayer2","c":"Player.Commands","l":"buildUpon()"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource","l":"buildUpon()"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"buildUpon()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"buildUpon()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"buildUpon()"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer","l":"buildUpon()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"buildUpon()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"buildUponParameters()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"UrlTemplate","l":"buildUri(String, long, int, long)","url":"buildUri(java.lang.String,long,int,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"buildUtcTimingElement(String, String)","url":"buildUtcTimingElement(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"buildVideoRenderers(Context, int, MediaCodecSelector, boolean, Handler, VideoRendererEventListener, long, ArrayList)","url":"buildVideoRenderers(android.content.Context,int,com.google.android.exoplayer2.mediacodec.MediaCodecSelector,boolean,android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener,long,java.util.ArrayList)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BundledChunkExtractor","l":"BundledChunkExtractor(Extractor, int, Format)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.Extractor,int,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.source","c":"BundledExtractorsAdapter","l":"BundledExtractorsAdapter(ExtractorsFactory)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.ExtractorsFactory)"},{"p":"com.google.android.exoplayer2.source.hls","c":"BundledHlsMediaChunkExtractor","l":"BundledHlsMediaChunkExtractor(Extractor, Format, TimestampAdjuster)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.Extractor,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.util.TimestampAdjuster)"},{"p":"com.google.android.exoplayer2","c":"BundleListRetriever","l":"BundleListRetriever(List)","url":"%3Cinit%3E(java.util.List)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData.Segment","l":"BY_START_THEN_END_THEN_DIVISOR"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"byteAlign()"},{"p":"com.google.android.exoplayer2.upstream","c":"ByteArrayDataSink","l":"ByteArrayDataSink()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"ByteArrayDataSource","l":"ByteArrayDataSource(byte[])","url":"%3Cinit%3E(byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData.Segment","l":"byteOffset"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.SegmentBase","l":"byteRangeLength"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.SegmentBase","l":"byteRangeOffset"},{"p":"com.google.android.exoplayer2","c":"C","l":"BYTES_PER_FLOAT"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"MlltFrame","l":"bytesBetweenReference"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"MlltFrame","l":"bytesDeviations"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadProgress","l":"bytesDownloaded"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"bytesLeft()"},{"p":"com.google.android.exoplayer2.drm","c":"MediaDrmCallbackException","l":"bytesLoaded"},{"p":"com.google.android.exoplayer2.source","c":"LoadEventInfo","l":"bytesLoaded"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"bytesLoaded()"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"bytesLoaded()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor.AudioFormat","l":"bytesPerFrame"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData.Segment","l":"bytesRead"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceInputStream","l":"bytesRead()"},{"p":"com.google.android.exoplayer2.upstream","c":"BaseDataSource","l":"bytesTransferred(int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"CACHE_IGNORED_REASON_ERROR"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"CACHE_IGNORED_REASON_UNSET_LENGTH"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheWriter","l":"cache()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CachedRegionTracker","l":"CACHED_TO_END"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink","l":"CacheDataSink(Cache, long, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,long,int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink","l":"CacheDataSink(Cache, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink.CacheDataSinkException","l":"CacheDataSinkException(IOException)","url":"%3Cinit%3E(java.io.IOException)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSinkFactory","l":"CacheDataSinkFactory(Cache, long, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,long,int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSinkFactory","l":"CacheDataSinkFactory(Cache, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"CacheDataSource(Cache, DataSource, DataSource, DataSink, int, CacheDataSource.EventListener, CacheKeyFactory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSink,int,com.google.android.exoplayer2.upstream.cache.CacheDataSource.EventListener,com.google.android.exoplayer2.upstream.cache.CacheKeyFactory)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"CacheDataSource(Cache, DataSource, DataSource, DataSink, int, CacheDataSource.EventListener)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSink,int,com.google.android.exoplayer2.upstream.cache.CacheDataSource.EventListener)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"CacheDataSource(Cache, DataSource, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.DataSource,int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"CacheDataSource(Cache, DataSource)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.DataSource)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSourceFactory","l":"CacheDataSourceFactory(Cache, DataSource.Factory, DataSource.Factory, DataSink.Factory, int, CacheDataSource.EventListener, CacheKeyFactory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.upstream.DataSink.Factory,int,com.google.android.exoplayer2.upstream.cache.CacheDataSource.EventListener,com.google.android.exoplayer2.upstream.cache.CacheKeyFactory)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSourceFactory","l":"CacheDataSourceFactory(Cache, DataSource.Factory, DataSource.Factory, DataSink.Factory, int, CacheDataSource.EventListener)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.upstream.DataSink.Factory,int,com.google.android.exoplayer2.upstream.cache.CacheDataSource.EventListener)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSourceFactory","l":"CacheDataSourceFactory(Cache, DataSource.Factory, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.DataSource.Factory,int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSourceFactory","l":"CacheDataSourceFactory(Cache, DataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CachedRegionTracker","l":"CachedRegionTracker(Cache, String, ChunkIndex)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,java.lang.String,com.google.android.exoplayer2.extractor.ChunkIndex)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache.CacheException","l":"CacheException(String, Throwable)","url":"%3Cinit%3E(java.lang.String,java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache.CacheException","l":"CacheException(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache.CacheException","l":"CacheException(Throwable)","url":"%3Cinit%3E(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheSpan","l":"CacheSpan(String, long, long, long, File)","url":"%3Cinit%3E(java.lang.String,long,long,long,java.io.File)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheSpan","l":"CacheSpan(String, long, long)","url":"%3Cinit%3E(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheWriter","l":"CacheWriter(CacheDataSource, DataSpec, byte[], CacheWriter.ProgressListener)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.CacheDataSource,com.google.android.exoplayer2.upstream.DataSpec,byte[],com.google.android.exoplayer2.upstream.cache.CacheWriter.ProgressListener)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.SeekOperationParams","l":"calculateNextSearchBytePosition(long, long, long, long, long, long)","url":"calculateNextSearchBytePosition(long,long,long,long,long,long)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"calculateTargetBufferBytes(Renderer[], ExoTrackSelection[])","url":"calculateTargetBufferBytes(com.google.android.exoplayer2.Renderer[],com.google.android.exoplayer2.trackselection.ExoTrackSelection[])"},{"p":"com.google.android.exoplayer2.video.spherical","c":"CameraMotionRenderer","l":"CameraMotionRenderer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.ServerControl","l":"canBlockReload"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"cancel()"},{"p":"com.google.android.exoplayer2.ext.workmanager","c":"WorkManagerScheduler","l":"cancel()"},{"p":"com.google.android.exoplayer2.offline","c":"Downloader","l":"cancel()"},{"p":"com.google.android.exoplayer2.offline","c":"ProgressiveDownloader","l":"cancel()"},{"p":"com.google.android.exoplayer2.offline","c":"SegmentDownloader","l":"cancel()"},{"p":"com.google.android.exoplayer2.scheduler","c":"PlatformScheduler","l":"cancel()"},{"p":"com.google.android.exoplayer2.scheduler","c":"Scheduler","l":"cancel()"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer","l":"cancel()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheWriter","l":"cancel()"},{"p":"com.google.android.exoplayer2.util","c":"RunnableFutureTask","l":"cancel(boolean)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ContainerMediaChunk","l":"cancelLoad()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"DataChunk","l":"cancelLoad()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"InitializationChunk","l":"cancelLoad()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"SingleSampleMediaChunk","l":"cancelLoad()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaChunk","l":"cancelLoad()"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader.Loadable","l":"cancelLoad()"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"cancelLoad()"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"cancelLoading()"},{"p":"com.google.android.exoplayer2.util","c":"RunnableFutureTask","l":"cancelWork()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableNalUnitBitArray","l":"canReadBits(int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableNalUnitBitArray","l":"canReadExpGolombCodedNum()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"canReplace(DrmInitData.SchemeData)","url":"canReplace(com.google.android.exoplayer2.drm.DrmInitData.SchemeData)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"canReuseCodec(Format, Format)","url":"canReuseCodec(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"canReuseCodec(MediaCodecInfo, Format, Format)","url":"canReuseCodec(com.google.android.exoplayer2.mediacodec.MediaCodecInfo,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"canReuseCodec(MediaCodecInfo, Format, Format)","url":"canReuseCodec(com.google.android.exoplayer2.mediacodec.MediaCodecInfo,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"canReuseCodec(MediaCodecInfo, Format, Format)","url":"canReuseCodec(com.google.android.exoplayer2.mediacodec.MediaCodecInfo,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"canReuseDecoder(String, Format, Format)","url":"canReuseDecoder(java.lang.String,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Libgav1VideoRenderer","l":"canReuseDecoder(String, Format, Format)","url":"canReuseDecoder(java.lang.String,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"LibvpxVideoRenderer","l":"canReuseDecoder(String, Format, Format)","url":"canReuseDecoder(java.lang.String,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"canReuseDecoder(String, Format, Format)","url":"canReuseDecoder(java.lang.String,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"canSelectFormat(Format, int, long)","url":"canSelectFormat(com.google.android.exoplayer2.Format,int,long)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.ServerControl","l":"canSkipDateRanges"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"capabilities"},{"p":"com.google.android.exoplayer2.util","c":"IntArrayQueue","l":"capacity()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"capacity()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry.VariantInfo","l":"captionGroupId"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Variant","l":"captionGroupId"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"CaptionStyleCompat(int, int, int, int, int, Typeface)","url":"%3Cinit%3E(int,int,int,int,int,android.graphics.Typeface)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SmtaMetadataEntry","l":"captureFrameRate"},{"p":"com.google.android.exoplayer2.testutil","c":"CapturingAudioSink","l":"CapturingAudioSink(AudioSink)","url":"%3Cinit%3E(com.google.android.exoplayer2.audio.AudioSink)"},{"p":"com.google.android.exoplayer2.testutil","c":"CapturingRenderersFactory","l":"CapturingRenderersFactory(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"castNonNull(T)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"castNonNullTypeArray(T[])"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"CastPlayer(CastContext, MediaItemConverter, long, long)","url":"%3Cinit%3E(com.google.android.gms.cast.framework.CastContext,com.google.android.exoplayer2.ext.cast.MediaItemConverter,long,long)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"CastPlayer(CastContext, MediaItemConverter)","url":"%3Cinit%3E(com.google.android.gms.cast.framework.CastContext,com.google.android.exoplayer2.ext.cast.MediaItemConverter)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"CastPlayer(CastContext)","url":"%3Cinit%3E(com.google.android.gms.cast.framework.CastContext)"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea608Decoder","l":"Cea608Decoder(String, int, long)","url":"%3Cinit%3E(java.lang.String,int,long)"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea708Decoder","l":"Cea708Decoder(int, List)","url":"%3Cinit%3E(int,java.util.List)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"ceilDivide(int, int)","url":"ceilDivide(int,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"ceilDivide(long, long)","url":"ceilDivide(long,long)"},{"p":"com.google.android.exoplayer2","c":"C","l":"CENC_TYPE_cbc1"},{"p":"com.google.android.exoplayer2","c":"C","l":"CENC_TYPE_cbcs"},{"p":"com.google.android.exoplayer2","c":"C","l":"CENC_TYPE_cenc"},{"p":"com.google.android.exoplayer2","c":"C","l":"CENC_TYPE_cens"},{"p":"com.google.android.exoplayer2","c":"Format","l":"channelCount"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil.Config","l":"channelCount"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util.SyncFrameInfo","l":"channelCount"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util.SyncFrameInfo","l":"channelCount"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor.AudioFormat","l":"channelCount"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusDecoder","l":"channelCount"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil.Header","l":"channels"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"channels"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.VorbisIdHeader","l":"channels"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"ChapterFrame(String, int, int, long, long, Id3Frame[])","url":"%3Cinit%3E(java.lang.String,int,int,long,long,com.google.android.exoplayer2.metadata.id3.Id3Frame[])"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"chapterId"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterTocFrame","l":"ChapterTocFrame(String, boolean, boolean, String[], Id3Frame[])","url":"%3Cinit%3E(java.lang.String,boolean,boolean,java.lang.String[],com.google.android.exoplayer2.metadata.id3.Id3Frame[])"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacMetadataReader","l":"checkAndPeekStreamMarker(ExtractorInput)","url":"checkAndPeekStreamMarker(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacFrameReader","l":"checkAndReadFrameHeader(ParsableByteArray, FlacStreamMetadata, int, FlacFrameReader.SampleNumberHolder)","url":"checkAndReadFrameHeader(com.google.android.exoplayer2.util.ParsableByteArray,com.google.android.exoplayer2.extractor.FlacStreamMetadata,int,com.google.android.exoplayer2.extractor.FlacFrameReader.SampleNumberHolder)"},{"p":"com.google.android.exoplayer2.util","c":"Assertions","l":"checkArgument(boolean, Object)","url":"checkArgument(boolean,java.lang.Object)"},{"p":"com.google.android.exoplayer2.util","c":"Assertions","l":"checkArgument(boolean)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"checkCleartextTrafficPermitted(MediaItem...)","url":"checkCleartextTrafficPermitted(com.google.android.exoplayer2.MediaItem...)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorUtil","l":"checkContainerInput(boolean, String)","url":"checkContainerInput(boolean,java.lang.String)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacFrameReader","l":"checkFrameHeaderFromPeek(ExtractorInput, FlacStreamMetadata, int, FlacFrameReader.SampleNumberHolder)","url":"checkFrameHeaderFromPeek(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.FlacStreamMetadata,int,com.google.android.exoplayer2.extractor.FlacFrameReader.SampleNumberHolder)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil","l":"checkGlError()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunkIterator","l":"checkInBounds()"},{"p":"com.google.android.exoplayer2.util","c":"Assertions","l":"checkIndex(int, int, int)","url":"checkIndex(int,int,int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"checkInitialization()"},{"p":"com.google.android.exoplayer2.util","c":"Assertions","l":"checkMainThread()"},{"p":"com.google.android.exoplayer2.util","c":"Assertions","l":"checkNotEmpty(String, Object)","url":"checkNotEmpty(java.lang.String,java.lang.Object)"},{"p":"com.google.android.exoplayer2.util","c":"Assertions","l":"checkNotEmpty(String)","url":"checkNotEmpty(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"Assertions","l":"checkNotNull(T, Object)","url":"checkNotNull(T,java.lang.Object)"},{"p":"com.google.android.exoplayer2.util","c":"Assertions","l":"checkNotNull(T)"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"checkRequirements(Context)","url":"checkRequirements(android.content.Context)"},{"p":"com.google.android.exoplayer2.util","c":"Assertions","l":"checkState(boolean, Object)","url":"checkState(boolean,java.lang.Object)"},{"p":"com.google.android.exoplayer2.util","c":"Assertions","l":"checkState(boolean)"},{"p":"com.google.android.exoplayer2.util","c":"Assertions","l":"checkStateNotNull(T, Object)","url":"checkStateNotNull(T,java.lang.Object)"},{"p":"com.google.android.exoplayer2.util","c":"Assertions","l":"checkStateNotNull(T)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterTocFrame","l":"children"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkHolder","l":"chunk"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"Chunk(DataSource, DataSpec, int, Format, int, Object, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,int,com.google.android.exoplayer2.Format,int,java.lang.Object,long,long)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"chunkCount"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkHolder","l":"ChunkHolder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaChunk","l":"chunkIndex"},{"p":"com.google.android.exoplayer2.extractor","c":"ChunkIndex","l":"ChunkIndex(int[], long[], long[], long[])","url":"%3Cinit%3E(int[],long[],long[],long[])"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"ChunkSampleStream(int, int[], Format[], T, SequenceableLoader.Callback>, Allocator, long, DrmSessionManager, DrmSessionEventListener.EventDispatcher, LoadErrorHandlingPolicy, MediaSourceEventListener.EventDispatcher)","url":"%3Cinit%3E(int,int[],com.google.android.exoplayer2.Format[],T,com.google.android.exoplayer2.source.SequenceableLoader.Callback,com.google.android.exoplayer2.upstream.Allocator,long,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher,com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy,com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2","c":"FormatHolder","l":"clear()"},{"p":"com.google.android.exoplayer2.decoder","c":"Buffer","l":"clear()"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"clear()"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleOutputBuffer","l":"clear()"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"clear()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkHolder","l":"clear()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"clear()"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleOutputBuffer","l":"clear()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.RequestProperties","l":"clear()"},{"p":"com.google.android.exoplayer2.util","c":"IntArrayQueue","l":"clear()"},{"p":"com.google.android.exoplayer2.util","c":"TimedValueQueue","l":"clear()"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"clear(Handler, Runnable)","url":"clear(android.os.Handler,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.drm","c":"HttpMediaDrmCallback","l":"clearAllKeyRequestProperties()"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"clearAllRequestProperties()"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"clearAllRequestProperties()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"clearAllRequestProperties()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource","l":"clearAllRequestProperties()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.RequestProperties","l":"clearAndSet(Map)","url":"clearAndSet(java.util.Map)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioComponent","l":"clearAuxEffectInfo()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"clearAuxEffectInfo()"},{"p":"com.google.android.exoplayer2.decoder","c":"CryptoInfo","l":"clearBlocks"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput.CryptoData","l":"clearBlocks"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"clearCameraMotionListener(CameraMotionListener)","url":"clearCameraMotionListener(com.google.android.exoplayer2.video.spherical.CameraMotionListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"clearCameraMotionListener(CameraMotionListener)","url":"clearCameraMotionListener(com.google.android.exoplayer2.video.spherical.CameraMotionListener)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecUtil","l":"clearDecoderInfoCache()"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"clearFatalError()"},{"p":"com.google.android.exoplayer2.decoder","c":"Buffer","l":"clearFlag(int)"},{"p":"com.google.android.exoplayer2","c":"C","l":"CLEARKEY_UUID"},{"p":"com.google.android.exoplayer2.drm","c":"HttpMediaDrmCallback","l":"clearKeyRequestProperty(String)","url":"clearKeyRequestProperty(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"clearMediaItems()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"clearMediaItems()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"clearMediaItems()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"clearMediaItems()"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.ClearMediaItems","l":"ClearMediaItems(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil","l":"clearPrefixFlags(boolean[])"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"clearRequestProperty(String)","url":"clearRequestProperty(java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"clearRequestProperty(String)","url":"clearRequestProperty(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"clearRequestProperty(String)","url":"clearRequestProperty(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource","l":"clearRequestProperty(String)","url":"clearRequestProperty(java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"clearSelectionOverride(int, TrackGroupArray)","url":"clearSelectionOverride(int,com.google.android.exoplayer2.source.TrackGroupArray)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"clearSelectionOverrides()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"clearSelectionOverrides(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.CleartextNotPermittedException","l":"CleartextNotPermittedException(IOException, DataSpec)","url":"%3Cinit%3E(java.io.IOException,com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorOutput","l":"clearTrackOutputs()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"clearTrackSelections(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"clearVideoFrameMetadataListener(VideoFrameMetadataListener)","url":"clearVideoFrameMetadataListener(com.google.android.exoplayer2.video.VideoFrameMetadataListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"clearVideoFrameMetadataListener(VideoFrameMetadataListener)","url":"clearVideoFrameMetadataListener(com.google.android.exoplayer2.video.VideoFrameMetadataListener)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"clearVideoSizeConstraints()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"clearVideoSizeConstraints()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"clearVideoSurface()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"clearVideoSurface()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"clearVideoSurface()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"clearVideoSurface()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"clearVideoSurface()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"clearVideoSurface()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"clearVideoSurface()"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.ClearVideoSurface","l":"ClearVideoSurface(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"clearVideoSurface(Surface)","url":"clearVideoSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"clearVideoSurface(Surface)","url":"clearVideoSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"clearVideoSurface(Surface)","url":"clearVideoSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"clearVideoSurface(Surface)","url":"clearVideoSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"clearVideoSurface(Surface)","url":"clearVideoSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"clearVideoSurface(Surface)","url":"clearVideoSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"clearVideoSurfaceHolder(SurfaceHolder)","url":"clearVideoSurfaceHolder(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"clearVideoSurfaceHolder(SurfaceHolder)","url":"clearVideoSurfaceHolder(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"clearVideoSurfaceHolder(SurfaceHolder)","url":"clearVideoSurfaceHolder(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"clearVideoSurfaceHolder(SurfaceHolder)","url":"clearVideoSurfaceHolder(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"clearVideoSurfaceHolder(SurfaceHolder)","url":"clearVideoSurfaceHolder(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"clearVideoSurfaceHolder(SurfaceHolder)","url":"clearVideoSurfaceHolder(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"clearVideoSurfaceView(SurfaceView)","url":"clearVideoSurfaceView(android.view.SurfaceView)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"clearVideoSurfaceView(SurfaceView)","url":"clearVideoSurfaceView(android.view.SurfaceView)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"clearVideoSurfaceView(SurfaceView)","url":"clearVideoSurfaceView(android.view.SurfaceView)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"clearVideoSurfaceView(SurfaceView)","url":"clearVideoSurfaceView(android.view.SurfaceView)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"clearVideoSurfaceView(SurfaceView)","url":"clearVideoSurfaceView(android.view.SurfaceView)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"clearVideoSurfaceView(SurfaceView)","url":"clearVideoSurfaceView(android.view.SurfaceView)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"clearVideoTextureView(TextureView)","url":"clearVideoTextureView(android.view.TextureView)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"clearVideoTextureView(TextureView)","url":"clearVideoTextureView(android.view.TextureView)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"clearVideoTextureView(TextureView)","url":"clearVideoTextureView(android.view.TextureView)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"clearVideoTextureView(TextureView)","url":"clearVideoTextureView(android.view.TextureView)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"clearVideoTextureView(TextureView)","url":"clearVideoTextureView(android.view.TextureView)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"clearVideoTextureView(TextureView)","url":"clearVideoTextureView(android.view.TextureView)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"clearViewportSizeConstraints()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"clearViewportSizeConstraints()"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"clearWindowColor()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunk","l":"clippedEndTimeUs"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunk","l":"clippedStartTimeUs"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"ClippingMediaPeriod(MediaPeriod, boolean, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaPeriod,boolean,long,long)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource","l":"ClippingMediaSource(MediaSource, long, long, boolean, boolean, boolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaSource,long,long,boolean,boolean,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource","l":"ClippingMediaSource(MediaSource, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaSource,long,long)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource","l":"ClippingMediaSource(MediaSource, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaSource,long)"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"clippingProperties"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPayloadFormat","l":"clockRate"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder","l":"cloneAndClear()"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.DefaultShuffleOrder","l":"cloneAndClear()"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.UnshuffledShuffleOrder","l":"cloneAndClear()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeShuffleOrder","l":"cloneAndClear()"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder","l":"cloneAndInsert(int, int)","url":"cloneAndInsert(int,int)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.DefaultShuffleOrder","l":"cloneAndInsert(int, int)","url":"cloneAndInsert(int,int)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.UnshuffledShuffleOrder","l":"cloneAndInsert(int, int)","url":"cloneAndInsert(int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeShuffleOrder","l":"cloneAndInsert(int, int)","url":"cloneAndInsert(int,int)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder","l":"cloneAndRemove(int, int)","url":"cloneAndRemove(int,int)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.DefaultShuffleOrder","l":"cloneAndRemove(int, int)","url":"cloneAndRemove(int,int)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.UnshuffledShuffleOrder","l":"cloneAndRemove(int, int)","url":"cloneAndRemove(int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeShuffleOrder","l":"cloneAndRemove(int, int)","url":"cloneAndRemove(int,int)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"close()"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.ext.rtmp","c":"RtmpDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"close()"},{"p":"com.google.android.exoplayer2.testutil","c":"FailOnCloseDataSink","l":"close()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"AssetDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"ByteArrayDataSink","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"ByteArrayDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"ContentDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSchemeDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSink","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceInputStream","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"DummyDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"PriorityDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"RawResourceDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"ResolvingDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"StatsDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"TeeDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream","c":"UdpDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink","l":"close()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesCipherDataSink","l":"close()"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesCipherDataSource","l":"close()"},{"p":"com.google.android.exoplayer2.util","c":"ConditionVariable","l":"close()"},{"p":"com.google.android.exoplayer2.util","c":"ReusableBufferedOutputStream","l":"close()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"closedCaptions"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"closeQuietly(Closeable)","url":"closeQuietly(java.io.Closeable)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"closeQuietly(DataSource)","url":"closeQuietly(com.google.android.exoplayer2.upstream.DataSource)"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"closeSession(byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"closeSession(byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"closeSession(byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"closeSession(byte[])"},{"p":"com.google.android.exoplayer2","c":"SeekParameters","l":"CLOSEST_SYNC"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"CODEC_OPERATING_RATE_UNSET"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter.Configuration","l":"codecInfo"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecDecoderException","l":"codecInfo"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer.DecoderInitializationException","l":"codecInfo"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer.CodecMaxValues","l":"CodecMaxValues(int, int, int)","url":"%3Cinit%3E(int,int,int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"codecMimeType"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"codecNeedsSetOutputSurfaceWorkaround(String)","url":"codecNeedsSetOutputSurfaceWorkaround(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"codecs"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil.Config","l":"codecs"},{"p":"com.google.android.exoplayer2.video","c":"AvcConfig","l":"codecs"},{"p":"com.google.android.exoplayer2.video","c":"DolbyVisionConfig","l":"codecs"},{"p":"com.google.android.exoplayer2.video","c":"HevcConfig","l":"codecs"},{"p":"com.google.android.exoplayer2","c":"C","l":"COLOR_RANGE_FULL"},{"p":"com.google.android.exoplayer2","c":"C","l":"COLOR_RANGE_LIMITED"},{"p":"com.google.android.exoplayer2","c":"C","l":"COLOR_SPACE_BT2020"},{"p":"com.google.android.exoplayer2","c":"C","l":"COLOR_SPACE_BT601"},{"p":"com.google.android.exoplayer2","c":"C","l":"COLOR_SPACE_BT709"},{"p":"com.google.android.exoplayer2","c":"C","l":"COLOR_TRANSFER_HLG"},{"p":"com.google.android.exoplayer2","c":"C","l":"COLOR_TRANSFER_SDR"},{"p":"com.google.android.exoplayer2","c":"C","l":"COLOR_TRANSFER_ST2084"},{"p":"com.google.android.exoplayer2","c":"Format","l":"colorInfo"},{"p":"com.google.android.exoplayer2.video","c":"ColorInfo","l":"ColorInfo(int, int, int, byte[])","url":"%3Cinit%3E(int,int,int,byte[])"},{"p":"com.google.android.exoplayer2.video","c":"ColorInfo","l":"colorRange"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"colors"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"colorspace"},{"p":"com.google.android.exoplayer2.video","c":"ColorInfo","l":"colorSpace"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"COLORSPACE_BT2020"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"COLORSPACE_BT601"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"COLORSPACE_BT709"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"COLORSPACE_UNKNOWN"},{"p":"com.google.android.exoplayer2.video","c":"ColorInfo","l":"colorTransfer"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_ADJUST_DEVICE_VOLUME"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_CHANGE_MEDIA_ITEMS"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_GET_AUDIO_ATTRIBUTES"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_GET_CURRENT_MEDIA_ITEM"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_GET_DEVICE_VOLUME"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_GET_MEDIA_ITEMS_METADATA"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_GET_TEXT"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_GET_TIMELINE"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_GET_VOLUME"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_INVALID"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor","l":"COMMAND_MOVE_QUEUE_ITEM"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_PLAY_PAUSE"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_PREPARE_STOP"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SEEK_BACK"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SEEK_FORWARD"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SEEK_IN_CURRENT_WINDOW"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SEEK_TO_DEFAULT_POSITION"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SEEK_TO_NEXT"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SEEK_TO_NEXT_WINDOW"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SEEK_TO_PREVIOUS"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SEEK_TO_PREVIOUS_WINDOW"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SEEK_TO_WINDOW"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SET_DEVICE_VOLUME"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SET_MEDIA_ITEMS_METADATA"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SET_REPEAT_MODE"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SET_SHUFFLE_MODE"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SET_SPEED_AND_PITCH"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SET_VIDEO_SURFACE"},{"p":"com.google.android.exoplayer2","c":"Player","l":"COMMAND_SET_VOLUME"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"PrivateCommand","l":"commandBytes"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"CommentFrame","l":"CommentFrame(String, String, String)","url":"%3Cinit%3E(java.lang.String,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.CommentHeader","l":"CommentHeader(String, String[], int)","url":"%3Cinit%3E(java.lang.String,java.lang.String[],int)"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.CommentHeader","l":"comments"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"commitFile(File, long)","url":"commitFile(java.io.File,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"commitFile(File, long)","url":"commitFile(java.io.File,long)"},{"p":"com.google.android.exoplayer2","c":"C","l":"COMMON_PSSH_UUID"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"compare(DrmInitData.SchemeData, DrmInitData.SchemeData)","url":"compare(com.google.android.exoplayer2.drm.DrmInitData.SchemeData,com.google.android.exoplayer2.drm.DrmInitData.SchemeData)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"compareLong(long, long)","url":"compareLong(long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheSpan","l":"compareTo(CacheSpan)","url":"compareTo(com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.AudioTrackScore","l":"compareTo(DefaultTrackSelector.AudioTrackScore)","url":"compareTo(com.google.android.exoplayer2.trackselection.DefaultTrackSelector.AudioTrackScore)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.OtherTrackScore","l":"compareTo(DefaultTrackSelector.OtherTrackScore)","url":"compareTo(com.google.android.exoplayer2.trackselection.DefaultTrackSelector.OtherTrackScore)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.TextTrackScore","l":"compareTo(DefaultTrackSelector.TextTrackScore)","url":"compareTo(com.google.android.exoplayer2.trackselection.DefaultTrackSelector.TextTrackScore)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.VideoTrackScore","l":"compareTo(DefaultTrackSelector.VideoTrackScore)","url":"compareTo(com.google.android.exoplayer2.trackselection.DefaultTrackSelector.VideoTrackScore)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock.HandlerMessage","l":"compareTo(FakeClock.HandlerMessage)","url":"compareTo(com.google.android.exoplayer2.testutil.FakeClock.HandlerMessage)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.SegmentBase","l":"compareTo(Long)","url":"compareTo(java.lang.Long)"},{"p":"com.google.android.exoplayer2.offline","c":"SegmentDownloader.Segment","l":"compareTo(SegmentDownloader.Segment)","url":"compareTo(com.google.android.exoplayer2.offline.SegmentDownloader.Segment)"},{"p":"com.google.android.exoplayer2.offline","c":"StreamKey","l":"compareTo(StreamKey)","url":"compareTo(com.google.android.exoplayer2.offline.StreamKey)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"compilation"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"UrlTemplate","l":"compile(String)","url":"compile(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil","l":"compileProgram(String, String)","url":"compileProgram(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil","l":"compileProgram(String[], String[])","url":"compileProgram(java.lang.String[],java.lang.String[])"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"componentSpliceList"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.Event","l":"componentSpliceList"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand.ComponentSplice","l":"componentSplicePlaybackPositionUs"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand.ComponentSplice","l":"componentSplicePts"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand.ComponentSplice","l":"componentTag"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.ComponentSplice","l":"componentTag"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"composer"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"CompositeMediaSource()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source","c":"CompositeSequenceableLoader","l":"CompositeSequenceableLoader(SequenceableLoader[])","url":"%3Cinit%3E(com.google.android.exoplayer2.source.SequenceableLoader[])"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"ConcatenatingMediaSource(boolean, boolean, ShuffleOrder, MediaSource...)","url":"%3Cinit%3E(boolean,boolean,com.google.android.exoplayer2.source.ShuffleOrder,com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"ConcatenatingMediaSource(boolean, MediaSource...)","url":"%3Cinit%3E(boolean,com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"ConcatenatingMediaSource(boolean, ShuffleOrder, MediaSource...)","url":"%3Cinit%3E(boolean,com.google.android.exoplayer2.source.ShuffleOrder,com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"ConcatenatingMediaSource(MediaSource...)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.util","c":"ConditionVariable","l":"ConditionVariable()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.util","c":"ConditionVariable","l":"ConditionVariable(Clock)","url":"%3Cinit%3E(com.google.android.exoplayer2.util.Clock)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"conductor"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts","l":"configs()"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts","l":"configsNoSniffing()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter.Configuration","l":"Configuration(MediaCodecInfo, MediaFormat, Format, Surface, MediaCrypto, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.mediacodec.MediaCodecInfo,android.media.MediaFormat,com.google.android.exoplayer2.Format,android.view.Surface,android.media.MediaCrypto,int)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.ConfigurationException","l":"ConfigurationException(String, Format)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.ConfigurationException","l":"ConfigurationException(Throwable, Format)","url":"%3Cinit%3E(java.lang.Throwable,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor","l":"configure(AudioProcessor.AudioFormat)","url":"configure(com.google.android.exoplayer2.audio.AudioProcessor.AudioFormat)"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"configure(AudioProcessor.AudioFormat)","url":"configure(com.google.android.exoplayer2.audio.AudioProcessor.AudioFormat)"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"configure(AudioProcessor.AudioFormat)","url":"configure(com.google.android.exoplayer2.audio.AudioProcessor.AudioFormat)"},{"p":"com.google.android.exoplayer2.ext.gvr","c":"GvrAudioProcessor","l":"configure(AudioProcessor.AudioFormat)","url":"configure(com.google.android.exoplayer2.audio.AudioProcessor.AudioFormat)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"configure(Format, int, int[])","url":"configure(com.google.android.exoplayer2.Format,int,int[])"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"configure(Format, int, int[])","url":"configure(com.google.android.exoplayer2.Format,int,int[])"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"configure(Format, int, int[])","url":"configure(com.google.android.exoplayer2.Format,int,int[])"},{"p":"com.google.android.exoplayer2.testutil","c":"CapturingAudioSink","l":"configure(Format, int, int[])","url":"configure(com.google.android.exoplayer2.Format,int,int[])"},{"p":"com.google.android.exoplayer2.extractor","c":"ConstantBitrateSeekMap","l":"ConstantBitrateSeekMap(long, long, int, int)","url":"%3Cinit%3E(long,long,int,int)"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"constraintsFlagsAndReservedZero2Bits"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"constrainValue(float, float, float)","url":"constrainValue(float,float,float)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"constrainValue(int, int, int)","url":"constrainValue(int,int,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"constrainValue(long, long, long)","url":"constrainValue(long,long,long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"DataChunk","l":"consume(byte[], int)","url":"consume(byte[],int)"},{"p":"com.google.android.exoplayer2.extractor","c":"CeaUtil","l":"consume(long, ParsableByteArray, TrackOutput[])","url":"consume(long,com.google.android.exoplayer2.util.ParsableByteArray,com.google.android.exoplayer2.extractor.TrackOutput[])"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"SeiReader","l":"consume(long, ParsableByteArray)","url":"consume(long,com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PesReader","l":"consume(ParsableByteArray, int)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"SectionReader","l":"consume(ParsableByteArray, int)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader","l":"consume(ParsableByteArray, int)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray,int)"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","c":"RtpAc3Reader","l":"consume(ParsableByteArray, long, int, boolean)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray,long,int,boolean)"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","c":"RtpPayloadReader","l":"consume(ParsableByteArray, long, int, boolean)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray,long,int,boolean)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Reader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Reader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsReader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DtsReader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DvbSubtitleReader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"ElementaryStreamReader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H262Reader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H263Reader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H264Reader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H265Reader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Id3Reader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"LatmReader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"MpegAudioReader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PassthroughSectionPayloadReader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"SectionPayloadReader","l":"consume(ParsableByteArray)","url":"consume(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor","c":"CeaUtil","l":"consumeCcData(long, ParsableByteArray, TrackOutput[])","url":"consumeCcData(long,com.google.android.exoplayer2.util.ParsableByteArray,com.google.android.exoplayer2.extractor.TrackOutput[])"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ContainerMediaChunk","l":"ContainerMediaChunk(DataSource, DataSpec, Format, int, Object, long, long, long, long, long, int, long, ChunkExtractor)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,com.google.android.exoplayer2.Format,int,java.lang.Object,long,long,long,long,long,int,long,com.google.android.exoplayer2.source.chunk.ChunkExtractor)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"containerMimeType"},{"p":"com.google.android.exoplayer2","c":"Player.Commands","l":"contains(int)"},{"p":"com.google.android.exoplayer2","c":"Player.Events","l":"contains(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.Events","l":"contains(int)"},{"p":"com.google.android.exoplayer2.util","c":"FlagSet","l":"contains(int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"contains(Object[], Object)","url":"contains(java.lang.Object[],java.lang.Object)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadata","l":"contains(String)","url":"contains(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"DefaultContentMetadata","l":"contains(String)","url":"contains(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"Player.Events","l":"containsAny(int...)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.Events","l":"containsAny(int...)"},{"p":"com.google.android.exoplayer2.util","c":"FlagSet","l":"containsAny(int...)"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"containsCodecsCorrespondingToMimeType(String, String)","url":"containsCodecsCorrespondingToMimeType(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.SelectionOverride","l":"containsTrack(int)"},{"p":"com.google.android.exoplayer2","c":"C","l":"CONTENT_TYPE_MOVIE"},{"p":"com.google.android.exoplayer2","c":"C","l":"CONTENT_TYPE_MUSIC"},{"p":"com.google.android.exoplayer2","c":"C","l":"CONTENT_TYPE_SONIFICATION"},{"p":"com.google.android.exoplayer2","c":"C","l":"CONTENT_TYPE_SPEECH"},{"p":"com.google.android.exoplayer2","c":"C","l":"CONTENT_TYPE_UNKNOWN"},{"p":"com.google.android.exoplayer2.upstream","c":"ContentDataSource","l":"ContentDataSource(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.upstream","c":"ContentDataSource.ContentDataSourceException","l":"ContentDataSourceException(IOException, int)","url":"%3Cinit%3E(java.io.IOException,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"ContentDataSource.ContentDataSourceException","l":"ContentDataSourceException(IOException)","url":"%3Cinit%3E(java.io.IOException)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"contentDurationUs"},{"p":"com.google.android.exoplayer2","c":"ParserException","l":"contentIsMalformed"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"contentLength"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.SingleSegmentRepresentation","l":"contentLength"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadataMutations","l":"ContentMetadataMutations()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"contentPositionMs"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"contentResumeOffsetUs"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes","l":"contentType"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.InvalidContentTypeException","l":"contentType"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"continueLoading(long)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeSequenceableLoader","l":"continueLoading(long)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"continueLoading(long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"continueLoading(long)"},{"p":"com.google.android.exoplayer2.source","c":"SequenceableLoader","l":"continueLoading(long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"continueLoading(long)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"continueLoading(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"continueLoading(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"continueLoading(long)"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","c":"AppInfoTable","l":"CONTROL_CODE_AUTOSTART"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","c":"AppInfoTable","l":"CONTROL_CODE_PRESENT"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","c":"AppInfoTable","l":"controlCode"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor.MediaDescriptionConverter","l":"convert(MediaDescriptionCompat)","url":"convert(android.support.v4.media.MediaDescriptionCompat)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"DefaultMediaItemConverter","l":"convertToExoPlayerMediaItem(MediaItem)","url":"convertToExoPlayerMediaItem(androidx.media2.common.MediaItem)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"MediaItemConverter","l":"convertToExoPlayerMediaItem(MediaItem)","url":"convertToExoPlayerMediaItem(androidx.media2.common.MediaItem)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"DefaultMediaItemConverter","l":"convertToMedia2MediaItem(MediaItem)","url":"convertToMedia2MediaItem(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"MediaItemConverter","l":"convertToMedia2MediaItem(MediaItem)","url":"convertToMedia2MediaItem(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"copy(Format[])","url":"copy(com.google.android.exoplayer2.Format[])"},{"p":"com.google.android.exoplayer2.offline","c":"FilterableManifest","l":"copy(List)","url":"copy(java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"copy(List)","url":"copy(java.util.List)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"copy(List)","url":"copy(java.util.List)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"copy(List)","url":"copy(java.util.List)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest","l":"copy(List)","url":"copy(java.util.List)"},{"p":"com.google.android.exoplayer2.util","c":"ListenerSet","l":"copy(Looper, ListenerSet.IterationFinishedEvent)","url":"copy(android.os.Looper,com.google.android.exoplayer2.util.ListenerSet.IterationFinishedEvent)"},{"p":"com.google.android.exoplayer2.util","c":"CopyOnWriteMultiset","l":"CopyOnWriteMultiset()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ProgramInformation","l":"copyright"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"copyWith(long, int)","url":"copyWith(long,int)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.Part","l":"copyWith(long, int)","url":"copyWith(long,int)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.Segment","l":"copyWith(long, int)","url":"copyWith(long,int)"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata","l":"copyWithAppendedEntries(Metadata.Entry...)","url":"copyWithAppendedEntries(com.google.android.exoplayer2.metadata.Metadata.Entry...)"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata","l":"copyWithAppendedEntriesFrom(Metadata)","url":"copyWithAppendedEntriesFrom(com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"copyWithBitrate(int)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"copyWithData(byte[])"},{"p":"com.google.android.exoplayer2","c":"Format","l":"copyWithDrmInitData(DrmInitData)","url":"copyWithDrmInitData(com.google.android.exoplayer2.drm.DrmInitData)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"copyWithEndTag()"},{"p":"com.google.android.exoplayer2","c":"Format","l":"copyWithExoMediaCryptoType(Class)","url":"copyWithExoMediaCryptoType(java.lang.Class)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"copyWithFormat(Format)","url":"copyWithFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Variant","l":"copyWithFormat(Format)","url":"copyWithFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"copyWithFrameRate(float)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"copyWithGaplessInfo(int, int)","url":"copyWithGaplessInfo(int,int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"copyWithId(String)","url":"copyWithId(java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"copyWithKeySetId(byte[])"},{"p":"com.google.android.exoplayer2","c":"Format","l":"copyWithLabel(String)","url":"copyWithLabel(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"copyWithManifestFormatInfo(Format)","url":"copyWithManifestFormatInfo(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"copyWithMaxInputSize(int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"copyWithMergedRequest(DownloadRequest)","url":"copyWithMergedRequest(com.google.android.exoplayer2.offline.DownloadRequest)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"copyWithMetadata(Metadata)","url":"copyWithMetadata(com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"DefaultContentMetadata","l":"copyWithMutationsApplied(ContentMetadataMutations)","url":"copyWithMutationsApplied(com.google.android.exoplayer2.upstream.cache.ContentMetadataMutations)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"copyWithPeriodUid(Object)","url":"copyWithPeriodUid(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource.MediaPeriodId","l":"copyWithPeriodUid(Object)","url":"copyWithPeriodUid(java.lang.Object)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"copyWithPictureFrames(List)","url":"copyWithPictureFrames(java.util.List)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"copyWithSchemeType(String)","url":"copyWithSchemeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"copyWithSeekTable(FlacStreamMetadata.SeekTable)","url":"copyWithSeekTable(com.google.android.exoplayer2.extractor.FlacStreamMetadata.SeekTable)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"copyWithSubsampleOffsetUs(long)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"copyWithVideoSize(int, int)","url":"copyWithVideoSize(int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"copyWithVorbisComments(List)","url":"copyWithVorbisComments(java.util.List)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"copyWithWindowSequenceNumber(long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource.MediaPeriodId","l":"copyWithWindowSequenceNumber(long)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"count"},{"p":"com.google.android.exoplayer2.util","c":"CopyOnWriteMultiset","l":"count(E)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"crc32(byte[], int, int, int)","url":"crc32(byte[],int,int,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"crc8(byte[], int, int, int)","url":"crc8(byte[],int,int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts.ExtractorFactory","l":"create()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod.TrackDataFactory","l":"create(Format, MediaSource.MediaPeriodId)","url":"create(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"create(int, int, int)","url":"create(int,int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput.Factory","l":"create(int, int)","url":"create(int,int)"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"create(int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter.Factory","l":"createAdapter(MediaCodecAdapter.Configuration)","url":"createAdapter(com.google.android.exoplayer2.mediacodec.MediaCodecAdapter.Configuration)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter.Factory","l":"createAdapter(MediaCodecAdapter.Configuration)","url":"createAdapter(com.google.android.exoplayer2.mediacodec.MediaCodecAdapter.Configuration)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionUtil.AdaptiveTrackSelectionFactory","l":"createAdaptiveTrackSelection(ExoTrackSelection.Definition)","url":"createAdaptiveTrackSelection(com.google.android.exoplayer2.trackselection.ExoTrackSelection.Definition)"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection.Factory","l":"createAdaptiveTrackSelection(TrackGroup, int[], int, BandwidthMeter, ImmutableList)","url":"createAdaptiveTrackSelection(com.google.android.exoplayer2.source.TrackGroup,int[],int,com.google.android.exoplayer2.upstream.BandwidthMeter,com.google.common.collect.ImmutableList)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"createAdPlaybackState(int, long...)","url":"createAdPlaybackState(int,long...)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"createAudioSampleFormat(String, String, String, int, int, int, int, int, List, DrmInitData, int, String)","url":"createAudioSampleFormat(java.lang.String,java.lang.String,java.lang.String,int,int,int,int,int,java.util.List,com.google.android.exoplayer2.drm.DrmInitData,int,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"createAudioSampleFormat(String, String, String, int, int, int, int, List, DrmInitData, int, String)","url":"createAudioSampleFormat(java.lang.String,java.lang.String,java.lang.String,int,int,int,int,java.util.List,com.google.android.exoplayer2.drm.DrmInitData,int,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil","l":"createBuffer(float[])"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil","l":"createBuffer(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"createByteArray(int...)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"createByteList(int...)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource.Factory","l":"createChunkSource(ExoTrackSelection, long, TransferListener)","url":"createChunkSource(com.google.android.exoplayer2.trackselection.ExoTrackSelection,long,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource.Factory","l":"createChunkSource(LoaderErrorThrower, SsManifest, int, ExoTrackSelection, TransferListener)","url":"createChunkSource(com.google.android.exoplayer2.upstream.LoaderErrorThrower,com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest,int,com.google.android.exoplayer2.trackselection.ExoTrackSelection,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsChunkSource.Factory","l":"createChunkSource(LoaderErrorThrower, SsManifest, int, ExoTrackSelection, TransferListener)","url":"createChunkSource(com.google.android.exoplayer2.upstream.LoaderErrorThrower,com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest,int,com.google.android.exoplayer2.trackselection.ExoTrackSelection,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter.Factory","l":"createCodec(MediaCodecAdapter.Configuration)","url":"createCodec(com.google.android.exoplayer2.mediacodec.MediaCodecAdapter.Configuration)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeSequenceableLoaderFactory","l":"createCompositeSequenceableLoader(SequenceableLoader...)","url":"createCompositeSequenceableLoader(com.google.android.exoplayer2.source.SequenceableLoader...)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultCompositeSequenceableLoaderFactory","l":"createCompositeSequenceableLoader(SequenceableLoader...)","url":"createCompositeSequenceableLoader(com.google.android.exoplayer2.source.SequenceableLoader...)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"createContainerFormat(String, String, String, String, String, int, int, int, String)","url":"createContainerFormat(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,int,int,int,java.lang.String)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultMediaDescriptionAdapter","l":"createCurrentContentIntent(Player)","url":"createCurrentContentIntent(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.MediaDescriptionAdapter","l":"createCurrentContentIntent(Player)","url":"createCurrentContentIntent(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.CustomActionReceiver","l":"createCustomActions(Context, int)","url":"createCustomActions(android.content.Context,int)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashChunkSource.Factory","l":"createDashChunkSource(LoaderErrorThrower, DashManifest, BaseUrlExclusionList, int, int[], ExoTrackSelection, int, long, boolean, List, PlayerEmsgHandler.PlayerTrackEmsgHandler, TransferListener)","url":"createDashChunkSource(com.google.android.exoplayer2.upstream.LoaderErrorThrower,com.google.android.exoplayer2.source.dash.manifest.DashManifest,com.google.android.exoplayer2.source.dash.BaseUrlExclusionList,int,int[],com.google.android.exoplayer2.trackselection.ExoTrackSelection,int,long,boolean,java.util.List,com.google.android.exoplayer2.source.dash.PlayerEmsgHandler.PlayerTrackEmsgHandler,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.Factory","l":"createDashChunkSource(LoaderErrorThrower, DashManifest, BaseUrlExclusionList, int, int[], ExoTrackSelection, int, long, boolean, List, PlayerEmsgHandler.PlayerTrackEmsgHandler, TransferListener)","url":"createDashChunkSource(com.google.android.exoplayer2.upstream.LoaderErrorThrower,com.google.android.exoplayer2.source.dash.manifest.DashManifest,com.google.android.exoplayer2.source.dash.BaseUrlExclusionList,int,int[],com.google.android.exoplayer2.trackselection.ExoTrackSelection,int,long,boolean,java.util.List,com.google.android.exoplayer2.source.dash.PlayerEmsgHandler.PlayerTrackEmsgHandler,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveDataSet.Factory","l":"createDataSet(TrackGroup, long)","url":"createDataSet(com.google.android.exoplayer2.source.TrackGroup,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FailOnCloseDataSink.Factory","l":"createDataSink()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSink.Factory","l":"createDataSink()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink.Factory","l":"createDataSink()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSinkFactory","l":"createDataSink()"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource.Factory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.ext.rtmp","c":"RtmpDataSource.Factory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.ext.rtmp","c":"RtmpDataSourceFactory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource.Factory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSource.Factory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSourceFactory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource.Factory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSource.Factory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSourceFactory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.BaseFactory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.Factory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.upstream","c":"PriorityDataSourceFactory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.upstream","c":"ResolvingDataSource.Factory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSourceFactory","l":"createDataSource()"},{"p":"com.google.android.exoplayer2.source.hls","c":"DefaultHlsDataSourceFactory","l":"createDataSource(int)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsDataSourceFactory","l":"createDataSource(int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"createDataSourceForDownloading()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"createDataSourceForRemovingDownload()"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"createDataSourceInternal(HttpDataSource.RequestProperties)","url":"createDataSourceInternal(com.google.android.exoplayer2.upstream.HttpDataSource.RequestProperties)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSourceFactory","l":"createDataSourceInternal(HttpDataSource.RequestProperties)","url":"createDataSourceInternal(com.google.android.exoplayer2.upstream.HttpDataSource.RequestProperties)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSourceFactory","l":"createDataSourceInternal(HttpDataSource.RequestProperties)","url":"createDataSourceInternal(com.google.android.exoplayer2.upstream.HttpDataSource.RequestProperties)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.BaseFactory","l":"createDataSourceInternal(HttpDataSource.RequestProperties)","url":"createDataSourceInternal(com.google.android.exoplayer2.upstream.HttpDataSource.RequestProperties)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"createDecoder(Format, ExoMediaCrypto)","url":"createDecoder(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.drm.ExoMediaCrypto)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Libgav1VideoRenderer","l":"createDecoder(Format, ExoMediaCrypto)","url":"createDecoder(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.drm.ExoMediaCrypto)"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegAudioRenderer","l":"createDecoder(Format, ExoMediaCrypto)","url":"createDecoder(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.drm.ExoMediaCrypto)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"LibflacAudioRenderer","l":"createDecoder(Format, ExoMediaCrypto)","url":"createDecoder(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.drm.ExoMediaCrypto)"},{"p":"com.google.android.exoplayer2.ext.opus","c":"LibopusAudioRenderer","l":"createDecoder(Format, ExoMediaCrypto)","url":"createDecoder(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.drm.ExoMediaCrypto)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"LibvpxVideoRenderer","l":"createDecoder(Format, ExoMediaCrypto)","url":"createDecoder(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.drm.ExoMediaCrypto)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"createDecoder(Format, ExoMediaCrypto)","url":"createDecoder(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.drm.ExoMediaCrypto)"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataDecoderFactory","l":"createDecoder(Format)","url":"createDecoder(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleDecoderFactory","l":"createDecoder(Format)","url":"createDecoder(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"createDecoderException(Throwable, MediaCodecInfo)","url":"createDecoderException(java.lang.Throwable,com.google.android.exoplayer2.mediacodec.MediaCodecInfo)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"createDecoderException(Throwable, MediaCodecInfo)","url":"createDecoderException(java.lang.Throwable,com.google.android.exoplayer2.mediacodec.MediaCodecInfo)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl.Builder","l":"createDefaultLoadControl()"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloaderFactory","l":"createDownloader(DownloadRequest)","url":"createDownloader(com.google.android.exoplayer2.offline.DownloadRequest)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloaderFactory","l":"createDownloader(DownloadRequest)","url":"createDownloader(com.google.android.exoplayer2.offline.DownloadRequest)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"createDrmEventDispatcher(int, MediaSource.MediaPeriodId)","url":"createDrmEventDispatcher(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"createDrmEventDispatcher(MediaSource.MediaPeriodId)","url":"createDrmEventDispatcher(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"createEventDispatcher(int, MediaSource.MediaPeriodId, long)","url":"createEventDispatcher(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,long)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"createEventDispatcher(MediaSource.MediaPeriodId, long)","url":"createEventDispatcher(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,long)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"createEventDispatcher(MediaSource.MediaPeriodId)","url":"createEventDispatcher(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil","l":"createExternalTexture()"},{"p":"com.google.android.exoplayer2.source.hls","c":"DefaultHlsExtractorFactory","l":"createExtractor(Uri, Format, List, TimestampAdjuster, Map>, ExtractorInput)","url":"createExtractor(android.net.Uri,com.google.android.exoplayer2.Format,java.util.List,com.google.android.exoplayer2.util.TimestampAdjuster,java.util.Map,com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsExtractorFactory","l":"createExtractor(Uri, Format, List, TimestampAdjuster, Map>, ExtractorInput)","url":"createExtractor(android.net.Uri,com.google.android.exoplayer2.Format,java.util.List,com.google.android.exoplayer2.util.TimestampAdjuster,java.util.Map,com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"createExtractors()"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorsFactory","l":"createExtractors()"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"createExtractors(Uri, Map>)","url":"createExtractors(android.net.Uri,java.util.Map)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorsFactory","l":"createExtractors(Uri, Map>)","url":"createExtractors(android.net.Uri,java.util.Map)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionUtil","l":"createFallbackOptions(ExoTrackSelection)","url":"createFallbackOptions(com.google.android.exoplayer2.trackselection.ExoTrackSelection)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource.AdLoadException","l":"createForAd(Exception)","url":"createForAd(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource.AdLoadException","l":"createForAdGroup(Exception, int)","url":"createForAdGroup(java.lang.Exception,int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource.AdLoadException","l":"createForAllAds(Exception)","url":"createForAllAds(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.HttpDataSourceException","l":"createForIOException(IOException, DataSpec, int)","url":"createForIOException(java.io.IOException,com.google.android.exoplayer2.upstream.DataSpec,int)"},{"p":"com.google.android.exoplayer2","c":"ParserException","l":"createForMalformedContainer(String, Throwable)","url":"createForMalformedContainer(java.lang.String,java.lang.Throwable)"},{"p":"com.google.android.exoplayer2","c":"ParserException","l":"createForMalformedDataOfUnknownType(String, Throwable)","url":"createForMalformedDataOfUnknownType(java.lang.String,java.lang.Throwable)"},{"p":"com.google.android.exoplayer2","c":"ParserException","l":"createForMalformedManifest(String, Throwable)","url":"createForMalformedManifest(java.lang.String,java.lang.Throwable)"},{"p":"com.google.android.exoplayer2","c":"ParserException","l":"createForManifestWithUnsupportedFeature(String, Throwable)","url":"createForManifestWithUnsupportedFeature(java.lang.String,java.lang.Throwable)"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"createForRemote(String)","url":"createForRemote(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"createForRenderer(Throwable, String, int, Format, int, boolean, int)","url":"createForRenderer(java.lang.Throwable,java.lang.String,int,com.google.android.exoplayer2.Format,int,boolean,int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"createForSource(IOException, int)","url":"createForSource(java.io.IOException,int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"createForUnexpected(RuntimeException, int)","url":"createForUnexpected(java.lang.RuntimeException,int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"createForUnexpected(RuntimeException)","url":"createForUnexpected(java.lang.RuntimeException)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource.AdLoadException","l":"createForUnexpected(RuntimeException)","url":"createForUnexpected(java.lang.RuntimeException)"},{"p":"com.google.android.exoplayer2","c":"ParserException","l":"createForUnsupportedContainerFeature(String)","url":"createForUnsupportedContainerFeature(java.lang.String)"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"createFromCaptionStyle(CaptioningManager.CaptionStyle)","url":"createFromCaptionStyle(android.view.accessibility.CaptioningManager.CaptionStyle)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand.ComponentSplice","l":"createFromParcel(Parcel)","url":"createFromParcel(android.os.Parcel)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock","l":"createHandler(Looper, Handler.Callback)","url":"createHandler(android.os.Looper,android.os.Handler.Callback)"},{"p":"com.google.android.exoplayer2.util","c":"Clock","l":"createHandler(Looper, Handler.Callback)","url":"createHandler(android.os.Looper,android.os.Handler.Callback)"},{"p":"com.google.android.exoplayer2.util","c":"SystemClock","l":"createHandler(Looper, Handler.Callback)","url":"createHandler(android.os.Looper,android.os.Handler.Callback)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"createHandler(Looper, Handler.Callback)","url":"createHandler(android.os.Looper,android.os.Handler.Callback)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"createHandlerForCurrentLooper()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"createHandlerForCurrentLooper(Handler.Callback)","url":"createHandlerForCurrentLooper(android.os.Handler.Callback)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"createHandlerForCurrentOrMainLooper()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"createHandlerForCurrentOrMainLooper(Handler.Callback)","url":"createHandlerForCurrentOrMainLooper(android.os.Handler.Callback)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DefaultTsPayloadReaderFactory","l":"createInitialPayloadReaders()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.Factory","l":"createInitialPayloadReaders()"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleDecoder","l":"createInputBuffer()"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Gav1Decoder","l":"createInputBuffer()"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacDecoder","l":"createInputBuffer()"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusDecoder","l":"createInputBuffer()"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxDecoder","l":"createInputBuffer()"},{"p":"com.google.android.exoplayer2.text","c":"SimpleSubtitleDecoder","l":"createInputBuffer()"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"createMediaCrypto(byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"createMediaCrypto(byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"createMediaCrypto(byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"createMediaCrypto(byte[])"},{"p":"com.google.android.exoplayer2.util","c":"MediaFormatUtil","l":"createMediaFormatFromFormat(Format)","url":"createMediaFormatFromFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaSource","l":"createMediaPeriod(MediaSource.MediaPeriodId, TrackGroupArray, Allocator, MediaSourceEventListener.EventDispatcher, DrmSessionManager, DrmSessionEventListener.EventDispatcher, TransferListener)","url":"createMediaPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.upstream.Allocator,com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"createMediaPeriod(MediaSource.MediaPeriodId, TrackGroupArray, Allocator, MediaSourceEventListener.EventDispatcher, DrmSessionManager, DrmSessionEventListener.EventDispatcher, TransferListener)","url":"createMediaPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.upstream.Allocator,com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaPeriodAsserts.FilterableManifestMediaPeriodFactory","l":"createMediaPeriod(T, int)","url":"createMediaPeriod(T,int)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Variant","l":"createMediaPlaylistVariantUrl(Uri)","url":"createMediaPlaylistVariantUrl(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource.Factory","l":"createMediaSource()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"createMediaSource(DashManifest, MediaItem)","url":"createMediaSource(com.google.android.exoplayer2.source.dash.manifest.DashManifest,com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"createMediaSource(DashManifest)","url":"createMediaSource(com.google.android.exoplayer2.source.dash.manifest.DashManifest)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"createMediaSource(DownloadRequest, DataSource.Factory, DrmSessionManager)","url":"createMediaSource(com.google.android.exoplayer2.offline.DownloadRequest,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.drm.DrmSessionManager)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"createMediaSource(DownloadRequest, DataSource.Factory)","url":"createMediaSource(com.google.android.exoplayer2.offline.DownloadRequest,com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource.Factory","l":"createMediaSource(MediaItem.Subtitle, long)","url":"createMediaSource(com.google.android.exoplayer2.MediaItem.Subtitle,long)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"createMediaSource(MediaItem)","url":"createMediaSource(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceFactory","l":"createMediaSource(MediaItem)","url":"createMediaSource(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"createMediaSource(MediaItem)","url":"createMediaSource(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"createMediaSource(MediaItem)","url":"createMediaSource(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"createMediaSource(MediaItem)","url":"createMediaSource(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.Factory","l":"createMediaSource(MediaItem)","url":"createMediaSource(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"createMediaSource(MediaItem)","url":"createMediaSource(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"createMediaSource(SsManifest, MediaItem)","url":"createMediaSource(com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest,com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"createMediaSource(SsManifest)","url":"createMediaSource(com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest)"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource.Factory","l":"createMediaSource(Uri, Format, long)","url":"createMediaSource(android.net.Uri,com.google.android.exoplayer2.Format,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceFactory","l":"createMediaSource(Uri)","url":"createMediaSource(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"createMediaSource(Uri)","url":"createMediaSource(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"createMediaSource(Uri)","url":"createMediaSource(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"createMediaSource(Uri)","url":"createMediaSource(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"createMediaSource(Uri)","url":"createMediaSource(android.net.Uri)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"createMessage(PlayerMessage.Target)","url":"createMessage(com.google.android.exoplayer2.PlayerMessage.Target)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"createMessage(PlayerMessage.Target)","url":"createMessage(com.google.android.exoplayer2.PlayerMessage.Target)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"createMessage(PlayerMessage.Target)","url":"createMessage(com.google.android.exoplayer2.PlayerMessage.Target)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"createMetadataInputBuffer(byte[])"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"createNotification(Player, NotificationCompat.Builder, boolean, Bitmap)","url":"createNotification(com.google.android.exoplayer2.Player,androidx.core.app.NotificationCompat.Builder,boolean,android.graphics.Bitmap)"},{"p":"com.google.android.exoplayer2.util","c":"NotificationUtil","l":"createNotificationChannel(Context, String, int, int, int)","url":"createNotificationChannel(android.content.Context,java.lang.String,int,int,int)"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleDecoder","l":"createOutputBuffer()"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Gav1Decoder","l":"createOutputBuffer()"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacDecoder","l":"createOutputBuffer()"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusDecoder","l":"createOutputBuffer()"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxDecoder","l":"createOutputBuffer()"},{"p":"com.google.android.exoplayer2.text","c":"SimpleSubtitleDecoder","l":"createOutputBuffer()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DefaultTsPayloadReaderFactory","l":"createPayloadReader(int, TsPayloadReader.EsInfo)","url":"createPayloadReader(int,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.EsInfo)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.Factory","l":"createPayloadReader(int, TsPayloadReader.EsInfo)","url":"createPayloadReader(int,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.EsInfo)"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","c":"DefaultRtpPayloadReaderFactory","l":"createPayloadReader(RtpPayloadFormat)","url":"createPayloadReader(com.google.android.exoplayer2.source.rtsp.RtpPayloadFormat)"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","c":"RtpPayloadReader.Factory","l":"createPayloadReader(RtpPayloadFormat)","url":"createPayloadReader(com.google.android.exoplayer2.source.rtsp.RtpPayloadFormat)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source","c":"LoopingMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"createPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"createPeriod(MediaSource.MediaPeriodId, long)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,long)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"createPeriod(MediaSource.MediaPeriodId)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"createPeriod(MediaSource.MediaPeriodId)","url":"createPeriod(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"createPlaceholder(Object)","url":"createPlaceholder(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistParserFactory","l":"createPlaylistParser()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"FilteringHlsPlaylistParserFactory","l":"createPlaylistParser()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistParserFactory","l":"createPlaylistParser()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistParserFactory","l":"createPlaylistParser(HlsMasterPlaylist, HlsMediaPlaylist)","url":"createPlaylistParser(com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist,com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"FilteringHlsPlaylistParserFactory","l":"createPlaylistParser(HlsMasterPlaylist, HlsMediaPlaylist)","url":"createPlaylistParser(com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist,com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistParserFactory","l":"createPlaylistParser(HlsMasterPlaylist, HlsMediaPlaylist)","url":"createPlaylistParser(com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist,com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaExtractor.Factory","l":"createProgressiveMediaExtractor()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkExtractor.Factory","l":"createProgressiveMediaExtractor(int, Format, boolean, List, TrackOutput)","url":"createProgressiveMediaExtractor(int,com.google.android.exoplayer2.Format,boolean,java.util.List,com.google.android.exoplayer2.extractor.TrackOutput)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"createRendererException(Throwable, Format, boolean, int)","url":"createRendererException(java.lang.Throwable,com.google.android.exoplayer2.Format,boolean,int)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"createRendererException(Throwable, Format, int)","url":"createRendererException(java.lang.Throwable,com.google.android.exoplayer2.Format,int)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"createRenderers(Handler, VideoRendererEventListener, AudioRendererEventListener, TextOutput, MetadataOutput)","url":"createRenderers(android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.text.TextOutput,com.google.android.exoplayer2.metadata.MetadataOutput)"},{"p":"com.google.android.exoplayer2","c":"RenderersFactory","l":"createRenderers(Handler, VideoRendererEventListener, AudioRendererEventListener, TextOutput, MetadataOutput)","url":"createRenderers(android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.text.TextOutput,com.google.android.exoplayer2.metadata.MetadataOutput)"},{"p":"com.google.android.exoplayer2.testutil","c":"CapturingRenderersFactory","l":"createRenderers(Handler, VideoRendererEventListener, AudioRendererEventListener, TextOutput, MetadataOutput)","url":"createRenderers(android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.text.TextOutput,com.google.android.exoplayer2.metadata.MetadataOutput)"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"createRetryAction(boolean, long)","url":"createRetryAction(boolean,long)"},{"p":"com.google.android.exoplayer2.robolectric","c":"RobolectricUtil","l":"createRobolectricConditionVariable()"},{"p":"com.google.android.exoplayer2","c":"Format","l":"createSampleFormat(String, String)","url":"createSampleFormat(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"createSampleStream(Allocator, MediaSourceEventListener.EventDispatcher, DrmSessionManager, DrmSessionEventListener.EventDispatcher, Format, List)","url":"createSampleStream(com.google.android.exoplayer2.upstream.Allocator,com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher,com.google.android.exoplayer2.Format,java.util.List)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"createSeekParamsForTargetTimeUs(long)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"createSessionCreationData(DrmInitData, DrmInitData)","url":"createSessionCreationData(com.google.android.exoplayer2.drm.DrmInitData,com.google.android.exoplayer2.drm.DrmInitData)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"createSingleVariantMasterPlaylist(String)","url":"createSingleVariantMasterPlaylist(java.lang.String)"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea608Decoder","l":"createSubtitle()"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea708Decoder","l":"createSubtitle()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"createTempDirectory(Context, String)","url":"createTempDirectory(android.content.Context,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"createTempFile(Context, String)","url":"createTempFile(android.content.Context,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"createTestFile(File, long)","url":"createTestFile(java.io.File,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"createTestFile(File, String, long)","url":"createTestFile(java.io.File,java.lang.String,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"createTestFile(File, String)","url":"createTestFile(java.io.File,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker.Factory","l":"createTracker(HlsDataSourceFactory, LoadErrorHandlingPolicy, HlsPlaylistParserFactory)","url":"createTracker(com.google.android.exoplayer2.source.hls.HlsDataSourceFactory,com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy,com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParserFactory)"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","c":"RtpAc3Reader","l":"createTracks(ExtractorOutput, int)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,int)"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","c":"RtpPayloadReader","l":"createTracks(ExtractorOutput, int)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Reader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Reader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsReader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DtsReader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DvbSubtitleReader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"ElementaryStreamReader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H262Reader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H263Reader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H264Reader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H265Reader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Id3Reader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"LatmReader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"MpegAudioReader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"SeiReader","l":"createTracks(ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"createTracks(com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection.Factory","l":"createTrackSelections(ExoTrackSelection.Definition[], BandwidthMeter, MediaSource.MediaPeriodId, Timeline)","url":"createTrackSelections(com.google.android.exoplayer2.trackselection.ExoTrackSelection.Definition[],com.google.android.exoplayer2.upstream.BandwidthMeter,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection.Factory","l":"createTrackSelections(ExoTrackSelection.Definition[], BandwidthMeter, MediaSource.MediaPeriodId, Timeline)","url":"createTrackSelections(com.google.android.exoplayer2.trackselection.ExoTrackSelection.Definition[],com.google.android.exoplayer2.upstream.BandwidthMeter,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.trackselection","c":"RandomTrackSelection.Factory","l":"createTrackSelections(ExoTrackSelection.Definition[], BandwidthMeter, MediaSource.MediaPeriodId, Timeline)","url":"createTrackSelections(com.google.android.exoplayer2.trackselection.ExoTrackSelection.Definition[],com.google.android.exoplayer2.upstream.BandwidthMeter,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionUtil","l":"createTrackSelectionsForDefinitions(ExoTrackSelection.Definition[], TrackSelectionUtil.AdaptiveTrackSelectionFactory)","url":"createTrackSelectionsForDefinitions(com.google.android.exoplayer2.trackselection.ExoTrackSelection.Definition[],com.google.android.exoplayer2.trackselection.TrackSelectionUtil.AdaptiveTrackSelectionFactory)"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleDecoder","l":"createUnexpectedDecodeException(Throwable)","url":"createUnexpectedDecodeException(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Gav1Decoder","l":"createUnexpectedDecodeException(Throwable)","url":"createUnexpectedDecodeException(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacDecoder","l":"createUnexpectedDecodeException(Throwable)","url":"createUnexpectedDecodeException(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusDecoder","l":"createUnexpectedDecodeException(Throwable)","url":"createUnexpectedDecodeException(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxDecoder","l":"createUnexpectedDecodeException(Throwable)","url":"createUnexpectedDecodeException(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.text","c":"SimpleSubtitleDecoder","l":"createUnexpectedDecodeException(Throwable)","url":"createUnexpectedDecodeException(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"createVideoSampleFormat(String, String, String, int, int, int, int, float, List, DrmInitData)","url":"createVideoSampleFormat(java.lang.String,java.lang.String,java.lang.String,int,int,int,int,float,java.util.List,com.google.android.exoplayer2.drm.DrmInitData)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"createVideoSampleFormat(String, String, String, int, int, int, int, float, List, int, float, DrmInitData)","url":"createVideoSampleFormat(java.lang.String,java.lang.String,java.lang.String,int,int,int,int,float,java.util.List,int,float,com.google.android.exoplayer2.drm.DrmInitData)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"createWithDrm(Allocator, Looper, DrmSessionManager, DrmSessionEventListener.EventDispatcher)","url":"createWithDrm(com.google.android.exoplayer2.upstream.Allocator,android.os.Looper,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"createWithoutDrm(Allocator)","url":"createWithoutDrm(com.google.android.exoplayer2.upstream.Allocator)"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"Format","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"HeartRating","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"MediaItem.ClippingProperties","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"MediaItem.LiveConfiguration","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"PercentageRating","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"PlaybackParameters","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"Player.Commands","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"Rating","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"StarRating","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"ThumbRating","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"CREATOR"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"CREATOR"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes","l":"CREATOR"},{"p":"com.google.android.exoplayer2.device","c":"DeviceInfo","l":"CREATOR"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"CREATOR"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","c":"AppInfoTable","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"VorbisComment","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyInfo","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ApicFrame","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"BinaryFrame","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterTocFrame","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"CommentFrame","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"GeobFrame","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"InternalFrame","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"MlltFrame","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"PrivFrame","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"TextInformationFrame","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"UrlLinkFrame","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MdtaMetadataEntry","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MotionPhotoMetadata","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData.Segment","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SmtaMetadataEntry","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"PrivateCommand","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceNullCommand","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand","l":"CREATOR"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"TimeSignalCommand","l":"CREATOR"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"CREATOR"},{"p":"com.google.android.exoplayer2.offline","c":"StreamKey","l":"CREATOR"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"CREATOR"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroup","l":"CREATOR"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroupArray","l":"CREATOR"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"CREATOR"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"CREATOR"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry","l":"CREATOR"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry.VariantInfo","l":"CREATOR"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"CREATOR"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"CREATOR"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.SelectionOverride","l":"CREATOR"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"CREATOR"},{"p":"com.google.android.exoplayer2.video","c":"ColorInfo","l":"CREATOR"},{"p":"com.google.android.exoplayer2.video","c":"VideoSize","l":"CREATOR"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.OpenException","l":"cronetConnectionStatus"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"CronetDataSource(CronetEngine, Executor, int, int, boolean, HttpDataSource.RequestProperties, boolean)","url":"%3Cinit%3E(org.chromium.net.CronetEngine,java.util.concurrent.Executor,int,int,boolean,com.google.android.exoplayer2.upstream.HttpDataSource.RequestProperties,boolean)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"CronetDataSource(CronetEngine, Executor, int, int, boolean, HttpDataSource.RequestProperties)","url":"%3Cinit%3E(org.chromium.net.CronetEngine,java.util.concurrent.Executor,int,int,boolean,com.google.android.exoplayer2.upstream.HttpDataSource.RequestProperties)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"CronetDataSource(CronetEngine, Executor, int, int, int, boolean, boolean, String, HttpDataSource.RequestProperties, Predicate, boolean)","url":"%3Cinit%3E(org.chromium.net.CronetEngine,java.util.concurrent.Executor,int,int,int,boolean,boolean,java.lang.String,com.google.android.exoplayer2.upstream.HttpDataSource.RequestProperties,com.google.common.base.Predicate,boolean)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"CronetDataSource(CronetEngine, Executor, Predicate, int, int, boolean, HttpDataSource.RequestProperties, boolean)","url":"%3Cinit%3E(org.chromium.net.CronetEngine,java.util.concurrent.Executor,com.google.common.base.Predicate,int,int,boolean,com.google.android.exoplayer2.upstream.HttpDataSource.RequestProperties,boolean)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"CronetDataSource(CronetEngine, Executor, Predicate, int, int, boolean, HttpDataSource.RequestProperties)","url":"%3Cinit%3E(org.chromium.net.CronetEngine,java.util.concurrent.Executor,com.google.common.base.Predicate,int,int,boolean,com.google.android.exoplayer2.upstream.HttpDataSource.RequestProperties)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"CronetDataSource(CronetEngine, Executor, Predicate)","url":"%3Cinit%3E(org.chromium.net.CronetEngine,java.util.concurrent.Executor,com.google.common.base.Predicate)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"CronetDataSource(CronetEngine, Executor)","url":"%3Cinit%3E(org.chromium.net.CronetEngine,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"CronetDataSourceFactory(CronetEngineWrapper, Executor, HttpDataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper,java.util.concurrent.Executor,com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"CronetDataSourceFactory(CronetEngineWrapper, Executor, int, int, boolean, HttpDataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper,java.util.concurrent.Executor,int,int,boolean,com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"CronetDataSourceFactory(CronetEngineWrapper, Executor, int, int, boolean, String)","url":"%3Cinit%3E(com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper,java.util.concurrent.Executor,int,int,boolean,java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"CronetDataSourceFactory(CronetEngineWrapper, Executor, String)","url":"%3Cinit%3E(com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper,java.util.concurrent.Executor,java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"CronetDataSourceFactory(CronetEngineWrapper, Executor, TransferListener, HttpDataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper,java.util.concurrent.Executor,com.google.android.exoplayer2.upstream.TransferListener,com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"CronetDataSourceFactory(CronetEngineWrapper, Executor, TransferListener, int, int, boolean, HttpDataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper,java.util.concurrent.Executor,com.google.android.exoplayer2.upstream.TransferListener,int,int,boolean,com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"CronetDataSourceFactory(CronetEngineWrapper, Executor, TransferListener, int, int, boolean, String)","url":"%3Cinit%3E(com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper,java.util.concurrent.Executor,com.google.android.exoplayer2.upstream.TransferListener,int,int,boolean,java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"CronetDataSourceFactory(CronetEngineWrapper, Executor, TransferListener, String)","url":"%3Cinit%3E(com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper,java.util.concurrent.Executor,com.google.android.exoplayer2.upstream.TransferListener,java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"CronetDataSourceFactory(CronetEngineWrapper, Executor, TransferListener)","url":"%3Cinit%3E(com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper,java.util.concurrent.Executor,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"CronetDataSourceFactory(CronetEngineWrapper, Executor)","url":"%3Cinit%3E(com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetEngineWrapper","l":"CronetEngineWrapper(Context, String, boolean)","url":"%3Cinit%3E(android.content.Context,java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetEngineWrapper","l":"CronetEngineWrapper(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetEngineWrapper","l":"CronetEngineWrapper(CronetEngine)","url":"%3Cinit%3E(org.chromium.net.CronetEngine)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter.Configuration","l":"crypto"},{"p":"com.google.android.exoplayer2","c":"C","l":"CRYPTO_MODE_AES_CBC"},{"p":"com.google.android.exoplayer2","c":"C","l":"CRYPTO_MODE_AES_CTR"},{"p":"com.google.android.exoplayer2","c":"C","l":"CRYPTO_MODE_UNENCRYPTED"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"TrackEncryptionBox","l":"cryptoData"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput.CryptoData","l":"CryptoData(int, byte[], int, int)","url":"%3Cinit%3E(int,byte[],int,int)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"cryptoInfo"},{"p":"com.google.android.exoplayer2.decoder","c":"CryptoInfo","l":"CryptoInfo()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput.CryptoData","l":"cryptoMode"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"csrc"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"CSRC_SIZE"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"csrcCount"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCueInfo","l":"cue"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCueParser","l":"CUE_HEADER_PATTERN"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"Cue(CharSequence, Layout.Alignment, float, int, int, float, int, float, boolean, int)","url":"%3Cinit%3E(java.lang.CharSequence,android.text.Layout.Alignment,float,int,int,float,int,float,boolean,int)"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"Cue(CharSequence, Layout.Alignment, float, int, int, float, int, float, int, float)","url":"%3Cinit%3E(java.lang.CharSequence,android.text.Layout.Alignment,float,int,int,float,int,float,int,float)"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"Cue(CharSequence, Layout.Alignment, float, int, int, float, int, float)","url":"%3Cinit%3E(java.lang.CharSequence,android.text.Layout.Alignment,float,int,int,float,int,float)"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"Cue(CharSequence)","url":"%3Cinit%3E(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"CURRENT_POSITION_NOT_SET"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer.InsufficientCapacityException","l":"currentCapacity"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"currentMediaPeriodId"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"currentPlaybackPositionMs"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"currentTimeline"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock","l":"currentTimeMillis()"},{"p":"com.google.android.exoplayer2.util","c":"Clock","l":"currentTimeMillis()"},{"p":"com.google.android.exoplayer2.util","c":"SystemClock","l":"currentTimeMillis()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"currentWindowIndex"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"CUSTOM_ERROR_CODE_BASE"},{"p":"com.google.android.exoplayer2","c":"MediaItem.PlaybackProperties","l":"customCacheKey"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"customCacheKey"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"customData"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"d(String, String, Throwable)","url":"d(java.lang.String,java.lang.String,java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"d(String, String)","url":"d(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.offline","c":"DashDownloader","l":"DashDownloader(MediaItem, CacheDataSource.Factory, Executor)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.source.dash.offline","c":"DashDownloader","l":"DashDownloader(MediaItem, CacheDataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.dash.offline","c":"DashDownloader","l":"DashDownloader(MediaItem, ParsingLoadable.Parser, CacheDataSource.Factory, Executor)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.upstream.ParsingLoadable.Parser,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"DashManifest(long, long, long, boolean, long, long, long, long, ProgramInformation, UtcTimingElement, ServiceDescriptionElement, Uri, List)","url":"%3Cinit%3E(long,long,long,boolean,long,long,long,long,com.google.android.exoplayer2.source.dash.manifest.ProgramInformation,com.google.android.exoplayer2.source.dash.manifest.UtcTimingElement,com.google.android.exoplayer2.source.dash.manifest.ServiceDescriptionElement,android.net.Uri,java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"DashManifestParser()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashManifestStaleException","l":"DashManifestStaleException()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashWrappingSegmentIndex","l":"DashWrappingSegmentIndex(ChunkIndex, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.ChunkIndex,long)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"data"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleOutputBuffer","l":"data"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"data"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.VorbisIdHeader","l":"data"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"BinaryFrame","l":"data"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"GeobFrame","l":"data"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"data"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.ProtectionElement","l":"data"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData.Segment","l":"data"},{"p":"com.google.android.exoplayer2.upstream","c":"Allocation","l":"data"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"data"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"data"},{"p":"com.google.android.exoplayer2.audio","c":"WavUtil","l":"DATA_FOURCC"},{"p":"com.google.android.exoplayer2","c":"C","l":"DATA_TYPE_AD"},{"p":"com.google.android.exoplayer2","c":"C","l":"DATA_TYPE_CUSTOM_BASE"},{"p":"com.google.android.exoplayer2","c":"C","l":"DATA_TYPE_DRM"},{"p":"com.google.android.exoplayer2","c":"C","l":"DATA_TYPE_MANIFEST"},{"p":"com.google.android.exoplayer2","c":"C","l":"DATA_TYPE_MEDIA"},{"p":"com.google.android.exoplayer2","c":"C","l":"DATA_TYPE_MEDIA_INITIALIZATION"},{"p":"com.google.android.exoplayer2","c":"C","l":"DATA_TYPE_MEDIA_PROGRESSIVE_LIVE"},{"p":"com.google.android.exoplayer2","c":"C","l":"DATA_TYPE_TIME_SYNCHRONIZATION"},{"p":"com.google.android.exoplayer2","c":"C","l":"DATA_TYPE_UNKNOWN"},{"p":"com.google.android.exoplayer2.database","c":"ExoDatabaseProvider","l":"DATABASE_NAME"},{"p":"com.google.android.exoplayer2.database","c":"DatabaseIOException","l":"DatabaseIOException(SQLException, String)","url":"%3Cinit%3E(android.database.SQLException,java.lang.String)"},{"p":"com.google.android.exoplayer2.database","c":"DatabaseIOException","l":"DatabaseIOException(SQLException)","url":"%3Cinit%3E(android.database.SQLException)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"DataChunk","l":"DataChunk(DataSource, DataSpec, int, Format, int, Object, byte[])","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,int,com.google.android.exoplayer2.Format,int,java.lang.Object,byte[])"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSchemeDataSource","l":"DataSchemeDataSource()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource.Factory","l":"dataSetFactory"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"dataSource"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"DataSourceContractTest()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceException","l":"DataSourceException(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceException","l":"DataSourceException(String, int)","url":"%3Cinit%3E(java.lang.String,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceException","l":"DataSourceException(String, Throwable, int)","url":"%3Cinit%3E(java.lang.String,java.lang.Throwable,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceException","l":"DataSourceException(Throwable, int)","url":"%3Cinit%3E(java.lang.Throwable,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource.Factory","l":"dataSourceFactory"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceInputStream","l":"DataSourceInputStream(DataSource, DataSpec)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.drm","c":"MediaDrmCallbackException","l":"dataSpec"},{"p":"com.google.android.exoplayer2.offline","c":"SegmentDownloader.Segment","l":"dataSpec"},{"p":"com.google.android.exoplayer2.source","c":"LoadEventInfo","l":"dataSpec"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"dataSpec"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.HttpDataSourceException","l":"dataSpec"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"dataSpec"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"DataSpec(Uri, byte[], long, long, long, String, int)","url":"%3Cinit%3E(android.net.Uri,byte[],long,long,long,java.lang.String,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"DataSpec(Uri, int, byte[], long, long, long, String, int, Map)","url":"%3Cinit%3E(android.net.Uri,int,byte[],long,long,long,java.lang.String,int,java.util.Map)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"DataSpec(Uri, int, byte[], long, long, long, String, int)","url":"%3Cinit%3E(android.net.Uri,int,byte[],long,long,long,java.lang.String,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"DataSpec(Uri, int)","url":"%3Cinit%3E(android.net.Uri,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"DataSpec(Uri, long, long, long, String, int)","url":"%3Cinit%3E(android.net.Uri,long,long,long,java.lang.String,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"DataSpec(Uri, long, long, String, int, Map)","url":"%3Cinit%3E(android.net.Uri,long,long,java.lang.String,int,java.util.Map)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"DataSpec(Uri, long, long, String, int)","url":"%3Cinit%3E(android.net.Uri,long,long,java.lang.String,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"DataSpec(Uri, long, long, String)","url":"%3Cinit%3E(android.net.Uri,long,long,java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"DataSpec(Uri, long, long)","url":"%3Cinit%3E(android.net.Uri,long,long)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"DataSpec(Uri)","url":"%3Cinit%3E(android.net.Uri)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"dataSpecWithEndPositionOutOfRange_readsToEnd()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"dataSpecWithLength_readExpectedRange()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"dataSpecWithPosition_readUntilEnd()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"dataSpecWithPositionAndLength_readExpectedRange()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"dataSpecWithPositionAtEnd_throwsPositionOutOfRangeException()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"dataSpecWithPositionAtEndAndLength_throwsPositionOutOfRangeException()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"dataSpecWithPositionOutOfRange_throwsPositionOutOfRangeException()"},{"p":"com.google.android.exoplayer2","c":"ParserException","l":"dataType"},{"p":"com.google.android.exoplayer2.source","c":"MediaLoadData","l":"dataType"},{"p":"com.google.android.exoplayer2.util","c":"DebugTextViewHelper","l":"DebugTextViewHelper(SimpleExoPlayer, TextView)","url":"%3Cinit%3E(com.google.android.exoplayer2.SimpleExoPlayer,android.widget.TextView)"},{"p":"com.google.android.exoplayer2.text","c":"SimpleSubtitleDecoder","l":"decode(byte[], int, boolean)","url":"decode(byte[],int,boolean)"},{"p":"com.google.android.exoplayer2.text.dvb","c":"DvbDecoder","l":"decode(byte[], int, boolean)","url":"decode(byte[],int,boolean)"},{"p":"com.google.android.exoplayer2.text.pgs","c":"PgsDecoder","l":"decode(byte[], int, boolean)","url":"decode(byte[],int,boolean)"},{"p":"com.google.android.exoplayer2.text.ssa","c":"SsaDecoder","l":"decode(byte[], int, boolean)","url":"decode(byte[],int,boolean)"},{"p":"com.google.android.exoplayer2.text.subrip","c":"SubripDecoder","l":"decode(byte[], int, boolean)","url":"decode(byte[],int,boolean)"},{"p":"com.google.android.exoplayer2.text.ttml","c":"TtmlDecoder","l":"decode(byte[], int, boolean)","url":"decode(byte[],int,boolean)"},{"p":"com.google.android.exoplayer2.text.tx3g","c":"Tx3gDecoder","l":"decode(byte[], int, boolean)","url":"decode(byte[],int,boolean)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"Mp4WebvttDecoder","l":"decode(byte[], int, boolean)","url":"decode(byte[],int,boolean)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttDecoder","l":"decode(byte[], int, boolean)","url":"decode(byte[],int,boolean)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"Id3Decoder","l":"decode(byte[], int)","url":"decode(byte[],int)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacDecoder","l":"decode(DecoderInputBuffer, SimpleOutputBuffer, boolean)","url":"decode(com.google.android.exoplayer2.decoder.DecoderInputBuffer,com.google.android.exoplayer2.decoder.SimpleOutputBuffer,boolean)"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusDecoder","l":"decode(DecoderInputBuffer, SimpleOutputBuffer, boolean)","url":"decode(com.google.android.exoplayer2.decoder.DecoderInputBuffer,com.google.android.exoplayer2.decoder.SimpleOutputBuffer,boolean)"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleDecoder","l":"decode(I, O, boolean)","url":"decode(I,O,boolean)"},{"p":"com.google.android.exoplayer2.metadata","c":"SimpleMetadataDecoder","l":"decode(MetadataInputBuffer, ByteBuffer)","url":"decode(com.google.android.exoplayer2.metadata.MetadataInputBuffer,java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","c":"AppInfoTableDecoder","l":"decode(MetadataInputBuffer, ByteBuffer)","url":"decode(com.google.android.exoplayer2.metadata.MetadataInputBuffer,java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessageDecoder","l":"decode(MetadataInputBuffer, ByteBuffer)","url":"decode(com.google.android.exoplayer2.metadata.MetadataInputBuffer,java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyDecoder","l":"decode(MetadataInputBuffer, ByteBuffer)","url":"decode(com.google.android.exoplayer2.metadata.MetadataInputBuffer,java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"Id3Decoder","l":"decode(MetadataInputBuffer, ByteBuffer)","url":"decode(com.google.android.exoplayer2.metadata.MetadataInputBuffer,java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInfoDecoder","l":"decode(MetadataInputBuffer, ByteBuffer)","url":"decode(com.google.android.exoplayer2.metadata.MetadataInputBuffer,java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataDecoder","l":"decode(MetadataInputBuffer)","url":"decode(com.google.android.exoplayer2.metadata.MetadataInputBuffer)"},{"p":"com.google.android.exoplayer2.metadata","c":"SimpleMetadataDecoder","l":"decode(MetadataInputBuffer)","url":"decode(com.google.android.exoplayer2.metadata.MetadataInputBuffer)"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessageDecoder","l":"decode(ParsableByteArray)","url":"decode(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.text","c":"SimpleSubtitleDecoder","l":"decode(SubtitleInputBuffer, SubtitleOutputBuffer, boolean)","url":"decode(com.google.android.exoplayer2.text.SubtitleInputBuffer,com.google.android.exoplayer2.text.SubtitleOutputBuffer,boolean)"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea608Decoder","l":"decode(SubtitleInputBuffer)","url":"decode(com.google.android.exoplayer2.text.SubtitleInputBuffer)"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea708Decoder","l":"decode(SubtitleInputBuffer)","url":"decode(com.google.android.exoplayer2.text.SubtitleInputBuffer)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Gav1Decoder","l":"decode(VideoDecoderInputBuffer, VideoDecoderOutputBuffer, boolean)","url":"decode(com.google.android.exoplayer2.video.VideoDecoderInputBuffer,com.google.android.exoplayer2.video.VideoDecoderOutputBuffer,boolean)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxDecoder","l":"decode(VideoDecoderInputBuffer, VideoDecoderOutputBuffer, boolean)","url":"decode(com.google.android.exoplayer2.video.VideoDecoderInputBuffer,com.google.android.exoplayer2.video.VideoDecoderOutputBuffer,boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"DecoderAudioRenderer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"DecoderAudioRenderer(Handler, AudioRendererEventListener, AudioCapabilities, AudioProcessor...)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioCapabilities,com.google.android.exoplayer2.audio.AudioProcessor...)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"DecoderAudioRenderer(Handler, AudioRendererEventListener, AudioProcessor...)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioProcessor...)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"DecoderAudioRenderer(Handler, AudioRendererEventListener, AudioSink)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioSink)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"decoderCounters"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"decoderCounters"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"DecoderCounters()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderException","l":"DecoderException(String, Throwable)","url":"%3Cinit%3E(java.lang.String,java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderException","l":"DecoderException(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderException","l":"DecoderException(Throwable)","url":"%3Cinit%3E(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"decoderInitCount"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer.DecoderInitializationException","l":"DecoderInitializationException(Format, Throwable, boolean, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format,java.lang.Throwable,boolean,int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer.DecoderInitializationException","l":"DecoderInitializationException(Format, Throwable, boolean, MediaCodecInfo)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format,java.lang.Throwable,boolean,com.google.android.exoplayer2.mediacodec.MediaCodecInfo)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener.EventDispatcher","l":"decoderInitialized(String, long, long)","url":"decoderInitialized(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener.EventDispatcher","l":"decoderInitialized(String, long, long)","url":"decoderInitialized(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"DecoderInputBuffer(int, int)","url":"%3Cinit%3E(int,int)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"DecoderInputBuffer(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"decoderName"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"decoderPrivate"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"decoderReleaseCount"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener.EventDispatcher","l":"decoderReleased(String)","url":"decoderReleased(java.lang.String)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener.EventDispatcher","l":"decoderReleased(String)","url":"decoderReleased(java.lang.String)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DecoderReuseEvaluation(String, Format, Format, int, int)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format,int,int)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"DecoderVideoRenderer(long, Handler, VideoRendererEventListener, int)","url":"%3Cinit%3E(long,android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener,int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.DeviceComponent","l":"decreaseDeviceVolume()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"decreaseDeviceVolume()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"decreaseDeviceVolume()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"decreaseDeviceVolume()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"decreaseDeviceVolume()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"decreaseDeviceVolume()"},{"p":"com.google.android.exoplayer2.drm","c":"DecryptionException","l":"DecryptionException(int, String)","url":"%3Cinit%3E(int,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts.AssertionConfig","l":"deduplicateConsecutiveFormats"},{"p":"com.google.android.exoplayer2","c":"PlaybackParameters","l":"DEFAULT"},{"p":"com.google.android.exoplayer2","c":"RendererConfiguration","l":"DEFAULT"},{"p":"com.google.android.exoplayer2","c":"SeekParameters","l":"DEFAULT"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes","l":"DEFAULT"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter.Factory","l":"DEFAULT"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecSelector","l":"DEFAULT"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataDecoderFactory","l":"DEFAULT"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsExtractorFactory","l":"DEFAULT"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleDecoderFactory","l":"DEFAULT"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"DEFAULT"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"DEFAULT"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"DEFAULT"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheKeyFactory","l":"DEFAULT"},{"p":"com.google.android.exoplayer2.util","c":"Clock","l":"DEFAULT"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DEFAULT_AD_MARKER_COLOR"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DEFAULT_AD_MARKER_WIDTH_DP"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"DEFAULT_AD_PRELOAD_TIMEOUT_MS"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"DEFAULT_ALLOWED_VIDEO_JOINING_TIME_MS"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_AUDIO_BUFFER_SIZE"},{"p":"com.google.android.exoplayer2.audio","c":"AudioCapabilities","l":"DEFAULT_AUDIO_CAPABILITIES"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_BACK_BUFFER_DURATION_MS"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"DEFAULT_BANDWIDTH_FRACTION"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DEFAULT_BAR_HEIGHT_DP"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"DEFAULT_BOTTOM_PADDING_FRACTION"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_BUFFER_FOR_PLAYBACK_MS"},{"p":"com.google.android.exoplayer2","c":"C","l":"DEFAULT_BUFFER_SEGMENT_SIZE"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink","l":"DEFAULT_BUFFER_SIZE"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheWriter","l":"DEFAULT_BUFFER_SIZE_BYTES"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DEFAULT_BUFFERED_COLOR"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"DEFAULT_BUFFERED_FRACTION_TO_LIVE_EDGE_FOR_QUALITY_INCREASE"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_CAMERA_MOTION_BUFFER_SIZE"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"DEFAULT_CONNECT_TIMEOUT_MILLIS"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"DEFAULT_CONNECT_TIMEOUT_MILLIS"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"DEFAULT_CONNECT_TIMEOUT_MILLIS"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"DEFAULT_DETACH_SURFACE_TIMEOUT_MS"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"DEFAULT_FACTORY"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl","l":"DEFAULT_FALLBACK_MAX_PLAYBACK_SPEED"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl","l":"DEFAULT_FALLBACK_MIN_PLAYBACK_SPEED"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource","l":"DEFAULT_FALLBACK_TARGET_LIVE_OFFSET_MS"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"DEFAULT_FOREGROUND_NOTIFICATION_UPDATE_INTERVAL"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink","l":"DEFAULT_FRAGMENT_SIZE"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"DEFAULT_INITIAL_BITRATE_COUNTRY_GROUPS"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"DEFAULT_INITIAL_BITRATE_ESTIMATE"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"DEFAULT_INITIAL_BITRATE_ESTIMATES_2G"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"DEFAULT_INITIAL_BITRATE_ESTIMATES_3G"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"DEFAULT_INITIAL_BITRATE_ESTIMATES_4G"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"DEFAULT_INITIAL_BITRATE_ESTIMATES_5G_NSA"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"DEFAULT_INITIAL_BITRATE_ESTIMATES_5G_SA"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"DEFAULT_INITIAL_BITRATE_ESTIMATES_WIFI"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource","l":"DEFAULT_LIVE_PRESENTATION_DELAY_MS"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource","l":"DEFAULT_LIVE_PRESENTATION_DELAY_MS"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource","l":"DEFAULT_LOADING_CHECK_INTERVAL_BYTES"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultLoadErrorHandlingPolicy","l":"DEFAULT_LOCATION_EXCLUSION_MS"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_MAX_BUFFER_MS"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl","l":"DEFAULT_MAX_LIVE_OFFSET_ERROR_MS_FOR_UNIT_SPEED"},{"p":"com.google.android.exoplayer2.upstream","c":"UdpDataSource","l":"DEFAULT_MAX_PACKET_SIZE"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"DEFAULT_MAX_PARALLEL_DOWNLOADS"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueNavigator","l":"DEFAULT_MAX_QUEUE_SIZE"},{"p":"com.google.android.exoplayer2","c":"C","l":"DEFAULT_MAX_SEEK_TO_PREVIOUS_POSITION_MS"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"DEFAULT_MEDIA_ID"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource","l":"DEFAULT_MEDIA_ID"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_METADATA_BUFFER_SIZE"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_MIN_BUFFER_MS"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_MIN_BUFFER_SIZE"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultLoadErrorHandlingPolicy","l":"DEFAULT_MIN_LOADABLE_RETRY_COUNT"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultLoadErrorHandlingPolicy","l":"DEFAULT_MIN_LOADABLE_RETRY_COUNT_PROGRESSIVE_LIVE"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl","l":"DEFAULT_MIN_POSSIBLE_LIVE_OFFSET_SMOOTHING_FACTOR"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"DEFAULT_MIN_RETRY_COUNT"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl","l":"DEFAULT_MIN_UPDATE_INTERVAL_MS"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"DEFAULT_MINIMUM_SILENCE_DURATION_US"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_MUXED_BUFFER_SIZE"},{"p":"com.google.android.exoplayer2.util","c":"SntpClient","l":"DEFAULT_NTP_HOST"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"DEFAULT_PADDING_SILENCE_US"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"DEFAULT_PLAYBACK_ACTIONS"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"DEFAULT_PLAYBACK_SPEED"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DEFAULT_PLAYED_AD_MARKER_COLOR"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DEFAULT_PLAYED_COLOR"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"DEFAULT_PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_PRIORITIZE_TIME_OVER_SIZE_THRESHOLDS"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"BaseUrl","l":"DEFAULT_PRIORITY"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl","l":"DEFAULT_PROPORTIONAL_CONTROL_FACTOR"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"DEFAULT_PROVIDER"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"DEFAULT_READ_TIMEOUT_MILLIS"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSourceFactory","l":"DEFAULT_READ_TIMEOUT_MILLIS"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"DEFAULT_READ_TIMEOUT_MILLIS"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"DEFAULT_RELEASE_TIMEOUT_MS"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"RepeatModeActionProvider","l":"DEFAULT_REPEAT_TOGGLE_MODES"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"DEFAULT_REPEAT_TOGGLE_MODES"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"DEFAULT_REPEAT_TOGGLE_MODES"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"DEFAULT_REQUIREMENTS"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_RETAIN_BACK_BUFFER_FROM_KEYFRAME"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DEFAULT_SCRUBBER_COLOR"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DEFAULT_SCRUBBER_DISABLED_SIZE_DP"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DEFAULT_SCRUBBER_DRAGGED_SIZE_DP"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DEFAULT_SCRUBBER_ENABLED_SIZE_DP"},{"p":"com.google.android.exoplayer2","c":"C","l":"DEFAULT_SEEK_BACK_INCREMENT_MS"},{"p":"com.google.android.exoplayer2","c":"C","l":"DEFAULT_SEEK_FORWARD_INCREMENT_MS"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"DEFAULT_SEEK_TIMEOUT_MS"},{"p":"com.google.android.exoplayer2.analytics","c":"DefaultPlaybackSessionManager","l":"DEFAULT_SESSION_ID_GENERATOR"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"DEFAULT_SESSION_KEEPALIVE_MS"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"DEFAULT_SHOW_TIMEOUT_MS"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"DEFAULT_SHOW_TIMEOUT_MS"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"DEFAULT_SILENCE_THRESHOLD_LEVEL"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"DEFAULT_SLIDING_WINDOW_MAX_WEIGHT"},{"p":"com.google.android.exoplayer2.upstream","c":"UdpDataSource","l":"DEFAULT_SOCKET_TIMEOUT_MILLIS"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_TARGET_BUFFER_BYTES"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl","l":"DEFAULT_TARGET_LIVE_OFFSET_INCREMENT_ON_REBUFFER_MS"},{"p":"com.google.android.exoplayer2.testutil","c":"DumpFileAsserts","l":"DEFAULT_TEST_ASSET_DIRECTORY"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_TEXT_BUFFER_SIZE"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"DEFAULT_TEXT_SIZE_FRACTION"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"DEFAULT_TIME_BAR_MIN_UPDATE_INTERVAL_MS"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"DEFAULT_TIME_BAR_MIN_UPDATE_INTERVAL_MS"},{"p":"com.google.android.exoplayer2.robolectric","c":"RobolectricUtil","l":"DEFAULT_TIMEOUT_MS"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource","l":"DEFAULT_TIMEOUT_MS"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"DEFAULT_TIMESTAMP_SEARCH_BYTES"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DEFAULT_TOUCH_TARGET_HEIGHT_DP"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultLoadErrorHandlingPolicy","l":"DEFAULT_TRACK_BLACKLIST_MS"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultLoadErrorHandlingPolicy","l":"DEFAULT_TRACK_EXCLUSION_MS"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"DEFAULT_TRACK_SELECTOR_PARAMETERS"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"DEFAULT_TRACK_SELECTOR_PARAMETERS_WITHOUT_CONTEXT"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"DEFAULT_TRACK_SELECTOR_PARAMETERS_WITHOUT_VIEWPORT"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DEFAULT_UNPLAYED_COLOR"},{"p":"com.google.android.exoplayer2","c":"ExoPlayerLibraryInfo","l":"DEFAULT_USER_AGENT"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DEFAULT_VIDEO_BUFFER_SIZE"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"BaseUrl","l":"DEFAULT_WEIGHT"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"DEFAULT_WINDOW_DURATION_US"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"DEFAULT_WITHOUT_CONTEXT"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"DEFAULT_WITHOUT_CONTEXT"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultAllocator","l":"DefaultAllocator(boolean, int, int)","url":"%3Cinit%3E(boolean,int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultAllocator","l":"DefaultAllocator(boolean, int)","url":"%3Cinit%3E(boolean,int)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.DefaultAllowedCommandProvider","l":"DefaultAllowedCommandProvider(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink.DefaultAudioProcessorChain","l":"DefaultAudioProcessorChain(AudioProcessor...)","url":"%3Cinit%3E(com.google.android.exoplayer2.audio.AudioProcessor...)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink.DefaultAudioProcessorChain","l":"DefaultAudioProcessorChain(AudioProcessor[], SilenceSkippingAudioProcessor, SonicAudioProcessor)","url":"%3Cinit%3E(com.google.android.exoplayer2.audio.AudioProcessor[],com.google.android.exoplayer2.audio.SilenceSkippingAudioProcessor,com.google.android.exoplayer2.audio.SonicAudioProcessor)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"DefaultAudioSink(AudioCapabilities, AudioProcessor[], boolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.audio.AudioCapabilities,com.google.android.exoplayer2.audio.AudioProcessor[],boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"DefaultAudioSink(AudioCapabilities, AudioProcessor[])","url":"%3Cinit%3E(com.google.android.exoplayer2.audio.AudioCapabilities,com.google.android.exoplayer2.audio.AudioProcessor[])"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"DefaultAudioSink(AudioCapabilities, DefaultAudioSink.AudioProcessorChain, boolean, boolean, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.audio.AudioCapabilities,com.google.android.exoplayer2.audio.DefaultAudioSink.AudioProcessorChain,boolean,boolean,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"DefaultBandwidthMeter()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"DefaultCastOptionsProvider","l":"DefaultCastOptionsProvider()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source","c":"DefaultCompositeSequenceableLoaderFactory","l":"DefaultCompositeSequenceableLoaderFactory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"DefaultContentMetadata","l":"DefaultContentMetadata()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"DefaultContentMetadata","l":"DefaultContentMetadata(Map)","url":"%3Cinit%3E(java.util.Map)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"DefaultControlDispatcher()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"DefaultControlDispatcher(long, long)","url":"%3Cinit%3E(long,long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"DefaultDashChunkSource(ChunkExtractor.Factory, LoaderErrorThrower, DashManifest, BaseUrlExclusionList, int, int[], ExoTrackSelection, int, DataSource, long, int, boolean, List, PlayerEmsgHandler.PlayerTrackEmsgHandler)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.chunk.ChunkExtractor.Factory,com.google.android.exoplayer2.upstream.LoaderErrorThrower,com.google.android.exoplayer2.source.dash.manifest.DashManifest,com.google.android.exoplayer2.source.dash.BaseUrlExclusionList,int,int[],com.google.android.exoplayer2.trackselection.ExoTrackSelection,int,com.google.android.exoplayer2.upstream.DataSource,long,int,boolean,java.util.List,com.google.android.exoplayer2.source.dash.PlayerEmsgHandler.PlayerTrackEmsgHandler)"},{"p":"com.google.android.exoplayer2.database","c":"DefaultDatabaseProvider","l":"DefaultDatabaseProvider(SQLiteOpenHelper)","url":"%3Cinit%3E(android.database.sqlite.SQLiteOpenHelper)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSource","l":"DefaultDataSource(Context, boolean)","url":"%3Cinit%3E(android.content.Context,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSource","l":"DefaultDataSource(Context, DataSource)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.upstream.DataSource)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSource","l":"DefaultDataSource(Context, String, boolean)","url":"%3Cinit%3E(android.content.Context,java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSource","l":"DefaultDataSource(Context, String, int, int, boolean)","url":"%3Cinit%3E(android.content.Context,java.lang.String,int,int,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSourceFactory","l":"DefaultDataSourceFactory(Context, DataSource.Factory)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSourceFactory","l":"DefaultDataSourceFactory(Context, String, TransferListener)","url":"%3Cinit%3E(android.content.Context,java.lang.String,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSourceFactory","l":"DefaultDataSourceFactory(Context, String)","url":"%3Cinit%3E(android.content.Context,java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSourceFactory","l":"DefaultDataSourceFactory(Context, TransferListener, DataSource.Factory)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.upstream.TransferListener,com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSourceFactory","l":"DefaultDataSourceFactory(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloaderFactory","l":"DefaultDownloaderFactory(CacheDataSource.Factory, Executor)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloaderFactory","l":"DefaultDownloaderFactory(CacheDataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory)"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloadIndex","l":"DefaultDownloadIndex(DatabaseProvider, String)","url":"%3Cinit%3E(com.google.android.exoplayer2.database.DatabaseProvider,java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloadIndex","l":"DefaultDownloadIndex(DatabaseProvider)","url":"%3Cinit%3E(com.google.android.exoplayer2.database.DatabaseProvider)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"DefaultDrmSessionManager(UUID, ExoMediaDrm, MediaDrmCallback, HashMap, boolean, int)","url":"%3Cinit%3E(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm,com.google.android.exoplayer2.drm.MediaDrmCallback,java.util.HashMap,boolean,int)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"DefaultDrmSessionManager(UUID, ExoMediaDrm, MediaDrmCallback, HashMap, boolean)","url":"%3Cinit%3E(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm,com.google.android.exoplayer2.drm.MediaDrmCallback,java.util.HashMap,boolean)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"DefaultDrmSessionManager(UUID, ExoMediaDrm, MediaDrmCallback, HashMap)","url":"%3Cinit%3E(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm,com.google.android.exoplayer2.drm.MediaDrmCallback,java.util.HashMap)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManagerProvider","l":"DefaultDrmSessionManagerProvider()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"DefaultExtractorInput(DataReader, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataReader,long,long)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"DefaultExtractorsFactory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.hls","c":"DefaultHlsDataSourceFactory","l":"DefaultHlsDataSourceFactory(DataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.hls","c":"DefaultHlsExtractorFactory","l":"DefaultHlsExtractorFactory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.hls","c":"DefaultHlsExtractorFactory","l":"DefaultHlsExtractorFactory(int, boolean)","url":"%3Cinit%3E(int,boolean)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistParserFactory","l":"DefaultHlsPlaylistParserFactory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"DefaultHlsPlaylistTracker(HlsDataSourceFactory, LoadErrorHandlingPolicy, HlsPlaylistParserFactory, double)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.hls.HlsDataSourceFactory,com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy,com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParserFactory,double)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"DefaultHlsPlaylistTracker(HlsDataSourceFactory, LoadErrorHandlingPolicy, HlsPlaylistParserFactory)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.hls.HlsDataSourceFactory,com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy,com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParserFactory)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"DefaultHttpDataSource()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"DefaultHttpDataSource(String, int, int, boolean, HttpDataSource.RequestProperties)","url":"%3Cinit%3E(java.lang.String,int,int,boolean,com.google.android.exoplayer2.upstream.HttpDataSource.RequestProperties)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"DefaultHttpDataSource(String, int, int)","url":"%3Cinit%3E(java.lang.String,int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"DefaultHttpDataSource(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSourceFactory","l":"DefaultHttpDataSourceFactory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSourceFactory","l":"DefaultHttpDataSourceFactory(String, int, int, boolean)","url":"%3Cinit%3E(java.lang.String,int,int,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSourceFactory","l":"DefaultHttpDataSourceFactory(String, TransferListener, int, int, boolean)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.upstream.TransferListener,int,int,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSourceFactory","l":"DefaultHttpDataSourceFactory(String, TransferListener)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSourceFactory","l":"DefaultHttpDataSourceFactory(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"TrackEncryptionBox","l":"defaultInitializationVector"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DefaultLoadControl()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"DefaultLoadControl(DefaultAllocator, int, int, int, int, int, boolean, int, boolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DefaultAllocator,int,int,int,int,int,boolean,int,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultLoadErrorHandlingPolicy","l":"DefaultLoadErrorHandlingPolicy()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultLoadErrorHandlingPolicy","l":"DefaultLoadErrorHandlingPolicy(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultMediaDescriptionAdapter","l":"DefaultMediaDescriptionAdapter(PendingIntent)","url":"%3Cinit%3E(android.app.PendingIntent)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"DefaultMediaItemConverter","l":"DefaultMediaItemConverter()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"DefaultMediaItemConverter","l":"DefaultMediaItemConverter()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.DefaultMediaMetadataProvider","l":"DefaultMediaMetadataProvider(MediaControllerCompat, String)","url":"%3Cinit%3E(android.support.v4.media.session.MediaControllerCompat,java.lang.String)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"DefaultMediaSourceFactory(Context, ExtractorsFactory)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.extractor.ExtractorsFactory)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"DefaultMediaSourceFactory(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"DefaultMediaSourceFactory(DataSource.Factory, ExtractorsFactory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.extractor.ExtractorsFactory)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"DefaultMediaSourceFactory(DataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.analytics","c":"DefaultPlaybackSessionManager","l":"DefaultPlaybackSessionManager()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.analytics","c":"DefaultPlaybackSessionManager","l":"DefaultPlaybackSessionManager(Supplier)","url":"%3Cinit%3E(com.google.common.base.Supplier)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"defaultPositionUs"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"defaultPositionUs"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"DefaultRenderersFactory(Context, int, long)","url":"%3Cinit%3E(android.content.Context,int,long)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"DefaultRenderersFactory(Context, int)","url":"%3Cinit%3E(android.content.Context,int)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"DefaultRenderersFactory(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.testutil","c":"DefaultRenderersFactoryAsserts","l":"DefaultRenderersFactoryAsserts()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","c":"DefaultRtpPayloadReaderFactory","l":"DefaultRtpPayloadReaderFactory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.DefaultSeekTimestampConverter","l":"DefaultSeekTimestampConverter()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.DefaultShuffleOrder","l":"DefaultShuffleOrder(int, long)","url":"%3Cinit%3E(int,long)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.DefaultShuffleOrder","l":"DefaultShuffleOrder(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.DefaultShuffleOrder","l":"DefaultShuffleOrder(int[], long)","url":"%3Cinit%3E(int[],long)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource","l":"DefaultSsChunkSource(LoaderErrorThrower, SsManifest, int, ExoTrackSelection, DataSource)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.LoaderErrorThrower,com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest,int,com.google.android.exoplayer2.trackselection.ExoTrackSelection,com.google.android.exoplayer2.upstream.DataSource)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DefaultTimeBar(Context, AttributeSet, int, AttributeSet, int)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet,int,android.util.AttributeSet,int)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DefaultTimeBar(Context, AttributeSet, int, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet,int,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DefaultTimeBar(Context, AttributeSet, int)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet,int)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DefaultTimeBar(Context, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"DefaultTimeBar(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTrackNameProvider","l":"DefaultTrackNameProvider(Resources)","url":"%3Cinit%3E(android.content.res.Resources)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"DefaultTrackSelector()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"DefaultTrackSelector(Context, ExoTrackSelection.Factory)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.trackselection.ExoTrackSelection.Factory)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"DefaultTrackSelector(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"DefaultTrackSelector(DefaultTrackSelector.Parameters, ExoTrackSelection.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters,com.google.android.exoplayer2.trackselection.ExoTrackSelection.Factory)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"DefaultTrackSelector(ExoTrackSelection.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.trackselection.ExoTrackSelection.Factory)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DefaultTsPayloadReaderFactory","l":"DefaultTsPayloadReaderFactory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DefaultTsPayloadReaderFactory","l":"DefaultTsPayloadReaderFactory(int, List)","url":"%3Cinit%3E(int,java.util.List)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DefaultTsPayloadReaderFactory","l":"DefaultTsPayloadReaderFactory(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection.Definition","l":"Definition(TrackGroup, int...)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroup,int...)"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection.Definition","l":"Definition(TrackGroup, int[], int)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroup,int[],int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"delay(long)"},{"p":"com.google.android.exoplayer2.util","c":"AtomicFile","l":"delete()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"delete(File, DatabaseProvider)","url":"delete(java.io.File,com.google.android.exoplayer2.database.DatabaseProvider)"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"deltaPicOrderAlwaysZeroFlag"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistParser.DeltaUpdateException","l":"DeltaUpdateException()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"depth"},{"p":"com.google.android.exoplayer2.decoder","c":"Decoder","l":"dequeueInputBuffer()"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleDecoder","l":"dequeueInputBuffer()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"dequeueInputBufferIndex()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"dequeueInputBufferIndex()"},{"p":"com.google.android.exoplayer2.decoder","c":"Decoder","l":"dequeueOutputBuffer()"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleDecoder","l":"dequeueOutputBuffer()"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea608Decoder","l":"dequeueOutputBuffer()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"dequeueOutputBufferIndex(MediaCodec.BufferInfo)","url":"dequeueOutputBufferIndex(android.media.MediaCodec.BufferInfo)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"dequeueOutputBufferIndex(MediaCodec.BufferInfo)","url":"dequeueOutputBufferIndex(android.media.MediaCodec.BufferInfo)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"describeContents()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"describeContents()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","c":"AppInfoTable","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"VorbisComment","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyInfo","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"Id3Frame","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"MlltFrame","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MdtaMetadataEntry","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MotionPhotoMetadata","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData.Segment","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SmtaMetadataEntry","l":"describeContents()"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceCommand","l":"describeContents()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"describeContents()"},{"p":"com.google.android.exoplayer2.offline","c":"StreamKey","l":"describeContents()"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"describeContents()"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroup","l":"describeContents()"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroupArray","l":"describeContents()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry","l":"describeContents()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry.VariantInfo","l":"describeContents()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"describeContents()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.SelectionOverride","l":"describeContents()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"describeContents()"},{"p":"com.google.android.exoplayer2.video","c":"ColorInfo","l":"describeContents()"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"description"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"description"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ApicFrame","l":"description"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"CommentFrame","l":"description"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"GeobFrame","l":"description"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"InternalFrame","l":"description"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"TextInformationFrame","l":"description"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"UrlLinkFrame","l":"description"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Descriptor","l":"Descriptor(String, String, String)","url":"%3Cinit%3E(java.lang.String,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.EsInfo","l":"descriptorBytes"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"DEVICE"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"DEVICE_CHARGING"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"DEVICE_DEBUG_INFO"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"DEVICE_IDLE"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"DEVICE_STORAGE_NOT_LOW"},{"p":"com.google.android.exoplayer2.device","c":"DeviceInfo","l":"DeviceInfo(@com.google.android.exoplayer2.device.DeviceInfo.PlaybackType int, int, int)","url":"%3Cinit%3E(@com.google.android.exoplayer2.device.DeviceInfo.PlaybackTypeint,int,int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecDecoderException","l":"diagnosticInfo"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer.DecoderInitializationException","l":"diagnosticInfo"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"DIMEN_UNSET"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"disable()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"disable()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"disable()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"disable()"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"disable()"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"disable()"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"disable()"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"disable(MediaSource.MediaSourceCaller)","url":"disable(com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"disable(MediaSource.MediaSourceCaller)","url":"disable(com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller)"},{"p":"com.google.android.exoplayer2.util","c":"NetworkTypeObserver.Config","l":"disable5GNsaDisambiguation()"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"disableChildSource(T)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener.EventDispatcher","l":"disabled(DecoderCounters)","url":"disabled(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener.EventDispatcher","l":"disabled(DecoderCounters)","url":"disabled(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"disabledTextTrackSelectionFlags"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"disableInternal()"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"disableInternal()"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"disableInternal()"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsMediaSource","l":"disableInternal()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"disableRenderer(int)"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"disableSeeking()"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"disableSeeking()"},{"p":"com.google.android.exoplayer2.source","c":"BundledExtractorsAdapter","l":"disableSeekingOnMp3Streams()"},{"p":"com.google.android.exoplayer2.source","c":"MediaParserExtractorAdapter","l":"disableSeekingOnMp3Streams()"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaExtractor","l":"disableSeekingOnMp3Streams()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"disableTunneling()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"disableTunneling()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"disableTunneling()"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_APP_OVERRIDE"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_AUDIO_CHANNEL_COUNT_CHANGED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_AUDIO_ENCODING_CHANGED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_AUDIO_SAMPLE_RATE_CHANGED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_DRM_SESSION_CHANGED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_INITIALIZATION_DATA_CHANGED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_MAX_INPUT_SIZE_EXCEEDED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_MIME_TYPE_CHANGED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_OPERATING_RATE_CHANGED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_REUSE_NOT_IMPLEMENTED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_VIDEO_COLOR_INFO_CHANGED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_VIDEO_MAX_RESOLUTION_EXCEEDED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_VIDEO_RESOLUTION_CHANGED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_VIDEO_ROTATION_CHANGED"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"DISCARD_REASON_WORKAROUND"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"discardBuffer(long, boolean)","url":"discardBuffer(long,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"discardBuffer(long, boolean)","url":"discardBuffer(long,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"discardBuffer(long, boolean)","url":"discardBuffer(long,boolean)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"discardBuffer(long, boolean)","url":"discardBuffer(long,boolean)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"discardBuffer(long, boolean)","url":"discardBuffer(long,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"discardBuffer(long, boolean)","url":"discardBuffer(long,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"discardBuffer(long, boolean)","url":"discardBuffer(long,boolean)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"discardReasons"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"discardSampleMetadataToRead()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"discardTo(long, boolean, boolean)","url":"discardTo(long,boolean,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"discardTo(long, boolean)","url":"discardTo(long,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"discardToEnd()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"discardToRead()"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil","l":"discardToSps(ByteBuffer)","url":"discardToSps(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"discardUpstreamFrom(long)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"discardUpstreamSamples(int)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"discNumber"},{"p":"com.google.android.exoplayer2","c":"Player","l":"DISCONTINUITY_REASON_AUTO_TRANSITION"},{"p":"com.google.android.exoplayer2","c":"Player","l":"DISCONTINUITY_REASON_INTERNAL"},{"p":"com.google.android.exoplayer2","c":"Player","l":"DISCONTINUITY_REASON_REMOVE"},{"p":"com.google.android.exoplayer2","c":"Player","l":"DISCONTINUITY_REASON_SEEK"},{"p":"com.google.android.exoplayer2","c":"Player","l":"DISCONTINUITY_REASON_SEEK_ADJUSTMENT"},{"p":"com.google.android.exoplayer2","c":"Player","l":"DISCONTINUITY_REASON_SKIP"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"discontinuitySequence"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher","l":"dispatch(RecordedRequest)","url":"dispatch(okhttp3.mockwebserver.RecordedRequest)"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"dispatchFastForward(Player)","url":"dispatchFastForward(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"dispatchFastForward(Player)","url":"dispatchFastForward(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"dispatchKeyEvent(KeyEvent)","url":"dispatchKeyEvent(android.view.KeyEvent)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"dispatchKeyEvent(KeyEvent)","url":"dispatchKeyEvent(android.view.KeyEvent)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"dispatchKeyEvent(KeyEvent)","url":"dispatchKeyEvent(android.view.KeyEvent)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"dispatchKeyEvent(KeyEvent)","url":"dispatchKeyEvent(android.view.KeyEvent)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"dispatchMediaKeyEvent(KeyEvent)","url":"dispatchMediaKeyEvent(android.view.KeyEvent)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"dispatchMediaKeyEvent(KeyEvent)","url":"dispatchMediaKeyEvent(android.view.KeyEvent)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"dispatchMediaKeyEvent(KeyEvent)","url":"dispatchMediaKeyEvent(android.view.KeyEvent)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"dispatchMediaKeyEvent(KeyEvent)","url":"dispatchMediaKeyEvent(android.view.KeyEvent)"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"dispatchNext(Player)","url":"dispatchNext(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"dispatchNext(Player)","url":"dispatchNext(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"dispatchPrepare(Player)","url":"dispatchPrepare(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"dispatchPrepare(Player)","url":"dispatchPrepare(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"dispatchPrevious(Player)","url":"dispatchPrevious(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"dispatchPrevious(Player)","url":"dispatchPrevious(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"dispatchRewind(Player)","url":"dispatchRewind(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"dispatchRewind(Player)","url":"dispatchRewind(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"dispatchSeekTo(Player, int, long)","url":"dispatchSeekTo(com.google.android.exoplayer2.Player,int,long)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"dispatchSeekTo(Player, int, long)","url":"dispatchSeekTo(com.google.android.exoplayer2.Player,int,long)"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"dispatchSetPlaybackParameters(Player, PlaybackParameters)","url":"dispatchSetPlaybackParameters(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"dispatchSetPlaybackParameters(Player, PlaybackParameters)","url":"dispatchSetPlaybackParameters(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"dispatchSetPlayWhenReady(Player, boolean)","url":"dispatchSetPlayWhenReady(com.google.android.exoplayer2.Player,boolean)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"dispatchSetPlayWhenReady(Player, boolean)","url":"dispatchSetPlayWhenReady(com.google.android.exoplayer2.Player,boolean)"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"dispatchSetRepeatMode(Player, int)","url":"dispatchSetRepeatMode(com.google.android.exoplayer2.Player,int)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"dispatchSetRepeatMode(Player, int)","url":"dispatchSetRepeatMode(com.google.android.exoplayer2.Player,int)"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"dispatchSetShuffleModeEnabled(Player, boolean)","url":"dispatchSetShuffleModeEnabled(com.google.android.exoplayer2.Player,boolean)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"dispatchSetShuffleModeEnabled(Player, boolean)","url":"dispatchSetShuffleModeEnabled(com.google.android.exoplayer2.Player,boolean)"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"dispatchStop(Player, boolean)","url":"dispatchStop(com.google.android.exoplayer2.Player,boolean)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"dispatchStop(Player, boolean)","url":"dispatchStop(com.google.android.exoplayer2.Player,boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"dispatchTouchEvent(MotionEvent)","url":"dispatchTouchEvent(android.view.MotionEvent)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"displayHeight"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"displayTitle"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"displayWidth"},{"p":"com.google.android.exoplayer2.testutil","c":"Action","l":"doActionAndScheduleNext(SimpleExoPlayer, DefaultTrackSelector, Surface, HandlerWrapper, ActionSchedule.ActionNode)","url":"doActionAndScheduleNext(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface,com.google.android.exoplayer2.util.HandlerWrapper,com.google.android.exoplayer2.testutil.ActionSchedule.ActionNode)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action","l":"doActionAndScheduleNextImpl(SimpleExoPlayer, DefaultTrackSelector, Surface, HandlerWrapper, ActionSchedule.ActionNode)","url":"doActionAndScheduleNextImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface,com.google.android.exoplayer2.util.HandlerWrapper,com.google.android.exoplayer2.testutil.ActionSchedule.ActionNode)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.PlayUntilPosition","l":"doActionAndScheduleNextImpl(SimpleExoPlayer, DefaultTrackSelector, Surface, HandlerWrapper, ActionSchedule.ActionNode)","url":"doActionAndScheduleNextImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface,com.google.android.exoplayer2.util.HandlerWrapper,com.google.android.exoplayer2.testutil.ActionSchedule.ActionNode)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForIsLoading","l":"doActionAndScheduleNextImpl(SimpleExoPlayer, DefaultTrackSelector, Surface, HandlerWrapper, ActionSchedule.ActionNode)","url":"doActionAndScheduleNextImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface,com.google.android.exoplayer2.util.HandlerWrapper,com.google.android.exoplayer2.testutil.ActionSchedule.ActionNode)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForMessage","l":"doActionAndScheduleNextImpl(SimpleExoPlayer, DefaultTrackSelector, Surface, HandlerWrapper, ActionSchedule.ActionNode)","url":"doActionAndScheduleNextImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface,com.google.android.exoplayer2.util.HandlerWrapper,com.google.android.exoplayer2.testutil.ActionSchedule.ActionNode)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForPendingPlayerCommands","l":"doActionAndScheduleNextImpl(SimpleExoPlayer, DefaultTrackSelector, Surface, HandlerWrapper, ActionSchedule.ActionNode)","url":"doActionAndScheduleNextImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface,com.google.android.exoplayer2.util.HandlerWrapper,com.google.android.exoplayer2.testutil.ActionSchedule.ActionNode)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForPlayWhenReady","l":"doActionAndScheduleNextImpl(SimpleExoPlayer, DefaultTrackSelector, Surface, HandlerWrapper, ActionSchedule.ActionNode)","url":"doActionAndScheduleNextImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface,com.google.android.exoplayer2.util.HandlerWrapper,com.google.android.exoplayer2.testutil.ActionSchedule.ActionNode)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForPlaybackState","l":"doActionAndScheduleNextImpl(SimpleExoPlayer, DefaultTrackSelector, Surface, HandlerWrapper, ActionSchedule.ActionNode)","url":"doActionAndScheduleNextImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface,com.google.android.exoplayer2.util.HandlerWrapper,com.google.android.exoplayer2.testutil.ActionSchedule.ActionNode)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForPositionDiscontinuity","l":"doActionAndScheduleNextImpl(SimpleExoPlayer, DefaultTrackSelector, Surface, HandlerWrapper, ActionSchedule.ActionNode)","url":"doActionAndScheduleNextImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface,com.google.android.exoplayer2.util.HandlerWrapper,com.google.android.exoplayer2.testutil.ActionSchedule.ActionNode)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForTimelineChanged","l":"doActionAndScheduleNextImpl(SimpleExoPlayer, DefaultTrackSelector, Surface, HandlerWrapper, ActionSchedule.ActionNode)","url":"doActionAndScheduleNextImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface,com.google.android.exoplayer2.util.HandlerWrapper,com.google.android.exoplayer2.testutil.ActionSchedule.ActionNode)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.AddMediaItems","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.ClearMediaItems","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.ClearVideoSurface","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.ExecuteRunnable","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.MoveMediaItem","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.PlayUntilPosition","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.Prepare","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.RemoveMediaItem","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.RemoveMediaItems","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.Seek","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SendMessages","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetAudioAttributes","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetMediaItems","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetMediaItemsResetPosition","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetPlayWhenReady","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetPlaybackParameters","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetRendererDisabled","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetRepeatMode","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetShuffleModeEnabled","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetShuffleOrder","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetVideoSurface","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.Stop","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.ThrowPlaybackException","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForIsLoading","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForMessage","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForPendingPlayerCommands","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForPlayWhenReady","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForPlaybackState","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForPositionDiscontinuity","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForTimelineChanged","l":"doActionImpl(SimpleExoPlayer, DefaultTrackSelector, Surface)","url":"doActionImpl(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,android.view.Surface)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"InternalFrame","l":"domain"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"DONT_RETRY"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"DONT_RETRY_FATAL"},{"p":"com.google.android.exoplayer2.offline","c":"Downloader","l":"download(Downloader.ProgressListener)","url":"download(com.google.android.exoplayer2.offline.Downloader.ProgressListener)"},{"p":"com.google.android.exoplayer2.offline","c":"ProgressiveDownloader","l":"download(Downloader.ProgressListener)","url":"download(com.google.android.exoplayer2.offline.Downloader.ProgressListener)"},{"p":"com.google.android.exoplayer2.offline","c":"SegmentDownloader","l":"download(Downloader.ProgressListener)","url":"download(com.google.android.exoplayer2.offline.Downloader.ProgressListener)"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"Download(DownloadRequest, int, long, long, long, int, int, DownloadProgress)","url":"%3Cinit%3E(com.google.android.exoplayer2.offline.DownloadRequest,int,long,long,long,int,int,com.google.android.exoplayer2.offline.DownloadProgress)"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"Download(DownloadRequest, int, long, long, long, int, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.offline.DownloadRequest,int,long,long,long,int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"DownloadBuilder(DownloadRequest)","url":"%3Cinit%3E(com.google.android.exoplayer2.offline.DownloadRequest)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"DownloadBuilder(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadException","l":"DownloadException(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadException","l":"DownloadException(Throwable)","url":"%3Cinit%3E(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"DownloadHelper(MediaItem, MediaSource, DefaultTrackSelector.Parameters, RendererCapabilities[])","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.source.MediaSource,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters,com.google.android.exoplayer2.RendererCapabilities[])"},{"p":"com.google.android.exoplayer2.drm","c":"OfflineLicenseHelper","l":"downloadLicense(Format)","url":"downloadLicense(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"DownloadManager(Context, DatabaseProvider, Cache, DataSource.Factory, Executor)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.database.DatabaseProvider,com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.DataSource.Factory,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"DownloadManager(Context, DatabaseProvider, Cache, DataSource.Factory)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.database.DatabaseProvider,com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"DownloadManager(Context, WritableDownloadIndex, DownloaderFactory)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.offline.WritableDownloadIndex,com.google.android.exoplayer2.offline.DownloaderFactory)"},{"p":"com.google.android.exoplayer2.ui","c":"DownloadNotificationHelper","l":"DownloadNotificationHelper(Context, String)","url":"%3Cinit%3E(android.content.Context,java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadProgress","l":"DownloadProgress()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"DownloadService(int, long, String, int, int)","url":"%3Cinit%3E(int,long,java.lang.String,int,int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"DownloadService(int, long, String, int)","url":"%3Cinit%3E(int,long,java.lang.String,int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"DownloadService(int, long)","url":"%3Cinit%3E(int,long)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"DownloadService(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"downstreamFormatChanged(int, Format, int, Object, long)","url":"downstreamFormatChanged(int,com.google.android.exoplayer2.Format,int,java.lang.Object,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"downstreamFormatChanged(MediaLoadData)","url":"downstreamFormatChanged(com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.ext.workmanager","c":"WorkManagerScheduler.SchedulerWorker","l":"doWork()"},{"p":"com.google.android.exoplayer2.util","c":"RunnableFutureTask","l":"doWork()"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"drawableStateChanged()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionManager","l":"DRM_UNSUPPORTED"},{"p":"com.google.android.exoplayer2","c":"MediaItem.PlaybackProperties","l":"drmConfiguration"},{"p":"com.google.android.exoplayer2","c":"Format","l":"drmInitData"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.SegmentBase","l":"drmInitData"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"DrmInitData(DrmInitData.SchemeData...)","url":"%3Cinit%3E(com.google.android.exoplayer2.drm.DrmInitData.SchemeData...)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"DrmInitData(List)","url":"%3Cinit%3E(java.util.List)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"DrmInitData(String, DrmInitData.SchemeData...)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.drm.DrmInitData.SchemeData...)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"DrmInitData(String, List)","url":"%3Cinit%3E(java.lang.String,java.util.List)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener.EventDispatcher","l":"drmKeysLoaded()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener.EventDispatcher","l":"drmKeysRemoved()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener.EventDispatcher","l":"drmKeysRestored()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser.RepresentationInfo","l":"drmSchemeDatas"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser.RepresentationInfo","l":"drmSchemeType"},{"p":"com.google.android.exoplayer2","c":"FormatHolder","l":"drmSession"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener.EventDispatcher","l":"drmSessionAcquired(int)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession.DrmSessionException","l":"DrmSessionException(Throwable, int)","url":"%3Cinit%3E(java.lang.Throwable,int)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener.EventDispatcher","l":"drmSessionManagerError(Exception)","url":"drmSessionManagerError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener.EventDispatcher","l":"drmSessionReleased()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"dropOutputBuffer(MediaCodecAdapter, int, long)","url":"dropOutputBuffer(com.google.android.exoplayer2.mediacodec.MediaCodecAdapter,int,long)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"dropOutputBuffer(VideoDecoderOutputBuffer)","url":"dropOutputBuffer(com.google.android.exoplayer2.video.VideoDecoderOutputBuffer)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"droppedBufferCount"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener.EventDispatcher","l":"droppedFrames(int, long)","url":"droppedFrames(int,long)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"droppedToKeyframeCount"},{"p":"com.google.android.exoplayer2.audio","c":"DtsUtil","l":"DTS_HD_MAX_RATE_BYTES_PER_SECOND"},{"p":"com.google.android.exoplayer2.audio","c":"DtsUtil","l":"DTS_MAX_RATE_BYTES_PER_SECOND"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DtsReader","l":"DtsReader(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionManager","l":"DUMMY"},{"p":"com.google.android.exoplayer2.upstream","c":"LoaderErrorThrower.Dummy","l":"Dummy()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"DummyExoMediaDrm()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor","c":"DummyExtractorOutput","l":"DummyExtractorOutput()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"DummyMainThread","l":"DummyMainThread()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor","c":"DummyTrackOutput","l":"DummyTrackOutput()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.robolectric","c":"PlaybackOutput","l":"dump(Dumper)","url":"dump(com.google.android.exoplayer2.testutil.Dumper)"},{"p":"com.google.android.exoplayer2.testutil","c":"CapturingAudioSink","l":"dump(Dumper)","url":"dump(com.google.android.exoplayer2.testutil.Dumper)"},{"p":"com.google.android.exoplayer2.testutil","c":"CapturingRenderersFactory","l":"dump(Dumper)","url":"dump(com.google.android.exoplayer2.testutil.Dumper)"},{"p":"com.google.android.exoplayer2.testutil","c":"DumpableFormat","l":"dump(Dumper)","url":"dump(com.google.android.exoplayer2.testutil.Dumper)"},{"p":"com.google.android.exoplayer2.testutil","c":"Dumper.Dumpable","l":"dump(Dumper)","url":"dump(com.google.android.exoplayer2.testutil.Dumper)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorOutput","l":"dump(Dumper)","url":"dump(com.google.android.exoplayer2.testutil.Dumper)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"dump(Dumper)","url":"dump(com.google.android.exoplayer2.testutil.Dumper)"},{"p":"com.google.android.exoplayer2.testutil","c":"DumpableFormat","l":"DumpableFormat(Format, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"Dumper","l":"Dumper()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts.AssertionConfig","l":"dumpFilesPrefix"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"durationMs"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"durationMs"},{"p":"com.google.android.exoplayer2.extractor","c":"ChunkIndex","l":"durationsUs"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"durationsUs"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"durationUs"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"durationUs"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"durationUs"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"durationUs"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.SegmentBase","l":"durationUs"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest","l":"durationUs"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"durationUs"},{"p":"com.google.android.exoplayer2.text.dvb","c":"DvbDecoder","l":"DvbDecoder(List)","url":"%3Cinit%3E(java.util.List)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.DvbSubtitleInfo","l":"DvbSubtitleInfo(String, int, byte[])","url":"%3Cinit%3E(java.lang.String,int,byte[])"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.EsInfo","l":"dvbSubtitleInfos"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DvbSubtitleReader","l":"DvbSubtitleReader(List)","url":"%3Cinit%3E(java.util.List)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest","l":"dvrWindowLengthUs"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"dynamic"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"E_AC3_JOC_CODEC_STRING"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"E_AC3_MAX_RATE_BYTES_PER_SECOND"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"e(String, String, Throwable)","url":"e(java.lang.String,java.lang.String,java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"e(String, String)","url":"e(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"EDGE_TYPE_DEPRESSED"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"EDGE_TYPE_DROP_SHADOW"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"EDGE_TYPE_NONE"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"EDGE_TYPE_OUTLINE"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"EDGE_TYPE_RAISED"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"edgeColor"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"edgeType"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"editListDurations"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"editListMediaTimes"},{"p":"com.google.android.exoplayer2.audio","c":"AuxEffectInfo","l":"effectId"},{"p":"com.google.android.exoplayer2.util","c":"EGLSurfaceTexture","l":"EGLSurfaceTexture(Handler, EGLSurfaceTexture.TextureImageListener)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.util.EGLSurfaceTexture.TextureImageListener)"},{"p":"com.google.android.exoplayer2.util","c":"EGLSurfaceTexture","l":"EGLSurfaceTexture(Handler)","url":"%3Cinit%3E(android.os.Handler)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock","l":"elapsedRealtime()"},{"p":"com.google.android.exoplayer2.util","c":"Clock","l":"elapsedRealtime()"},{"p":"com.google.android.exoplayer2.util","c":"SystemClock","l":"elapsedRealtime()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"elapsedRealtimeEpochOffsetMs"},{"p":"com.google.android.exoplayer2.source","c":"LoadEventInfo","l":"elapsedRealtimeMs"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"ELEMENT_TYPE_BINARY"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"ELEMENT_TYPE_FLOAT"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"ELEMENT_TYPE_MASTER"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"ELEMENT_TYPE_STRING"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"ELEMENT_TYPE_UNKNOWN"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"ELEMENT_TYPE_UNSIGNED_INT"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterTocFrame","l":"elementId"},{"p":"com.google.android.exoplayer2.util","c":"CopyOnWriteMultiset","l":"elementSet()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream.EmbeddedSampleStream","l":"EmbeddedSampleStream(ChunkSampleStream, SampleQueue, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.chunk.ChunkSampleStream,com.google.android.exoplayer2.source.SampleQueue,int)"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"EMPTY"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"EMPTY"},{"p":"com.google.android.exoplayer2","c":"Player.Commands","l":"EMPTY"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"EMPTY"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"EMPTY"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionManager.DrmSessionReference","l":"EMPTY"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorsFactory","l":"EMPTY"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroupArray","l":"EMPTY"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaChunkIterator","l":"EMPTY"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"EMPTY"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"EMPTY"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"DefaultContentMetadata","l":"EMPTY"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor","l":"EMPTY_BUFFER"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"EMPTY_BYTE_ARRAY"},{"p":"com.google.android.exoplayer2.source","c":"EmptySampleStream","l":"EmptySampleStream()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"enable()"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"enable()"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"enable()"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"enable()"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"enable(MediaSource.MediaSourceCaller)","url":"enable(com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"enable(MediaSource.MediaSourceCaller)","url":"enable(com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"enable(RendererConfiguration, Format[], SampleStream, long, boolean, boolean, long, long)","url":"enable(com.google.android.exoplayer2.RendererConfiguration,com.google.android.exoplayer2.Format[],com.google.android.exoplayer2.source.SampleStream,long,boolean,boolean,long,long)"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"enable(RendererConfiguration, Format[], SampleStream, long, boolean, boolean, long, long)","url":"enable(com.google.android.exoplayer2.RendererConfiguration,com.google.android.exoplayer2.Format[],com.google.android.exoplayer2.source.SampleStream,long,boolean,boolean,long,long)"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"enable(RendererConfiguration, Format[], SampleStream, long, boolean, boolean, long, long)","url":"enable(com.google.android.exoplayer2.RendererConfiguration,com.google.android.exoplayer2.Format[],com.google.android.exoplayer2.source.SampleStream,long,boolean,boolean,long,long)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"enableChildSource(T)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"enableCount"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener.EventDispatcher","l":"enabled(DecoderCounters)","url":"enabled(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener.EventDispatcher","l":"enabled(DecoderCounters)","url":"enabled(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"enableInternal()"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"enableInternal()"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"enableInternal()"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsMediaSource","l":"enableInternal()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"enableRenderer(int)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"enableTunnelingV21()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"enableTunnelingV21()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"enableTunnelingV21()"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessageEncoder","l":"encode(EventMessage)","url":"encode(com.google.android.exoplayer2.metadata.emsg.EventMessage)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"encoderDelay"},{"p":"com.google.android.exoplayer2.extractor","c":"GaplessInfoHolder","l":"encoderDelay"},{"p":"com.google.android.exoplayer2","c":"Format","l":"encoderPadding"},{"p":"com.google.android.exoplayer2.extractor","c":"GaplessInfoHolder","l":"encoderPadding"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor.AudioFormat","l":"encoding"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_AAC_ELD"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_AAC_ER_BSAC"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_AAC_HE_V1"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_AAC_HE_V2"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_AAC_LC"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_AAC_XHE"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_AC3"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_AC4"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_DOLBY_TRUEHD"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_DTS"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_DTS_HD"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_E_AC3"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_E_AC3_JOC"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_INVALID"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_MP3"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_PCM_16BIT"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_PCM_16BIT_BIG_ENDIAN"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_PCM_24BIT"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_PCM_32BIT"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_PCM_8BIT"},{"p":"com.google.android.exoplayer2","c":"C","l":"ENCODING_PCM_FLOAT"},{"p":"com.google.android.exoplayer2.decoder","c":"CryptoInfo","l":"encryptedBlocks"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput.CryptoData","l":"encryptedBlocks"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.SegmentBase","l":"encryptionIV"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput.CryptoData","l":"encryptionKey"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream.FakeSampleStreamItem","l":"END_OF_STREAM_ITEM"},{"p":"com.google.android.exoplayer2.testutil","c":"Dumper","l":"endBlock()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData","l":"endData()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"endedCount"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"endMasterElement(int)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"endMasterElement(int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"endOffset"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkHolder","l":"endOfStream"},{"p":"com.google.android.exoplayer2","c":"MediaItem.ClippingProperties","l":"endPositionMs"},{"p":"com.google.android.exoplayer2.util","c":"TraceUtil","l":"endSection()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"endTimeMs"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData.Segment","l":"endTimeMs"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"endTimeUs"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCueInfo","l":"endTimeUs"},{"p":"com.google.android.exoplayer2.extractor","c":"DummyExtractorOutput","l":"endTracks()"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorOutput","l":"endTracks()"},{"p":"com.google.android.exoplayer2.extractor.jpeg","c":"StartOffsetExtractorOutput","l":"endTracks()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BundledChunkExtractor","l":"endTracks()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorOutput","l":"endTracks()"},{"p":"com.google.android.exoplayer2.util","c":"AtomicFile","l":"endWrite(OutputStream)","url":"endWrite(java.io.OutputStream)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"ensureCapacity(int)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"ensureSpaceForWrite(int)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"ensureUpdated()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"DefaultContentMetadata","l":"entrySet()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor.MediaIdEqualityChecker","l":"equals(MediaDescriptionCompat, MediaDescriptionCompat)","url":"equals(android.support.v4.media.MediaDescriptionCompat,android.support.v4.media.MediaDescriptionCompat)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"HeartRating","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.AdsConfiguration","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.ClippingProperties","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.DrmConfiguration","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.LiveConfiguration","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.PlaybackProperties","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Subtitle","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"PercentageRating","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"PlaybackParameters","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"Player.Commands","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"Player.Events","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"RendererConfiguration","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"SeekParameters","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"StarRating","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"ThumbRating","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndException","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndFormat","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndPlaybackState","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioCapabilities","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.audio","c":"AuxEffectInfo","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.device","c":"DeviceInfo","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap.SeekPoints","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekPoint","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput.CryptoData","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"VorbisComment","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyInfo","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ApicFrame","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"BinaryFrame","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterTocFrame","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"CommentFrame","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"GeobFrame","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"InternalFrame","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"MlltFrame","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"PrivFrame","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"TextInformationFrame","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"UrlLinkFrame","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MdtaMetadataEntry","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MotionPhotoMetadata","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData.Segment","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SmtaMetadataEntry","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.offline","c":"StreamKey","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroup","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroupArray","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"BaseUrl","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Descriptor","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ProgramInformation","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"RangedUri","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SegmentTimelineElement","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry.VariantInfo","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPayloadFormat","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.testutil","c":"DumpableFormat","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection.AdaptationCheckpoint","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.SelectionOverride","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionArray","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"DefaultContentMetadata","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.util","c":"FlagSet","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.video","c":"ColorInfo","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2.video","c":"VideoSize","l":"equals(Object)","url":"equals(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_AUDIO_TRACK_INIT_FAILED"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_AUDIO_TRACK_WRITE_FAILED"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_BEHIND_LIVE_WINDOW"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_DECODER_INIT_FAILED"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_DECODER_QUERY_FAILED"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_DECODING_FAILED"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_DECODING_FORMAT_EXCEEDS_CAPABILITIES"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_DECODING_FORMAT_UNSUPPORTED"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_DRM_CONTENT_ERROR"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_DRM_DEVICE_REVOKED"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_DRM_DISALLOWED_OPERATION"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_DRM_LICENSE_ACQUISITION_FAILED"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_DRM_LICENSE_EXPIRED"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_DRM_PROVISIONING_FAILED"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_DRM_SCHEME_UNSUPPORTED"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_DRM_SYSTEM_ERROR"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_DRM_UNSPECIFIED"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_FAILED_RUNTIME_CHECK"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_IO_BAD_HTTP_STATUS"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_IO_FILE_NOT_FOUND"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_IO_NETWORK_CONNECTION_FAILED"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_IO_NO_PERMISSION"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_IO_UNSPECIFIED"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_PARSING_CONTAINER_MALFORMED"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_PARSING_CONTAINER_UNSUPPORTED"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_PARSING_MANIFEST_MALFORMED"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_PARSING_MANIFEST_UNSUPPORTED"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_REMOTE_ERROR"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_TIMEOUT"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"ERROR_CODE_UNSPECIFIED"},{"p":"com.google.android.exoplayer2.drm","c":"DrmUtil","l":"ERROR_SOURCE_EXO_MEDIA_DRM"},{"p":"com.google.android.exoplayer2.drm","c":"DrmUtil","l":"ERROR_SOURCE_LICENSE_ACQUISITION"},{"p":"com.google.android.exoplayer2.drm","c":"DrmUtil","l":"ERROR_SOURCE_PROVISIONING"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"errorCode"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.WriteException","l":"errorCode"},{"p":"com.google.android.exoplayer2.drm","c":"DecryptionException","l":"errorCode"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession.DrmSessionException","l":"errorCode"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy.LoadErrorInfo","l":"errorCount"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"errorInfoEquals(PlaybackException)","url":"errorInfoEquals(com.google.android.exoplayer2.PlaybackException)"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"errorInfoEquals(PlaybackException)","url":"errorInfoEquals(com.google.android.exoplayer2.PlaybackException)"},{"p":"com.google.android.exoplayer2.drm","c":"ErrorStateDrmSession","l":"ErrorStateDrmSession(DrmSession.DrmSessionException)","url":"%3Cinit%3E(com.google.android.exoplayer2.drm.DrmSession.DrmSessionException)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"escapeFileName(String)","url":"escapeFileName(java.lang.String)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.EsInfo","l":"EsInfo(int, String, List, byte[])","url":"%3Cinit%3E(int,java.lang.String,java.util.List,byte[])"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"AdaptationSet","l":"essentialProperties"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"Id3Decoder.FramePredicate","l":"evaluate(int, int, int, int, int)","url":"evaluate(int,int,int,int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"evaluateQueueSize(long, List)","url":"evaluateQueueSize(long,java.util.List)"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"evaluateQueueSize(long, List)","url":"evaluateQueueSize(long,java.util.List)"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"evaluateQueueSize(long, List)","url":"evaluateQueueSize(long,java.util.List)"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"evaluateQueueSize(long, List)","url":"evaluateQueueSize(long,java.util.List)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_AUDIO_ATTRIBUTES_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_AUDIO_CODEC_ERROR"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_AUDIO_DECODER_INITIALIZED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_AUDIO_DECODER_RELEASED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_AUDIO_DISABLED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_AUDIO_ENABLED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_AUDIO_INPUT_FORMAT_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_AUDIO_POSITION_ADVANCING"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_AUDIO_SESSION_ID"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_AUDIO_SINK_ERROR"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_AUDIO_UNDERRUN"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_AVAILABLE_COMMANDS_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_AVAILABLE_COMMANDS_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_BANDWIDTH_ESTIMATE"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_DOWNSTREAM_FORMAT_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_DRM_KEYS_LOADED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_DRM_KEYS_REMOVED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_DRM_KEYS_RESTORED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_DRM_SESSION_ACQUIRED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_DRM_SESSION_MANAGER_ERROR"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_DRM_SESSION_RELEASED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_DROPPED_VIDEO_FRAMES"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_IS_LOADING_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_IS_LOADING_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_IS_PLAYING_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_IS_PLAYING_CHANGED"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"EVENT_KEY_EXPIRED"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"EVENT_KEY_REQUIRED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_LOAD_CANCELED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_LOAD_COMPLETED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_LOAD_ERROR"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_LOAD_STARTED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_MAX_SEEK_TO_PREVIOUS_POSITION_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_MAX_SEEK_TO_PREVIOUS_POSITION_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_MEDIA_ITEM_TRANSITION"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_MEDIA_ITEM_TRANSITION"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_MEDIA_METADATA_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_MEDIA_METADATA_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_METADATA"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_PLAY_WHEN_READY_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_PLAY_WHEN_READY_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_PLAYBACK_PARAMETERS_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_PLAYBACK_PARAMETERS_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_PLAYBACK_STATE_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_PLAYBACK_STATE_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_PLAYER_ERROR"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_PLAYER_ERROR"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_PLAYER_RELEASED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_PLAYLIST_METADATA_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_PLAYLIST_METADATA_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_POSITION_DISCONTINUITY"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_POSITION_DISCONTINUITY"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"EVENT_PROVISION_REQUIRED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_RENDERED_FIRST_FRAME"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_REPEAT_MODE_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_REPEAT_MODE_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_SEEK_BACK_INCREMENT_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_SEEK_BACK_INCREMENT_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_SEEK_FORWARD_INCREMENT_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_SEEK_FORWARD_INCREMENT_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_SHUFFLE_MODE_ENABLED_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_SHUFFLE_MODE_ENABLED_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_SKIP_SILENCE_ENABLED_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_STATIC_METADATA_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_STATIC_METADATA_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_SURFACE_SIZE_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_TIMELINE_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_TIMELINE_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"EVENT_TRACKS_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_TRACKS_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_UPSTREAM_DISCARDED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_VIDEO_CODEC_ERROR"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_VIDEO_DECODER_INITIALIZED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_VIDEO_DECODER_RELEASED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_VIDEO_DISABLED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_VIDEO_ENABLED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_VIDEO_FRAME_PROCESSING_OFFSET"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_VIDEO_INPUT_FORMAT_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_VIDEO_SIZE_CHANGED"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"EVENT_VOLUME_CHANGED"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener.EventDispatcher","l":"EventDispatcher()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"EventDispatcher()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"BandwidthMeter.EventListener.EventDispatcher","l":"EventDispatcher()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener.EventDispatcher","l":"EventDispatcher(Handler, AudioRendererEventListener)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener.EventDispatcher","l":"EventDispatcher(Handler, VideoRendererEventListener)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"EventLogger(MappingTrackSelector, String)","url":"%3Cinit%3E(com.google.android.exoplayer2.trackselection.MappingTrackSelector,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"EventLogger(MappingTrackSelector)","url":"%3Cinit%3E(com.google.android.exoplayer2.trackselection.MappingTrackSelector)"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"EventMessage(String, String, long, long, byte[])","url":"%3Cinit%3E(java.lang.String,java.lang.String,long,long,byte[])"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessageDecoder","l":"EventMessageDecoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessageEncoder","l":"EventMessageEncoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"eventPlaybackPositionMs"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand","l":"events"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"EventStream","l":"events"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.Events","l":"Events(FlagSet, SparseArray)","url":"%3Cinit%3E(com.google.android.exoplayer2.util.FlagSet,android.util.SparseArray)"},{"p":"com.google.android.exoplayer2","c":"Player.Events","l":"Events(FlagSet)","url":"%3Cinit%3E(com.google.android.exoplayer2.util.FlagSet)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"EventStream","l":"EventStream(String, String, long, long[], EventMessage[])","url":"%3Cinit%3E(java.lang.String,java.lang.String,long,long[],com.google.android.exoplayer2.metadata.emsg.EventMessage[])"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Period","l":"eventStreams"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndException","l":"eventTime"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndFormat","l":"eventTime"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndPlaybackState","l":"eventTime"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"EventTime(long, Timeline, int, MediaSource.MediaPeriodId, long, Timeline, int, MediaSource.MediaPeriodId, long, long)","url":"%3Cinit%3E(long,com.google.android.exoplayer2.Timeline,int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,long,com.google.android.exoplayer2.Timeline,int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,long,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndException","l":"EventTimeAndException(AnalyticsListener.EventTime, Exception)","url":"%3Cinit%3E(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndFormat","l":"EventTimeAndFormat(AnalyticsListener.EventTime, Format)","url":"%3Cinit%3E(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndPlaybackState","l":"EventTimeAndPlaybackState(AnalyticsListener.EventTime, @com.google.android.exoplayer2.analytics.PlaybackStats.PlaybackState int)","url":"%3Cinit%3E(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,@com.google.android.exoplayer2.analytics.PlaybackStats.PlaybackStateint)"},{"p":"com.google.android.exoplayer2","c":"SeekParameters","l":"EXACT"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"exceedAudioConstraintsIfNecessary"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"exceedRendererCapabilitiesIfNecessary"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"exceedVideoConstraintsIfNecessary"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndException","l":"exception"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData.Segment","l":"exception"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy.LoadErrorInfo","l":"exception"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData.Segment","l":"exceptionCleared"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData.Segment","l":"exceptionThrown"},{"p":"com.google.android.exoplayer2.source.dash","c":"BaseUrlExclusionList","l":"exclude(BaseUrl, long)","url":"exclude(com.google.android.exoplayer2.source.dash.manifest.BaseUrl,long)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"excludeMediaPlaylist(Uri, long)","url":"excludeMediaPlaylist(android.net.Uri,long)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"excludeMediaPlaylist(Uri, long)","url":"excludeMediaPlaylist(android.net.Uri,long)"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy.FallbackSelection","l":"exclusionDurationMs"},{"p":"com.google.android.exoplayer2.offline","c":"SegmentDownloader","l":"execute(RunnableFutureTask, boolean)","url":"execute(com.google.android.exoplayer2.util.RunnableFutureTask,boolean)"},{"p":"com.google.android.exoplayer2.drm","c":"HttpMediaDrmCallback","l":"executeKeyRequest(UUID, ExoMediaDrm.KeyRequest)","url":"executeKeyRequest(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm.KeyRequest)"},{"p":"com.google.android.exoplayer2.drm","c":"LocalMediaDrmCallback","l":"executeKeyRequest(UUID, ExoMediaDrm.KeyRequest)","url":"executeKeyRequest(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm.KeyRequest)"},{"p":"com.google.android.exoplayer2.drm","c":"MediaDrmCallback","l":"executeKeyRequest(UUID, ExoMediaDrm.KeyRequest)","url":"executeKeyRequest(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm.KeyRequest)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm.LicenseServer","l":"executeKeyRequest(UUID, ExoMediaDrm.KeyRequest)","url":"executeKeyRequest(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm.KeyRequest)"},{"p":"com.google.android.exoplayer2.drm","c":"HttpMediaDrmCallback","l":"executeProvisionRequest(UUID, ExoMediaDrm.ProvisionRequest)","url":"executeProvisionRequest(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm.ProvisionRequest)"},{"p":"com.google.android.exoplayer2.drm","c":"LocalMediaDrmCallback","l":"executeProvisionRequest(UUID, ExoMediaDrm.ProvisionRequest)","url":"executeProvisionRequest(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm.ProvisionRequest)"},{"p":"com.google.android.exoplayer2.drm","c":"MediaDrmCallback","l":"executeProvisionRequest(UUID, ExoMediaDrm.ProvisionRequest)","url":"executeProvisionRequest(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm.ProvisionRequest)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm.LicenseServer","l":"executeProvisionRequest(UUID, ExoMediaDrm.ProvisionRequest)","url":"executeProvisionRequest(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm.ProvisionRequest)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"executeRunnable(Runnable)","url":"executeRunnable(java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.ExecuteRunnable","l":"ExecuteRunnable(String, Runnable)","url":"%3Cinit%3E(java.lang.String,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.util","c":"AtomicFile","l":"exists()"},{"p":"com.google.android.exoplayer2.database","c":"ExoDatabaseProvider","l":"ExoDatabaseProvider(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"ExoHostedTest(String, boolean)","url":"%3Cinit%3E(java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"ExoHostedTest(String, long, boolean)","url":"%3Cinit%3E(java.lang.String,long,boolean)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"exoMediaCryptoType"},{"p":"com.google.android.exoplayer2","c":"ExoTimeoutException","l":"ExoTimeoutException(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"EXPECTED_PLAYING_TIME_MEDIA_DURATION_MS"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"EXPECTED_PLAYING_TIME_UNSET"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.UnexpectedDiscontinuityException","l":"expectedPresentationTimeUs"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"experimentalFlushWithoutAudioTrackRelease()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"experimentalFlushWithoutAudioTrackRelease()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"experimentalFlushWithoutAudioTrackRelease()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"experimentalIsSleepingForOffload()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"experimentalIsSleepingForOffload()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"experimentalIsSleepingForOffload()"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"experimentalSetAsynchronousBufferQueueingEnabled(boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"experimentalSetAsynchronousBufferQueueingEnabled(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"experimentalSetEnableKeepAudioTrackOnSeek(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"experimentalSetEnableKeepAudioTrackOnSeek(boolean)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"experimentalSetForceAsyncQueueingSynchronizationWorkaround(boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"experimentalSetForceAsyncQueueingSynchronizationWorkaround(boolean)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"experimentalSetForegroundModeTimeoutMs(long)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"experimentalSetForegroundModeTimeoutMs(long)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"experimentalSetOffloadSchedulingEnabled(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"experimentalSetOffloadSchedulingEnabled(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"experimentalSetOffloadSchedulingEnabled(boolean)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"experimentalSetSynchronizeCodecInteractionsWithQueueingEnabled(boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"experimentalSetSynchronizeCodecInteractionsWithQueueingEnabled(boolean)"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil","l":"EXTENDED_SAR"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"extension"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"EXTENSION_RENDERER_MODE_OFF"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"EXTENSION_RENDERER_MODE_ON"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"EXTENSION_RENDERER_MODE_PREFER"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor","l":"EXTRA_FROM_INDEX"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"EXTRA_INSTANCE_ID"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor","l":"EXTRA_TO_INDEX"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"extractAllSamplesFromFile(Extractor, Context, String)","url":"extractAllSamplesFromFile(com.google.android.exoplayer2.extractor.Extractor,android.content.Context,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"extractSeekMap(Extractor, FakeExtractorOutput, DataSource, Uri)","url":"extractSeekMap(com.google.android.exoplayer2.extractor.Extractor,com.google.android.exoplayer2.testutil.FakeExtractorOutput,com.google.android.exoplayer2.upstream.DataSource,android.net.Uri)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"extras"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"EXTRAS_SPEED"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.amr","c":"AmrExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.flac","c":"FlacExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.flv","c":"FlvExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.ogg","c":"OggExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Extractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Extractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.extractor.wav","c":"WavExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.source","c":"MediaParserExtractorAdapter","l":"FACTORY"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BundledChunkExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaParserChunkExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.source.hls","c":"MediaParserHlsMediaChunkExtractor","l":"FACTORY"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"FACTORY"},{"p":"com.google.android.exoplayer2.upstream","c":"DummyDataSource","l":"FACTORY"},{"p":"com.google.android.exoplayer2.ext.rtmp","c":"RtmpDataSource.Factory","l":"Factory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter.Factory","l":"Factory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource.Factory","l":"Factory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.Factory","l":"Factory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource.Factory","l":"Factory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection.Factory","l":"Factory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.trackselection","c":"RandomTrackSelection.Factory","l":"Factory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource.Factory","l":"Factory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSource.Factory","l":"Factory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink.Factory","l":"Factory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"Factory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FailOnCloseDataSink.Factory","l":"Factory(Cache, AtomicBoolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,java.util.concurrent.atomic.AtomicBoolean)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource.Factory","l":"Factory(Call.Factory)","url":"%3Cinit%3E(okhttp3.Call.Factory)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.Factory","l":"Factory(ChunkExtractor.Factory, DataSource.Factory, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.chunk.ChunkExtractor.Factory,com.google.android.exoplayer2.upstream.DataSource.Factory,int)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"Factory(CronetEngine, Executor)","url":"%3Cinit%3E(org.chromium.net.CronetEngine,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"Factory(CronetEngineWrapper, Executor)","url":"%3Cinit%3E(com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"Factory(DashChunkSource.Factory, DataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.dash.DashChunkSource.Factory,com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"Factory(DataSource.Factory, ExtractorsFactory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.extractor.ExtractorsFactory)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.Factory","l":"Factory(DataSource.Factory, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory,int)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"Factory(DataSource.Factory, ProgressiveMediaExtractor.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.source.ProgressiveMediaExtractor.Factory)"},{"p":"com.google.android.exoplayer2.upstream","c":"ResolvingDataSource.Factory","l":"Factory(DataSource.Factory, ResolvingDataSource.Resolver)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.upstream.ResolvingDataSource.Resolver)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"Factory(DataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource.Factory","l":"Factory(DataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"Factory(DataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.Factory","l":"Factory(DataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"Factory(DataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource.Factory","l":"Factory(DataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"Factory(DataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource.Factory","l":"Factory(FakeAdaptiveDataSet.Factory, FakeDataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.testutil.FakeAdaptiveDataSet.Factory,com.google.android.exoplayer2.testutil.FakeDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"Factory(HlsDataSourceFactory)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.hls.HlsDataSourceFactory)"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection.Factory","l":"Factory(int, int, int, float, float, Clock)","url":"%3Cinit%3E(int,int,int,float,float,com.google.android.exoplayer2.util.Clock)"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection.Factory","l":"Factory(int, int, int, float)","url":"%3Cinit%3E(int,int,int,float)"},{"p":"com.google.android.exoplayer2.trackselection","c":"RandomTrackSelection.Factory","l":"Factory(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveDataSet.Factory","l":"Factory(long, double, Random)","url":"%3Cinit%3E(long,double,java.util.Random)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"Factory(SsChunkSource.Factory, DataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.smoothstreaming.SsChunkSource.Factory,com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.testutil","c":"FailOnCloseDataSink","l":"FailOnCloseDataSink(Cache, AtomicBoolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.cache.Cache,java.util.concurrent.atomic.AtomicBoolean)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"failOnSpuriousAudioTimestamp"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"FAILURE_REASON_NONE"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"FAILURE_REASON_UNKNOWN"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"failureReason"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"FAKE_MEDIA_ITEM"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"FAKE_MEDIA_ITEM"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"FAKE_PROVISION_REQUEST"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"FakeAdaptiveMediaPeriod(TrackGroupArray, MediaSourceEventListener.EventDispatcher, Allocator, FakeChunkSource.Factory, long, TransferListener)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher,com.google.android.exoplayer2.upstream.Allocator,com.google.android.exoplayer2.testutil.FakeChunkSource.Factory,long,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaSource","l":"FakeAdaptiveMediaSource(Timeline, TrackGroupArray, FakeChunkSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.Timeline,com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.testutil.FakeChunkSource.Factory)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAudioRenderer","l":"FakeAudioRenderer(Handler, AudioRendererEventListener)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource","l":"FakeChunkSource(ExoTrackSelection, DataSource, FakeAdaptiveDataSet)","url":"%3Cinit%3E(com.google.android.exoplayer2.trackselection.ExoTrackSelection,com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.testutil.FakeAdaptiveDataSet)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock","l":"FakeClock(boolean)","url":"%3Cinit%3E(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock","l":"FakeClock(long, boolean)","url":"%3Cinit%3E(long,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock","l":"FakeClock(long, long, boolean)","url":"%3Cinit%3E(long,long,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock","l":"FakeClock(long)","url":"%3Cinit%3E(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource.Factory","l":"fakeDataSet"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet","l":"FakeDataSet()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource","l":"FakeDataSource()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource","l":"FakeDataSource(FakeDataSet, boolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.testutil.FakeDataSet,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource","l":"FakeDataSource(FakeDataSet)","url":"%3Cinit%3E(com.google.android.exoplayer2.testutil.FakeDataSet)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"FakeExoMediaDrm()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"FakeExoMediaDrm(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorOutput","l":"FakeExtractorOutput()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorOutput","l":"FakeExtractorOutput(FakeTrackOutput.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.testutil.FakeTrackOutput.Factory)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaChunk","l":"FakeMediaChunk(Format, long, long, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format,long,long,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaChunk","l":"FakeMediaChunk(Format, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format,long,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaChunkIterator","l":"FakeMediaChunkIterator(long[], long[])","url":"%3Cinit%3E(long[],long[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaClockRenderer","l":"FakeMediaClockRenderer(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"FakeMediaPeriod(TrackGroupArray, Allocator, FakeMediaPeriod.TrackDataFactory, MediaSourceEventListener.EventDispatcher, DrmSessionManager, DrmSessionEventListener.EventDispatcher, boolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.upstream.Allocator,com.google.android.exoplayer2.testutil.FakeMediaPeriod.TrackDataFactory,com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"FakeMediaPeriod(TrackGroupArray, Allocator, long, MediaSourceEventListener.EventDispatcher, DrmSessionManager, DrmSessionEventListener.EventDispatcher, boolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.upstream.Allocator,long,com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"FakeMediaPeriod(TrackGroupArray, Allocator, long, MediaSourceEventListener.EventDispatcher)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.upstream.Allocator,long,com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"FakeMediaSource()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"FakeMediaSource(Timeline, DrmSessionManager, FakeMediaPeriod.TrackDataFactory, Format...)","url":"%3Cinit%3E(com.google.android.exoplayer2.Timeline,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.testutil.FakeMediaPeriod.TrackDataFactory,com.google.android.exoplayer2.Format...)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"FakeMediaSource(Timeline, DrmSessionManager, FakeMediaPeriod.TrackDataFactory, TrackGroupArray)","url":"%3Cinit%3E(com.google.android.exoplayer2.Timeline,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.testutil.FakeMediaPeriod.TrackDataFactory,com.google.android.exoplayer2.source.TrackGroupArray)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"FakeMediaSource(Timeline, DrmSessionManager, Format...)","url":"%3Cinit%3E(com.google.android.exoplayer2.Timeline,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.Format...)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"FakeMediaSource(Timeline, Format...)","url":"%3Cinit%3E(com.google.android.exoplayer2.Timeline,com.google.android.exoplayer2.Format...)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"FakeRenderer(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"FakeSampleStream(Allocator, MediaSourceEventListener.EventDispatcher, DrmSessionManager, DrmSessionEventListener.EventDispatcher, Format, List)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.Allocator,com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher,com.google.android.exoplayer2.Format,java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeShuffleOrder","l":"FakeShuffleOrder(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"FakeTimeline()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"FakeTimeline(FakeTimeline.TimelineWindowDefinition...)","url":"%3Cinit%3E(com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition...)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"FakeTimeline(int, Object...)","url":"%3Cinit%3E(int,java.lang.Object...)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"FakeTimeline(Object[], FakeTimeline.TimelineWindowDefinition...)","url":"%3Cinit%3E(java.lang.Object[],com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition...)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"FakeTrackOutput(boolean)","url":"%3Cinit%3E(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"FakeTrackSelection(TrackGroup)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroup)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelector","l":"FakeTrackSelector()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelector","l":"FakeTrackSelector(boolean)","url":"%3Cinit%3E(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.FakeTransferListener","l":"FakeTransferListener()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeVideoRenderer","l":"FakeVideoRenderer(Handler, VideoRendererEventListener)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy","l":"FALLBACK_TYPE_LOCATION"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy","l":"FALLBACK_TYPE_TRACK"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer.DecoderInitializationException","l":"fallbackDecoderInitializationException"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy.FallbackOptions","l":"FallbackOptions(int, int, int, int)","url":"%3Cinit%3E(int,int,int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy.FallbackSelection","l":"FallbackSelection(int, long)","url":"%3Cinit%3E(int,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"fatalErrorCount"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"fatalErrorHistory"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"fatalErrorPlaybackCount"},{"p":"com.google.android.exoplayer2.database","c":"VersionTable","l":"FEATURE_CACHE_CONTENT_METADATA"},{"p":"com.google.android.exoplayer2.database","c":"VersionTable","l":"FEATURE_CACHE_FILE_METADATA"},{"p":"com.google.android.exoplayer2.database","c":"VersionTable","l":"FEATURE_EXTERNAL"},{"p":"com.google.android.exoplayer2.database","c":"VersionTable","l":"FEATURE_OFFLINE"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegAudioRenderer","l":"FfmpegAudioRenderer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegAudioRenderer","l":"FfmpegAudioRenderer(Handler, AudioRendererEventListener, AudioProcessor...)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioProcessor...)"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegAudioRenderer","l":"FfmpegAudioRenderer(Handler, AudioRendererEventListener, AudioSink)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioSink)"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"FIELD_CUSTOM_ID_BASE"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheSpan","l":"file"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSource","l":"FileDataSource()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSource.FileDataSourceException","l":"FileDataSourceException(Exception)","url":"%3Cinit%3E(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSource.FileDataSourceException","l":"FileDataSourceException(String, IOException)","url":"%3Cinit%3E(java.lang.String,java.io.IOException)"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSource.FileDataSourceException","l":"FileDataSourceException(String, Throwable, int)","url":"%3Cinit%3E(java.lang.String,java.lang.Throwable,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSource.FileDataSourceException","l":"FileDataSourceException(Throwable, int)","url":"%3Cinit%3E(java.lang.Throwable,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSourceFactory","l":"FileDataSourceFactory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSourceFactory","l":"FileDataSourceFactory(TransferListener)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"GeobFrame","l":"filename"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"FilteringHlsPlaylistParserFactory","l":"FilteringHlsPlaylistParserFactory(HlsPlaylistParserFactory, List)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParserFactory,java.util.List)"},{"p":"com.google.android.exoplayer2.offline","c":"FilteringManifestParser","l":"FilteringManifestParser(ParsingLoadable.Parser, List)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.ParsingLoadable.Parser,java.util.List)"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"filterRequirements(int)"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil","l":"findNalUnit(byte[], int, int, boolean[])","url":"findNalUnit(byte[],int,int,boolean[])"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttParserUtil","l":"findNextCueHeader(ParsableByteArray)","url":"findNextCueHeader(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsUtil","l":"findSyncBytePosition(byte[], int, int)","url":"findSyncBytePosition(byte[],int,int)"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"findTrueHdSyncframeOffset(ByteBuffer)","url":"findTrueHdSyncframeOffset(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.analytics","c":"DefaultPlaybackSessionManager","l":"finishAllSessions(AnalyticsListener.EventTime)","url":"finishAllSessions(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackSessionManager","l":"finishAllSessions(AnalyticsListener.EventTime)","url":"finishAllSessions(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap.SeekPoints","l":"first"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"firstPeriodIndex"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"firstReportedTimeMs"},{"p":"com.google.android.exoplayer2.trackselection","c":"FixedTrackSelection","l":"FixedTrackSelection(TrackGroup, int, int, int, Object)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroup,int,int,int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.trackselection","c":"FixedTrackSelection","l":"FixedTrackSelection(TrackGroup, int, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroup,int,int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"FixedTrackSelection","l":"FixedTrackSelection(TrackGroup, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroup,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"fixSmoothStreamingIsmManifestUri(Uri)","url":"fixSmoothStreamingIsmManifestUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"FLAC"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacDecoder","l":"FlacDecoder(int, int, int, List)","url":"%3Cinit%3E(int,int,int,java.util.List)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacExtractor","l":"FlacExtractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.flac","c":"FlacExtractor","l":"FlacExtractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacExtractor","l":"FlacExtractor(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.extractor.flac","c":"FlacExtractor","l":"FlacExtractor(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacSeekTableSeekMap","l":"FlacSeekTableSeekMap(FlacStreamMetadata, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.FlacStreamMetadata,long)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacMetadataReader.FlacStreamMetadataHolder","l":"flacStreamMetadata"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"FlacStreamMetadata(byte[], int)","url":"%3Cinit%3E(byte[],int)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"FlacStreamMetadata(int, int, int, int, int, int, int, long, ArrayList, ArrayList)","url":"%3Cinit%3E(int,int,int,int,int,int,int,long,java.util.ArrayList,java.util.ArrayList)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacMetadataReader.FlacStreamMetadataHolder","l":"FlacStreamMetadataHolder(FlacStreamMetadata)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.FlacStreamMetadata)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"FLAG_ALLOW_CACHE_FRAGMENTATION"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"FLAG_ALLOW_GZIP"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DefaultTsPayloadReaderFactory","l":"FLAG_ALLOW_NON_IDR_KEYFRAMES"},{"p":"com.google.android.exoplayer2","c":"C","l":"FLAG_AUDIBILITY_ENFORCED"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"FLAG_BLOCK_ON_CACHE"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader","l":"FLAG_DATA_ALIGNMENT_INDICATOR"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DefaultTsPayloadReaderFactory","l":"FLAG_DETECT_ACCESS_UNITS"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacExtractor","l":"FLAG_DISABLE_ID3_METADATA"},{"p":"com.google.android.exoplayer2.extractor.flac","c":"FlacExtractor","l":"FLAG_DISABLE_ID3_METADATA"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"FLAG_DISABLE_ID3_METADATA"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"FLAG_DISABLE_SEEK_FOR_CUES"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"FLAG_DONT_CACHE_IF_LENGTH_UNKNOWN"},{"p":"com.google.android.exoplayer2.extractor.amr","c":"AmrExtractor","l":"FLAG_ENABLE_CONSTANT_BITRATE_SEEKING"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"FLAG_ENABLE_CONSTANT_BITRATE_SEEKING"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsExtractor","l":"FLAG_ENABLE_CONSTANT_BITRATE_SEEKING"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"FLAG_ENABLE_EMSG_TRACK"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DefaultTsPayloadReaderFactory","l":"FLAG_ENABLE_HDMV_DTS_AUDIO_STREAMS"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"FLAG_ENABLE_INDEX_SEEKING"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DefaultTsPayloadReaderFactory","l":"FLAG_IGNORE_AAC_STREAM"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"FLAG_IGNORE_CACHE_FOR_UNSET_LENGTH_REQUESTS"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"FLAG_IGNORE_CACHE_ON_ERROR"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DefaultTsPayloadReaderFactory","l":"FLAG_IGNORE_H264_STREAM"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DefaultTsPayloadReaderFactory","l":"FLAG_IGNORE_SPLICE_INFO_STREAM"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"FLAG_MIGHT_NOT_USE_FULL_NETWORK_SPEED"},{"p":"com.google.android.exoplayer2.source","c":"SampleStream","l":"FLAG_OMIT_SAMPLE_DATA"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DefaultTsPayloadReaderFactory","l":"FLAG_OVERRIDE_CAPTION_DESCRIPTORS"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader","l":"FLAG_PAYLOAD_UNIT_START_INDICATOR"},{"p":"com.google.android.exoplayer2.source","c":"SampleStream","l":"FLAG_PEEK"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader","l":"FLAG_RANDOM_ACCESS_INDICATOR"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"FLAG_READ_MOTION_PHOTO_METADATA"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"FLAG_READ_SEF_DATA"},{"p":"com.google.android.exoplayer2.source","c":"SampleStream","l":"FLAG_REQUIRE_FORMAT"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"FLAG_WORKAROUND_IGNORE_EDIT_LISTS"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"FLAG_WORKAROUND_IGNORE_EDIT_LISTS"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"FLAG_WORKAROUND_IGNORE_TFDT_BOX"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes","l":"flags"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter.Configuration","l":"flags"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"flags"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"flip()"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"floatElement(int, double)","url":"floatElement(int,double)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"floatElement(int, double)","url":"floatElement(int,double)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor","l":"flush()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"flush()"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"flush()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"flush()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"flush()"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"flush()"},{"p":"com.google.android.exoplayer2.decoder","c":"Decoder","l":"flush()"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleDecoder","l":"flush()"},{"p":"com.google.android.exoplayer2.ext.gvr","c":"GvrAudioProcessor","l":"flush()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"flush()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"flush()"},{"p":"com.google.android.exoplayer2.testutil","c":"CapturingAudioSink","l":"flush()"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea608Decoder","l":"flush()"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea708Decoder","l":"flush()"},{"p":"com.google.android.exoplayer2.audio","c":"TeeAudioProcessor.AudioBufferSink","l":"flush(int, int, int)","url":"flush(int,int,int)"},{"p":"com.google.android.exoplayer2.audio","c":"TeeAudioProcessor.WavFileAudioBufferSink","l":"flush(int, int, int)","url":"flush(int,int,int)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"flushDecoder()"},{"p":"com.google.android.exoplayer2.util","c":"ListenerSet","l":"flushEvents()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"flushOrReinitializeCodec()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"flushOrReleaseCodec()"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"FLV"},{"p":"com.google.android.exoplayer2.extractor.flv","c":"FlvExtractor","l":"FlvExtractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.audio","c":"WavUtil","l":"FMT_FOURCC"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPayloadFormat","l":"fmtpParameters"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"focusSkipButton()"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"FOLDER_TYPE_ALBUMS"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"FOLDER_TYPE_ARTISTS"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"FOLDER_TYPE_GENRES"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"FOLDER_TYPE_MIXED"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"FOLDER_TYPE_NONE"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"FOLDER_TYPE_PLAYLISTS"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"FOLDER_TYPE_TITLES"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"FOLDER_TYPE_YEARS"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"folderType"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"FONT_SIZE_UNIT_EM"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"FONT_SIZE_UNIT_PERCENT"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"FONT_SIZE_UNIT_PIXEL"},{"p":"com.google.android.exoplayer2.robolectric","c":"ShadowMediaCodecConfig","l":"forAllSupportedMimeTypes()"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaCrypto","l":"forceAllowInsecureDecoderComponents"},{"p":"com.google.android.exoplayer2","c":"MediaItem.DrmConfiguration","l":"forceDefaultLicenseUri"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"forceHighestSupportedBitrate"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"forceLowestBitrate"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"forceStop()"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity.HostedTest","l":"forceStop()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forDash(Context, Uri, DataSource.Factory, RenderersFactory)","url":"forDash(android.content.Context,android.net.Uri,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.RenderersFactory)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forDash(Uri, DataSource.Factory, RenderersFactory, DrmSessionManager, DefaultTrackSelector.Parameters)","url":"forDash(android.net.Uri,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.RenderersFactory,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"FOREGROUND_NOTIFICATION_ID_NONE"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"foregroundColor"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"foregroundPlaybackCount"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forHls(Context, Uri, DataSource.Factory, RenderersFactory)","url":"forHls(android.content.Context,android.net.Uri,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.RenderersFactory)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forHls(Uri, DataSource.Factory, RenderersFactory, DrmSessionManager, DefaultTrackSelector.Parameters)","url":"forHls(android.net.Uri,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.RenderersFactory,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters)"},{"p":"com.google.android.exoplayer2","c":"FormatHolder","l":"format"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndFormat","l":"format"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.ConfigurationException","l":"format"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.InitializationException","l":"format"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.WriteException","l":"format"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"format"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter.Configuration","l":"format"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser.RepresentationInfo","l":"format"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"format"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Rendition","l":"format"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Variant","l":"format"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPayloadFormat","l":"format"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderInputBuffer","l":"format"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"format"},{"p":"com.google.android.exoplayer2","c":"C","l":"FORMAT_EXCEEDS_CAPABILITIES"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"FORMAT_EXCEEDS_CAPABILITIES"},{"p":"com.google.android.exoplayer2","c":"C","l":"FORMAT_HANDLED"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"FORMAT_HANDLED"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"FORMAT_SUPPORT_MASK"},{"p":"com.google.android.exoplayer2","c":"C","l":"FORMAT_UNSUPPORTED_DRM"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"FORMAT_UNSUPPORTED_DRM"},{"p":"com.google.android.exoplayer2","c":"C","l":"FORMAT_UNSUPPORTED_SUBTYPE"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"FORMAT_UNSUPPORTED_SUBTYPE"},{"p":"com.google.android.exoplayer2","c":"C","l":"FORMAT_UNSUPPORTED_TYPE"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"FORMAT_UNSUPPORTED_TYPE"},{"p":"com.google.android.exoplayer2.extractor","c":"DummyTrackOutput","l":"format(Format)","url":"format(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput","l":"format(Format)","url":"format(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"format(Format)","url":"format(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler.PlayerTrackEmsgHandler","l":"format(Format)","url":"format(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream.FakeSampleStreamItem","l":"format(Format)","url":"format(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"format(Format)","url":"format(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2","c":"FormatHolder","l":"FormatHolder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"formatInvariant(String, Object...)","url":"formatInvariant(java.lang.String,java.lang.Object...)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"formats"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forMediaItem(Context, MediaItem, RenderersFactory, DataSource.Factory)","url":"forMediaItem(android.content.Context,com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.RenderersFactory,com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forMediaItem(Context, MediaItem)","url":"forMediaItem(android.content.Context,com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forMediaItem(MediaItem, DefaultTrackSelector.Parameters, RenderersFactory, DataSource.Factory, DrmSessionManager)","url":"forMediaItem(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters,com.google.android.exoplayer2.RenderersFactory,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.drm.DrmSessionManager)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forMediaItem(MediaItem, DefaultTrackSelector.Parameters, RenderersFactory, DataSource.Factory)","url":"forMediaItem(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters,com.google.android.exoplayer2.RenderersFactory,com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forProgressive(Context, Uri, String)","url":"forProgressive(android.content.Context,android.net.Uri,java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forProgressive(Context, Uri)","url":"forProgressive(android.content.Context,android.net.Uri)"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher","l":"forResources(Iterable)","url":"forResources(java.lang.Iterable)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forSmoothStreaming(Context, Uri, DataSource.Factory, RenderersFactory)","url":"forSmoothStreaming(android.content.Context,android.net.Uri,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.RenderersFactory)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forSmoothStreaming(Uri, DataSource.Factory, RenderersFactory, DrmSessionManager, DefaultTrackSelector.Parameters)","url":"forSmoothStreaming(android.net.Uri,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.RenderersFactory,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"forSmoothStreaming(Uri, DataSource.Factory, RenderersFactory)","url":"forSmoothStreaming(android.net.Uri,com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.RenderersFactory)"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"ForwardingAudioSink(AudioSink)","url":"%3Cinit%3E(com.google.android.exoplayer2.audio.AudioSink)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"ForwardingExtractorInput(ExtractorInput)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"ForwardingPlayer(Player)","url":"%3Cinit%3E(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.source","c":"ForwardingTimeline","l":"ForwardingTimeline(Timeline)","url":"%3Cinit%3E(com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"FragmentedMp4Extractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"FragmentedMp4Extractor(int, TimestampAdjuster, Track, List, TrackOutput)","url":"%3Cinit%3E(int,com.google.android.exoplayer2.util.TimestampAdjuster,com.google.android.exoplayer2.extractor.mp4.Track,java.util.List,com.google.android.exoplayer2.extractor.TrackOutput)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"FragmentedMp4Extractor(int, TimestampAdjuster, Track, List)","url":"%3Cinit%3E(int,com.google.android.exoplayer2.util.TimestampAdjuster,com.google.android.exoplayer2.extractor.mp4.Track,java.util.List)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"FragmentedMp4Extractor(int, TimestampAdjuster, Track)","url":"%3Cinit%3E(int,com.google.android.exoplayer2.util.TimestampAdjuster,com.google.android.exoplayer2.extractor.mp4.Track)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"FragmentedMp4Extractor(int, TimestampAdjuster)","url":"%3Cinit%3E(int,com.google.android.exoplayer2.util.TimestampAdjuster)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"FragmentedMp4Extractor(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"frameMbsOnlyFlag"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"frameNumLength"},{"p":"com.google.android.exoplayer2","c":"Format","l":"frameRate"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util.SyncFrameInfo","l":"frameSize"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util.SyncFrameInfo","l":"frameSize"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil.Header","l":"frameSize"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaCrypto","l":"FrameworkMediaCrypto(UUID, byte[], boolean)","url":"%3Cinit%3E(java.util.UUID,byte[],boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.VorbisIdHeader","l":"framingFlag"},{"p":"com.google.android.exoplayer2","c":"Bundleable.Creator","l":"fromBundle(Bundle)","url":"fromBundle(android.os.Bundle)"},{"p":"com.google.android.exoplayer2.util","c":"BundleableUtils","l":"fromBundleList(Bundleable.Creator, List)","url":"fromBundleList(com.google.android.exoplayer2.Bundleable.Creator,java.util.List)"},{"p":"com.google.android.exoplayer2.util","c":"BundleableUtils","l":"fromNullableBundle(Bundleable.Creator, Bundle, T)","url":"fromNullableBundle(com.google.android.exoplayer2.Bundleable.Creator,android.os.Bundle,T)"},{"p":"com.google.android.exoplayer2.util","c":"BundleableUtils","l":"fromNullableBundle(Bundleable.Creator, Bundle)","url":"fromNullableBundle(com.google.android.exoplayer2.Bundleable.Creator,android.os.Bundle)"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"fromUri(String)","url":"fromUri(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"fromUri(Uri)","url":"fromUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"fromUtf8Bytes(byte[], int, int)","url":"fromUtf8Bytes(byte[],int,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"fromUtf8Bytes(byte[])"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.SegmentBase","l":"fullSegmentEncryptionKeyUri"},{"p":"com.google.android.exoplayer2.extractor","c":"GaplessInfoHolder","l":"GaplessInfoHolder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Gav1Decoder","l":"Gav1Decoder(int, int, int, int)","url":"%3Cinit%3E(int,int,int,int)"},{"p":"com.google.android.exoplayer2","c":"C","l":"generateAudioSessionIdV21(Context)","url":"generateAudioSessionIdV21(android.content.Context)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"generateCurrentPlayerMediaPeriodEventTime()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"generateEventTime(Timeline, int, MediaSource.MediaPeriodId)","url":"generateEventTime(com.google.android.exoplayer2.Timeline,int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.TrackIdGenerator","l":"generateNewId()"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"genre"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"genre"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"GeobFrame","l":"GeobFrame(String, String, String, byte[])","url":"%3Cinit%3E(java.lang.String,java.lang.String,java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.util","c":"RunnableFutureTask","l":"get()"},{"p":"com.google.android.exoplayer2","c":"Player.Commands","l":"get(int)"},{"p":"com.google.android.exoplayer2","c":"Player.Events","l":"get(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.Events","l":"get(int)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"get(int)"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata","l":"get(int)"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroupArray","l":"get(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionArray","l":"get(int)"},{"p":"com.google.android.exoplayer2.util","c":"FlagSet","l":"get(int)"},{"p":"com.google.android.exoplayer2.util","c":"LongArray","l":"get(int)"},{"p":"com.google.android.exoplayer2.util","c":"RunnableFutureTask","l":"get(long, TimeUnit)","url":"get(long,java.util.concurrent.TimeUnit)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManagerProvider","l":"get(MediaItem)","url":"get(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionManagerProvider","l":"get(MediaItem)","url":"get(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadata","l":"get(String, byte[])","url":"get(java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"DefaultContentMetadata","l":"get(String, byte[])","url":"get(java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadata","l":"get(String, long)","url":"get(java.lang.String,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"DefaultContentMetadata","l":"get(String, long)","url":"get(java.lang.String,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadata","l":"get(String, String)","url":"get(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"DefaultContentMetadata","l":"get(String, String)","url":"get(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getAbandonedBeforeReadyRatio()"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util","l":"getAc4SampleHeader(int, ParsableByteArray)","url":"getAc4SampleHeader(int,com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"getActionIndicesForCompactView(List, Player)","url":"getActionIndicesForCompactView(java.util.List,com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"getActions(Player)","url":"getActions(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.QueueNavigator","l":"getActiveQueueItemId(Player)","url":"getActiveQueueItemId(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueNavigator","l":"getActiveQueueItemId(Player)","url":"getActiveQueueItemId(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.analytics","c":"DefaultPlaybackSessionManager","l":"getActiveSessionId()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackSessionManager","l":"getActiveSessionId()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Period","l":"getAdaptationSetIndex(int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getAdaptiveMimeTypeForContentType(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"getAdaptiveSupport(int, int, boolean)","url":"getAdaptiveSupport(int,int,boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"getAdaptiveSupport(int, int, int[])","url":"getAdaptiveSupport(int,int,int[])"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"getAdaptiveSupport(int)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getAdCountInAdGroup(int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsUtil","l":"getAdCountInGroup(AdPlaybackState, int)","url":"getAdCountInGroup(com.google.android.exoplayer2.source.ads.AdPlaybackState,int)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"getAdDisplayContainer()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"DefaultCastOptionsProvider","l":"getAdditionalSessionProviders(Context)","url":"getAdditionalSessionProviders(android.content.Context)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getAdDurationUs(int, int)","url":"getAdDurationUs(int,int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"getAdGroup(int)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getAdGroupCount()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"getAdGroupIndexAfterPositionUs(long, long)","url":"getAdGroupIndexAfterPositionUs(long,long)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getAdGroupIndexAfterPositionUs(long)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"getAdGroupIndexForPositionUs(long, long)","url":"getAdGroupIndexForPositionUs(long,long)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getAdGroupIndexForPositionUs(long)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getAdGroupTimeUs(int)"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl","l":"getAdjustedPlaybackSpeed(long, long)","url":"getAdjustedPlaybackSpeed(long,long)"},{"p":"com.google.android.exoplayer2","c":"LivePlaybackSpeedControl","l":"getAdjustedPlaybackSpeed(long, long)","url":"getAdjustedPlaybackSpeed(long,long)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"getAdjustedSeekPositionUs(long, SeekParameters)","url":"getAdjustedSeekPositionUs(long,com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"getAdjustedSeekPositionUs(long, SeekParameters)","url":"getAdjustedSeekPositionUs(long,com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"getAdjustedSeekPositionUs(long, SeekParameters)","url":"getAdjustedSeekPositionUs(long,com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"getAdjustedSeekPositionUs(long, SeekParameters)","url":"getAdjustedSeekPositionUs(long,com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSource","l":"getAdjustedSeekPositionUs(long, SeekParameters)","url":"getAdjustedSeekPositionUs(long,com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"getAdjustedSeekPositionUs(long, SeekParameters)","url":"getAdjustedSeekPositionUs(long,com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"getAdjustedSeekPositionUs(long, SeekParameters)","url":"getAdjustedSeekPositionUs(long,com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource","l":"getAdjustedSeekPositionUs(long, SeekParameters)","url":"getAdjustedSeekPositionUs(long,com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"getAdjustedSeekPositionUs(long, SeekParameters)","url":"getAdjustedSeekPositionUs(long,com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource","l":"getAdjustedSeekPositionUs(long, SeekParameters)","url":"getAdjustedSeekPositionUs(long,com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"getAdjustedSeekPositionUs(long, SeekParameters)","url":"getAdjustedSeekPositionUs(long,com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"getAdjustedUpstreamFormat(Format)","url":"getAdjustedUpstreamFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.source.hls","c":"TimestampAdjusterProvider","l":"getAdjuster(int)"},{"p":"com.google.android.exoplayer2.ui","c":"AdViewProvider","l":"getAdOverlayInfos()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getAdOverlayInfos()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getAdOverlayInfos()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getAdResumePositionUs()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getAdsId()"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"getAdsLoader()"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory.AdsLoaderProvider","l":"getAdsLoader(MediaItem.AdsConfiguration)","url":"getAdsLoader(com.google.android.exoplayer2.MediaItem.AdsConfiguration)"},{"p":"com.google.android.exoplayer2.ui","c":"AdViewProvider","l":"getAdViewGroup()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getAdViewGroup()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getAdViewGroup()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionArray","l":"getAll()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet","l":"getAllData()"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"getAllocator()"},{"p":"com.google.android.exoplayer2","c":"LoadControl","l":"getAllocator()"},{"p":"com.google.android.exoplayer2.robolectric","c":"RandomizedMp3Decoder","l":"getAllOutputBytes()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.AllowedCommandProvider","l":"getAllowedCommands(MediaSession, MediaSession.ControllerInfo, SessionCommandGroup)","url":"getAllowedCommands(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo,androidx.media2.session.SessionCommandGroup)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.DefaultAllowedCommandProvider","l":"getAllowedCommands(MediaSession, MediaSession.ControllerInfo, SessionCommandGroup)","url":"getAllowedCommands(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo,androidx.media2.session.SessionCommandGroup)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelector","l":"getAllTrackSelections()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getAnalyticsCollector()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource","l":"getAndClearOpenedDataSpecs()"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"InputReaderAdapterV30","l":"getAndResetSeekPosition()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getApplicationLooper()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getApplicationLooper()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getApplicationLooper()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getApplicationLooper()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"getApplicationLooper()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getApplicationLooper()"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer","l":"getApplicationLooper()"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"getApproxBytesPerFrame()"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil","l":"getAttributes(int)"},{"p":"com.google.android.exoplayer2.util","c":"XmlPullParserUtil","l":"getAttributeValue(XmlPullParser, String)","url":"getAttributeValue(org.xmlpull.v1.XmlPullParser,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"XmlPullParserUtil","l":"getAttributeValueIgnorePrefix(XmlPullParser, String)","url":"getAttributeValueIgnorePrefix(org.xmlpull.v1.XmlPullParser,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioComponent","l":"getAudioAttributes()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getAudioAttributes()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getAudioAttributes()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getAudioAttributes()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getAudioAttributes()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getAudioAttributes()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getAudioAttributes()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes","l":"getAudioAttributesV21()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getAudioComponent()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getAudioComponent()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getAudioComponent()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getAudioContentTypeForStreamType(int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getAudioDecoderCounters()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getAudioFormat()"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"getAudioMediaMimeType(String)","url":"getAudioMediaMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink.AudioProcessorChain","l":"getAudioProcessors()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink.DefaultAudioProcessorChain","l":"getAudioProcessors()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioComponent","l":"getAudioSessionId()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getAudioSessionId()"},{"p":"com.google.android.exoplayer2.util","c":"DebugTextViewHelper","l":"getAudioString()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getAudioTrackChannelConfig(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getAudioUnderrunRate()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getAudioUsageForStreamType(int)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getAvailableCommands()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getAvailableCommands()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getAvailableCommands()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getAvailableCommands()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getAvailableCommands()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"getAvailableCommands(Player.Commands)","url":"getAvailableCommands(com.google.android.exoplayer2.Player.Commands)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashSegmentIndex","l":"getAvailableSegmentCount(long, long)","url":"getAvailableSegmentCount(long,long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashWrappingSegmentIndex","l":"getAvailableSegmentCount(long, long)","url":"getAvailableSegmentCount(long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"getAvailableSegmentCount(long, long)","url":"getAvailableSegmentCount(long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.MultiSegmentBase","l":"getAvailableSegmentCount(long, long)","url":"getAvailableSegmentCount(long,long)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"getBackBufferDurationUs()"},{"p":"com.google.android.exoplayer2","c":"LoadControl","l":"getBackBufferDurationUs()"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"getBackgroundColor()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"getBandwidthMeter()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelector","l":"getBandwidthMeter()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getBigEndianInt(ByteBuffer, int)","url":"getBigEndianInt(java.nio.ByteBuffer,int)"},{"p":"com.google.android.exoplayer2.util","c":"BundleUtil","l":"getBinder(Bundle, String)","url":"getBinder(android.os.Bundle,java.lang.String)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getBitmap()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"getBitmap(Context, String)","url":"getBitmap(android.content.Context,java.lang.String)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getBitmapHeight()"},{"p":"com.google.android.exoplayer2.upstream","c":"BandwidthMeter","l":"getBitrateEstimate()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"getBitrateEstimate()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"getBufferedPercentage()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getBufferedPercentage()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getBufferedPercentage()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getBufferedPosition()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getBufferedPosition()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getBufferedPosition()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getBufferedPosition()"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"getBufferedPosition()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getBufferedPosition()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getBufferedPosition()"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"getBufferedPositionUs()"},{"p":"com.google.android.exoplayer2.source","c":"CompositeSequenceableLoader","l":"getBufferedPositionUs()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"getBufferedPositionUs()"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"getBufferedPositionUs()"},{"p":"com.google.android.exoplayer2.source","c":"SequenceableLoader","l":"getBufferedPositionUs()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"getBufferedPositionUs()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"getBufferedPositionUs()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"getBufferedPositionUs()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"getBufferedPositionUs()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getBufferingState()"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxLibrary","l":"getBuildConfig()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"getByteArray(Context, String)","url":"getByteArray(android.content.Context,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"getBytePosition()"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"getBytesDownloaded()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getBytesFromHexString(String)","url":"getBytesFromHexString(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"StatsDataSource","l":"getBytesRead()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"getCache()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"getCache()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"getCachedBytes(String, long, long)","url":"getCachedBytes(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"getCachedBytes(String, long, long)","url":"getCachedBytes(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"getCachedLength(String, long, long)","url":"getCachedLength(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"getCachedLength(String, long, long)","url":"getCachedLength(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"getCachedSpans(String)","url":"getCachedSpans(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"getCachedSpans(String)","url":"getCachedSpans(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"getCacheKey()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"getCacheKey()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.SingleSegmentRepresentation","l":"getCacheKey()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"getCacheKeyFactory()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"getCacheKeyFactory()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"getCacheSpace()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"getCacheSpace()"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView","l":"getCameraMotionListener()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"getCapabilities()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"getCapabilities()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"getCapabilities()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioCapabilities","l":"getCapabilities(Context)","url":"getCapabilities(android.content.Context)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"DefaultCastOptionsProvider","l":"getCastOptions(Context)","url":"getCastOptions(android.content.Context)"},{"p":"com.google.android.exoplayer2.audio","c":"OpusUtil","l":"getChannelCount(byte[])"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getChildIndexByChildUid(Object)","url":"getChildIndexByChildUid(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getChildIndexByPeriodIndex(int)"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getChildIndexByWindowIndex(int)"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getChildPeriodUidFromConcatenatedUid(Object)","url":"getChildPeriodUidFromConcatenatedUid(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getChildTimelineUidFromConcatenatedUid(Object)","url":"getChildTimelineUidFromConcatenatedUid(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getChildUidByChildIndex(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveDataSet","l":"getChunkCount()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveDataSet","l":"getChunkDuration(int)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"getChunkDurationUs(int)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaChunkIterator","l":"getChunkEndTimeUs()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationSegmentIterator","l":"getChunkEndTimeUs()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveDataSet.Iterator","l":"getChunkEndTimeUs()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaChunkIterator","l":"getChunkEndTimeUs()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BundledChunkExtractor","l":"getChunkIndex()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkExtractor","l":"getChunkIndex()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaParserChunkExtractor","l":"getChunkIndex()"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"getChunkIndex()"},{"p":"com.google.android.exoplayer2.extractor","c":"ChunkIndex","l":"getChunkIndex(long)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"getChunkIndex(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveDataSet","l":"getChunkIndexByPosition(long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"getChunkSource()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaChunkIterator","l":"getChunkStartTimeUs()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationSegmentIterator","l":"getChunkStartTimeUs()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveDataSet.Iterator","l":"getChunkStartTimeUs()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaChunkIterator","l":"getChunkStartTimeUs()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getClock()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getClock()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getClock()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"getClock()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"getCodec()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getCodecCountOfType(String, int)","url":"getCodecCountOfType(java.lang.String,int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"getCodecInfo()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"getCodecMaxInputSize(MediaCodecInfo, Format, Format[])","url":"getCodecMaxInputSize(com.google.android.exoplayer2.mediacodec.MediaCodecInfo,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format[])"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"getCodecMaxValues(MediaCodecInfo, Format, Format[])","url":"getCodecMaxValues(com.google.android.exoplayer2.mediacodec.MediaCodecInfo,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format[])"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"getCodecNeedsEosPropagation()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"getCodecNeedsEosPropagation()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"getCodecOperatingRate()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"getCodecOperatingRateV23(float, Format, Format[])","url":"getCodecOperatingRateV23(float,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format[])"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"getCodecOperatingRateV23(float, Format, Format[])","url":"getCodecOperatingRateV23(float,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format[])"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"getCodecOperatingRateV23(float, Format, Format[])","url":"getCodecOperatingRateV23(float,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format[])"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"getCodecOutputMediaFormat()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecUtil","l":"getCodecProfileAndLevel(Format)","url":"getCodecProfileAndLevel(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"getCodecsCorrespondingToMimeType(String, String)","url":"getCodecsCorrespondingToMimeType(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getCodecsOfType(String, int)","url":"getCodecsOfType(java.lang.String,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"getCombinedPlaybackStats()"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"getCombineUpright()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getCommaDelimitedSimpleClassNames(Object[])","url":"getCommaDelimitedSimpleClassNames(java.lang.Object[])"},{"p":"com.google.android.exoplayer2.offline","c":"SegmentDownloader","l":"getCompressibleDataSpec(Uri)","url":"getCompressibleDataSpec(android.net.Uri)"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getConcatenatedUid(Object, Object)","url":"getConcatenatedUid(java.lang.Object,java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"getConfiguration()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"getConfiguration()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getContentBufferedPosition()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getContentBufferedPosition()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getContentBufferedPosition()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getContentBufferedPosition()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getContentBufferedPosition()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"getContentDuration()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getContentDuration()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getContentDuration()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadata","l":"getContentLength(ContentMetadata)","url":"getContentLength(com.google.android.exoplayer2.upstream.cache.ContentMetadata)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpUtil","l":"getContentLength(String, String)","url":"getContentLength(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"getContentMetadata(String)","url":"getContentMetadata(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"getContentMetadata(String)","url":"getContentMetadata(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getContentPosition()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getContentPosition()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getContentPosition()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getContentPosition()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getContentPosition()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getContentResumeOffsetUs(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getControllerAutoShow()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getControllerAutoShow()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getControllerHideOnTouch()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getControllerHideOnTouch()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getControllerShowTimeoutMs()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getControllerShowTimeoutMs()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"getCount()"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts.RequestSet","l":"getCount()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getCountryCode(Context)","url":"getCountryCode(android.content.Context)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"getCreatedMediaPeriods()"},{"p":"com.google.android.exoplayer2.text","c":"Subtitle","l":"getCues(long)"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleOutputBuffer","l":"getCues(long)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getCurrentAdGroupIndex()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentAdGroupIndex()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getCurrentAdGroupIndex()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getCurrentAdGroupIndex()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getCurrentAdGroupIndex()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getCurrentAdIndexInAdGroup()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentAdIndexInAdGroup()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getCurrentAdIndexInAdGroup()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getCurrentAdIndexInAdGroup()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getCurrentAdIndexInAdGroup()"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultMediaDescriptionAdapter","l":"getCurrentContentText(Player)","url":"getCurrentContentText(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.MediaDescriptionAdapter","l":"getCurrentContentText(Player)","url":"getCurrentContentText(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultMediaDescriptionAdapter","l":"getCurrentContentTitle(Player)","url":"getCurrentContentTitle(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.MediaDescriptionAdapter","l":"getCurrentContentTitle(Player)","url":"getCurrentContentTitle(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.TextComponent","l":"getCurrentCues()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getCurrentCues()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentCues()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getCurrentCues()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getCurrentCues()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getCurrentCues()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getCurrentDisplayModeSize(Context, Display)","url":"getCurrentDisplayModeSize(android.content.Context,android.view.Display)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getCurrentDisplayModeSize(Context)","url":"getCurrentDisplayModeSize(android.content.Context)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"getCurrentDownloads()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunkIterator","l":"getCurrentIndex()"},{"p":"com.google.android.exoplayer2.source","c":"BundledExtractorsAdapter","l":"getCurrentInputPosition()"},{"p":"com.google.android.exoplayer2.source","c":"MediaParserExtractorAdapter","l":"getCurrentInputPosition()"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaExtractor","l":"getCurrentInputPosition()"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultMediaDescriptionAdapter","l":"getCurrentLargeIcon(Player, PlayerNotificationManager.BitmapCallback)","url":"getCurrentLargeIcon(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ui.PlayerNotificationManager.BitmapCallback)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.MediaDescriptionAdapter","l":"getCurrentLargeIcon(Player, PlayerNotificationManager.BitmapCallback)","url":"getCurrentLargeIcon(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ui.PlayerNotificationManager.BitmapCallback)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"getCurrentLiveOffset()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getCurrentLiveOffset()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentLiveOffset()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"getCurrentManifest()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getCurrentManifest()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentManifest()"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector","l":"getCurrentMappedTrackInfo()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"getCurrentMediaItem()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getCurrentMediaItem()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentMediaItem()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getCurrentMediaItem()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getCurrentMediaItemIndex()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getCurrentOrMainLooper()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getCurrentPeriodIndex()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentPeriodIndex()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getCurrentPeriodIndex()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getCurrentPeriodIndex()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getCurrentPeriodIndex()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getCurrentPosition()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentPosition()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getCurrentPosition()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getCurrentPosition()"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"getCurrentPosition()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getCurrentPosition()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getCurrentPosition()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"getCurrentPositionUs(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"getCurrentPositionUs(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"getCurrentPositionUs(boolean)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getCurrentStaticMetadata()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentStaticMetadata()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getCurrentStaticMetadata()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getCurrentStaticMetadata()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getCurrentStaticMetadata()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.MediaDescriptionAdapter","l":"getCurrentSubText(Player)","url":"getCurrentSubText(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getCurrentTimeline()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentTimeline()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getCurrentTimeline()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getCurrentTimeline()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getCurrentTimeline()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getCurrentTrackGroups()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentTrackGroups()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getCurrentTrackGroups()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getCurrentTrackGroups()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getCurrentTrackGroups()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getCurrentTrackSelections()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentTrackSelections()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getCurrentTrackSelections()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getCurrentTrackSelections()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getCurrentTrackSelections()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"getCurrentUnixTimeMs()"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"getCurrentUrlRequest()"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"getCurrentUrlResponseInfo()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getCurrentWindowIndex()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getCurrentWindowIndex()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getCurrentWindowIndex()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getCurrentWindowIndex()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getCurrentWindowIndex()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.CustomActionProvider","l":"getCustomAction(Player)","url":"getCustomAction(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"RepeatModeActionProvider","l":"getCustomAction(Player)","url":"getCustomAction(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.CustomActionReceiver","l":"getCustomActions(Player)","url":"getCustomActions(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.CustomCommandProvider","l":"getCustomCommands(MediaSession, MediaSession.ControllerInfo)","url":"getCustomCommands(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyRequest","l":"getData()"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.ProvisionRequest","l":"getData()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData","l":"getData()"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource","l":"getData()"},{"p":"com.google.android.exoplayer2.upstream","c":"ByteArrayDataSink","l":"getData()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"getData()"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts.RequestSet","l":"getData(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet","l":"getData(String)","url":"getData(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet","l":"getData(Uri)","url":"getData(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"DataChunk","l":"getDataHolder()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource","l":"getDataSet()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaChunkIterator","l":"getDataSpec()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationSegmentIterator","l":"getDataSpec()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveDataSet.Iterator","l":"getDataSpec()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaChunkIterator","l":"getDataSpec()"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts.RequestSet","l":"getDataSpec(int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getDataUriForString(String, String)","url":"getDataUriForString(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"DebugTextViewHelper","l":"getDebugString()"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"getDecodedBitrate()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecUtil","l":"getDecoderInfo(String, boolean, boolean)","url":"getDecoderInfo(java.lang.String,boolean,boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"getDecoderInfos(MediaCodecSelector, Format, boolean)","url":"getDecoderInfos(com.google.android.exoplayer2.mediacodec.MediaCodecSelector,com.google.android.exoplayer2.Format,boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"getDecoderInfos(MediaCodecSelector, Format, boolean)","url":"getDecoderInfos(com.google.android.exoplayer2.mediacodec.MediaCodecSelector,com.google.android.exoplayer2.Format,boolean)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"getDecoderInfos(MediaCodecSelector, Format, boolean)","url":"getDecoderInfos(com.google.android.exoplayer2.mediacodec.MediaCodecSelector,com.google.android.exoplayer2.Format,boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecSelector","l":"getDecoderInfos(String, boolean, boolean)","url":"getDecoderInfos(java.lang.String,boolean,boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecUtil","l":"getDecoderInfos(String, boolean, boolean)","url":"getDecoderInfos(java.lang.String,boolean,boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecUtil","l":"getDecoderInfosSortedByFormatSupport(List, Format)","url":"getDecoderInfosSortedByFormatSupport(java.util.List,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecUtil","l":"getDecryptOnlyDecoderInfo()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getDefaultArtwork()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getDefaultArtwork()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"getDefaultPositionMs()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"getDefaultPositionUs()"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"getDefaultRequestProperties()"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource.Factory","l":"getDefaultRequestProperties()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource.Factory","l":"getDefaultRequestProperties()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.BaseFactory","l":"getDefaultRequestProperties()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.Factory","l":"getDefaultRequestProperties()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"getDefaults(Context)","url":"getDefaults(android.content.Context)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"getDefaults(Context)","url":"getDefaults(android.content.Context)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"getDefaultTrackSelectorParameters(Context)","url":"getDefaultTrackSelectorParameters(android.content.Context)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.ProvisionRequest","l":"getDefaultUrl()"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"getDeleteAfterDelivery()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getDeviceComponent()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getDeviceComponent()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getDeviceComponent()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.DeviceComponent","l":"getDeviceInfo()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getDeviceInfo()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getDeviceInfo()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getDeviceInfo()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getDeviceInfo()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getDeviceInfo()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.DeviceComponent","l":"getDeviceVolume()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getDeviceVolume()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getDeviceVolume()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getDeviceVolume()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getDeviceVolume()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getDeviceVolume()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpUtil","l":"getDocumentSize(String)","url":"getDocumentSize(java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"getDownload()"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloadIndex","l":"getDownload(String)","url":"getDownload(java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadIndex","l":"getDownload(String)","url":"getDownload(java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"getDownloadIndex()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"getDownloadManager()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"getDownloadRequest(byte[])"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"getDownloadRequest(String, byte[])","url":"getDownloadRequest(java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloadIndex","l":"getDownloads(int...)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadIndex","l":"getDownloads(int...)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"getDownloadsPaused()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getDrmUuid(String)","url":"getDrmUuid(java.lang.String)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getDroppedFramesRate()"},{"p":"com.google.android.exoplayer2.audio","c":"DtsUtil","l":"getDtsFrameSize(byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionManager","l":"getDummyDrmSessionManager()"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"getDummySeekMap()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getDuration()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getDuration()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getDuration()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getDuration()"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"getDuration()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getDuration()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getDuration()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getDurationMs()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"getDurationMs()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getDurationUs()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"getDurationUs()"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.BinarySearchSeekMap","l":"getDurationUs()"},{"p":"com.google.android.exoplayer2.extractor","c":"ChunkIndex","l":"getDurationUs()"},{"p":"com.google.android.exoplayer2.extractor","c":"ConstantBitrateSeekMap","l":"getDurationUs()"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacSeekTableSeekMap","l":"getDurationUs()"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"getDurationUs()"},{"p":"com.google.android.exoplayer2.extractor","c":"IndexSeekMap","l":"getDurationUs()"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap","l":"getDurationUs()"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap.Unseekable","l":"getDurationUs()"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"getDurationUs()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"getDurationUs()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashSegmentIndex","l":"getDurationUs(long, long)","url":"getDurationUs(long,long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashWrappingSegmentIndex","l":"getDurationUs(long, long)","url":"getDurationUs(long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"getDurationUs(long, long)","url":"getDurationUs(long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadataMutations","l":"getEditedValues()"},{"p":"com.google.android.exoplayer2.util","c":"SntpClient","l":"getElapsedRealtimeOffsetMs()"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"getElementType(int)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"getElementType(int)"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"getEncoding(String, String)","url":"getEncoding(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"getEncodingForAudioObjectType(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getEndedRatio()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"getEndTimeUs()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"getError()"},{"p":"com.google.android.exoplayer2.drm","c":"ErrorStateDrmSession","l":"getError()"},{"p":"com.google.android.exoplayer2","c":"C","l":"getErrorCodeForMediaDrmErrorCode(int)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmUtil","l":"getErrorCodeForMediaDrmException(Exception, int)","url":"getErrorCodeForMediaDrmException(java.lang.Exception,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getErrorCodeFromPlatformDiagnosticsInfo(String)","url":"getErrorCodeFromPlatformDiagnosticsInfo(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"getErrorCodeName()"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"getErrorCodeName(int)"},{"p":"com.google.android.exoplayer2.util","c":"ErrorMessageProvider","l":"getErrorMessage(T)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.Events","l":"getEventTime(int)"},{"p":"com.google.android.exoplayer2.text","c":"Subtitle","l":"getEventTime(int)"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleOutputBuffer","l":"getEventTime(int)"},{"p":"com.google.android.exoplayer2.text","c":"Subtitle","l":"getEventTimeCount()"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleOutputBuffer","l":"getEventTimeCount()"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"getExoMediaCryptoType()"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"getExoMediaCryptoType()"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"getExoMediaCryptoType()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"getExoMediaCryptoType()"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"getExoMediaCryptoType(Format)","url":"getExoMediaCryptoType(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionManager","l":"getExoMediaCryptoType(Format)","url":"getExoMediaCryptoType(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.TestResource","l":"getExpectedBytes()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"getExtractorInputFromPosition(DataSource, long, Uri)","url":"getExtractorInputFromPosition(com.google.android.exoplayer2.upstream.DataSource,long,android.net.Uri)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultLoadErrorHandlingPolicy","l":"getFallbackSelectionFor(LoadErrorHandlingPolicy.FallbackOptions, LoadErrorHandlingPolicy.LoadErrorInfo)","url":"getFallbackSelectionFor(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.FallbackOptions,com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.LoadErrorInfo)"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy","l":"getFallbackSelectionFor(LoadErrorHandlingPolicy.FallbackOptions, LoadErrorHandlingPolicy.LoadErrorInfo)","url":"getFallbackSelectionFor(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.FallbackOptions,com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.LoadErrorInfo)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"getFastForwardIncrementMs(Player)","url":"getFastForwardIncrementMs(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getFatalErrorRate()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getFatalErrorRatio()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"getFirstAdIndexToPlay()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getFirstAdIndexToPlay(int)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashSegmentIndex","l":"getFirstAvailableSegmentNum(long, long)","url":"getFirstAvailableSegmentNum(long,long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashWrappingSegmentIndex","l":"getFirstAvailableSegmentNum(long, long)","url":"getFirstAvailableSegmentNum(long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"getFirstAvailableSegmentNum(long, long)","url":"getFirstAvailableSegmentNum(long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.MultiSegmentBase","l":"getFirstAvailableSegmentNum(long, long)","url":"getFirstAvailableSegmentNum(long,long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationHolder","l":"getFirstAvailableSegmentNum(long)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"getFirstIndex()"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder","l":"getFirstIndex()"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.DefaultShuffleOrder","l":"getFirstIndex()"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.UnshuffledShuffleOrder","l":"getFirstIndex()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeShuffleOrder","l":"getFirstIndex()"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getFirstPeriodIndexByChildIndex(int)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunk","l":"getFirstSampleIndex(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacFrameReader","l":"getFirstSampleNumber(ExtractorInput, FlacStreamMetadata)","url":"getFirstSampleNumber(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.FlacStreamMetadata)"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"getFirstSampleTimestampUs()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashSegmentIndex","l":"getFirstSegmentNum()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashWrappingSegmentIndex","l":"getFirstSegmentNum()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationHolder","l":"getFirstSegmentNum()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"getFirstSegmentNum()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.MultiSegmentBase","l":"getFirstSegmentNum()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"getFirstTimestampUs()"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getFirstWindowIndex(boolean)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getFirstWindowIndex(boolean)"},{"p":"com.google.android.exoplayer2","c":"Timeline.RemotableTimeline","l":"getFirstWindowIndex(boolean)"},{"p":"com.google.android.exoplayer2.source","c":"ForwardingTimeline","l":"getFirstWindowIndex(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"getFirstWindowIndex(boolean)"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getFirstWindowIndexByChildIndex(int)"},{"p":"com.google.android.exoplayer2.decoder","c":"Buffer","l":"getFlag(int)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"getFontColor()"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"getFontFamily()"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"getFontSize()"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"getFontSizeUnit()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"getForegroundNotification(List)","url":"getForegroundNotification(java.util.List)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"getFormat(byte[], Metadata)","url":"getFormat(byte[],com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroup","l":"getFormat(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"getFormat(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"getFormat(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelection","l":"getFormat(int)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"getFormatHolder()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.TrackIdGenerator","l":"getFormatId()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"getFormatLanguageScore(Format, String, boolean)","url":"getFormatLanguageScore(com.google.android.exoplayer2.Format,java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"getFormatsRead()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"getFormatSupport(Format)","url":"getFormatSupport(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"getFormatSupport(Format)","url":"getFormatSupport(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"getFormatSupport(Format)","url":"getFormatSupport(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"getFormatSupport(int)"},{"p":"com.google.android.exoplayer2","c":"C","l":"getFormatSupportString(int)"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil","l":"getFrameSize(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacMetadataReader","l":"getFrameStartMarker(ExtractorInput)","url":"getFrameStartMarker(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.decoder","c":"CryptoInfo","l":"getFrameworkCryptoInfo()"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource","l":"getGzipSupport()"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil","l":"getH265NalUnitType(byte[], int)","url":"getH265NalUnitType(byte[],int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"getHttpMethodString()"},{"p":"com.google.android.exoplayer2.offline","c":"ActionFileUpgradeUtil.DownloadIdProvider","l":"getId(DownloadRequest)","url":"getId(com.google.android.exoplayer2.offline.DownloadRequest)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpUtils","l":"getIncomingRtpDataSpec(int)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"getIndex()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"getIndex()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"getIndex()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"getIndex()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.SingleSegmentRepresentation","l":"getIndex()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SingleSegmentBase","l":"getIndex()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"getIndexInTrackGroup(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"getIndexInTrackGroup(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelection","l":"getIndexInTrackGroup(int)"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getIndexOfPeriod(Object)","url":"getIndexOfPeriod(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getIndexOfPeriod(Object)","url":"getIndexOfPeriod(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"Timeline.RemotableTimeline","l":"getIndexOfPeriod(Object)","url":"getIndexOfPeriod(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"ForwardingTimeline","l":"getIndexOfPeriod(Object)","url":"getIndexOfPeriod(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource.PlaceholderTimeline","l":"getIndexOfPeriod(Object)","url":"getIndexOfPeriod(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"getIndexOfPeriod(Object)","url":"getIndexOfPeriod(java.lang.Object)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"getIndexOfPeriod(Object)","url":"getIndexOfPeriod(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"getIndexUri()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"getIndexUri()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.SingleSegmentRepresentation","l":"getIndexUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"Allocator","l":"getIndividualAllocationLength()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultAllocator","l":"getIndividualAllocationLength()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase","l":"getInitialization(Representation)","url":"getInitialization(com.google.android.exoplayer2.source.dash.manifest.Representation)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SegmentTemplate","l":"getInitialization(Representation)","url":"getInitialization(com.google.android.exoplayer2.source.dash.manifest.Representation)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"getInitializationUri()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"getInitialStartTimeUs()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"getInitialStartTimeUs()"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"getInitialTimeline()"},{"p":"com.google.android.exoplayer2.source","c":"LoopingMediaSource","l":"getInitialTimeline()"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"getInitialTimeline()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"getInitialTimeline()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"getInMemoryDatabaseProvider()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"getInputBuffer(int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"getInputBuffer(int)"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegLibrary","l":"getInputBufferPaddingSize()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"getInputStream(Context, String)","url":"getInputStream(android.content.Context,java.lang.String)"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"getInstance()"},{"p":"com.google.android.exoplayer2.util","c":"NetworkTypeObserver","l":"getInstance(Context)","url":"getInstance(android.content.Context)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getIntegerCodeForString(String)","url":"getIntegerCodeForString(java.lang.String)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionView","l":"getIsDisabled()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getItem(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getJoinTimeRatio()"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyStatus","l":"getKeyId()"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"getKeyRequest(byte[], List, int, HashMap)","url":"getKeyRequest(byte[],java.util.List,int,java.util.HashMap)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"getKeyRequest(byte[], List, int, HashMap)","url":"getKeyRequest(byte[],java.util.List,int,java.util.HashMap)"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"getKeyRequest(byte[], List, int, HashMap)","url":"getKeyRequest(byte[],java.util.List,int,java.util.HashMap)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"getKeyRequest(byte[], List, int, HashMap)","url":"getKeyRequest(byte[],java.util.List,int,java.util.HashMap)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"getKeys()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"getKeys()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.DrmConfiguration","l":"getKeySetId()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"getLargestQueuedTimestampUs()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"getLargestQueuedTimestampUs()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"getLargestReadTimestampUs()"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"getLastAdjustedTimestampUs()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationHolder","l":"getLastAvailableSegmentNum(long)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder","l":"getLastIndex()"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.DefaultShuffleOrder","l":"getLastIndex()"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.UnshuffledShuffleOrder","l":"getLastIndex()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeShuffleOrder","l":"getLastIndex()"},{"p":"com.google.android.exoplayer2.upstream","c":"StatsDataSource","l":"getLastOpenedUri()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"getLastResetPositionUs()"},{"p":"com.google.android.exoplayer2.upstream","c":"StatsDataSource","l":"getLastResponseHeaders()"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getLastWindowIndex(boolean)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getLastWindowIndex(boolean)"},{"p":"com.google.android.exoplayer2","c":"Timeline.RemotableTimeline","l":"getLastWindowIndex(boolean)"},{"p":"com.google.android.exoplayer2.source","c":"ForwardingTimeline","l":"getLastWindowIndex(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"getLastWindowIndex(boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"getLength()"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"getLength()"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"getLength()"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder","l":"getLength()"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.DefaultShuffleOrder","l":"getLength()"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.UnshuffledShuffleOrder","l":"getLength()"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"InputReaderAdapterV30","l":"getLength()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"getLength()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeShuffleOrder","l":"getLength()"},{"p":"com.google.android.exoplayer2.drm","c":"OfflineLicenseHelper","l":"getLicenseDurationRemainingSec(byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"WidevineUtil","l":"getLicenseDurationRemainingSec(DrmSession)","url":"getLicenseDurationRemainingSec(com.google.android.exoplayer2.drm.DrmSession)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyRequest","l":"getLicenseServerUrl()"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getLine()"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getLineAnchor()"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getLineType()"},{"p":"com.google.android.exoplayer2","c":"BundleListRetriever","l":"getList(IBinder)","url":"getList(android.os.IBinder)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"getLoadControl()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getLocaleLanguageTag(Locale)","url":"getLocaleLanguageTag(java.util.Locale)"},{"p":"com.google.android.exoplayer2.upstream","c":"UdpDataSource","l":"getLocalPort()"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"getLogLevel()"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"getLooper()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"getLooper()"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"getLooper()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"getManifest()"},{"p":"com.google.android.exoplayer2.offline","c":"SegmentDownloader","l":"getManifest(DataSource, DataSpec, boolean)","url":"getManifest(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"getMappedTrackInfo(int)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"getMasterPlaylist()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"getMasterPlaylist()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioCapabilities","l":"getMaxChannelCount()"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"getMaxDecodedFrameSize()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"getMaxInputSize(MediaCodecInfo, Format)","url":"getMaxInputSize(com.google.android.exoplayer2.mediacodec.MediaCodecInfo,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"getMaxParallelDownloads()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getMaxSeekToPreviousPosition()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getMaxSeekToPreviousPosition()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getMaxSeekToPreviousPosition()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getMaxSeekToPreviousPosition()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getMaxSeekToPreviousPosition()"},{"p":"com.google.android.exoplayer2","c":"StarRating","l":"getMaxStars()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"getMaxSupportedInstances()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanAudioFormatBitrate()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanBandwidth()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanElapsedTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanInitialAudioFormatBitrate()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanInitialVideoFormatBitrate()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanInitialVideoFormatHeight()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanJoinTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanNonFatalErrorCount()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanPauseBufferCount()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanPauseCount()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanPausedTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanPlayAndWaitTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanPlayTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanRebufferCount()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanRebufferTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanSeekCount()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanSeekTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanSingleRebufferTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanSingleSeekTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanTimeBetweenFatalErrors()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanTimeBetweenNonFatalErrors()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanTimeBetweenRebuffers()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanVideoFormatBitrate()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanVideoFormatHeight()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMeanWaitTimeMs()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"getMediaClock()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"getMediaClock()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"getMediaClock()"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"getMediaClock()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"getMediaClock()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaClockRenderer","l":"getMediaClock()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"getMediaCodecConfiguration(MediaCodecInfo, Format, MediaCrypto, float)","url":"getMediaCodecConfiguration(com.google.android.exoplayer2.mediacodec.MediaCodecInfo,com.google.android.exoplayer2.Format,android.media.MediaCrypto,float)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"getMediaCodecConfiguration(MediaCodecInfo, Format, MediaCrypto, float)","url":"getMediaCodecConfiguration(com.google.android.exoplayer2.mediacodec.MediaCodecInfo,com.google.android.exoplayer2.Format,android.media.MediaCrypto,float)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"getMediaCodecConfiguration(MediaCodecInfo, Format, MediaCrypto, float)","url":"getMediaCodecConfiguration(com.google.android.exoplayer2.mediacodec.MediaCodecInfo,com.google.android.exoplayer2.Format,android.media.MediaCrypto,float)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"getMediaCrypto()"},{"p":"com.google.android.exoplayer2.drm","c":"ErrorStateDrmSession","l":"getMediaCrypto()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueNavigator","l":"getMediaDescription(Player, int)","url":"getMediaDescription(com.google.android.exoplayer2.Player,int)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink.AudioProcessorChain","l":"getMediaDuration(long)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink.DefaultAudioProcessorChain","l":"getMediaDuration(long)"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"getMediaDuration(long)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getMediaDurationForPlayoutDuration(long, float)","url":"getMediaDurationForPlayoutDuration(long,float)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"getMediaFormat(Format, String, int, float)","url":"getMediaFormat(com.google.android.exoplayer2.Format,java.lang.String,int,float)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"getMediaFormat(Format, String, MediaCodecVideoRenderer.CodecMaxValues, float, boolean, int)","url":"getMediaFormat(com.google.android.exoplayer2.Format,java.lang.String,com.google.android.exoplayer2.video.MediaCodecVideoRenderer.CodecMaxValues,float,boolean,int)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source","c":"LoopingMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"getMediaItem()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"getMediaItemAt(int)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getMediaItemAt(int)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getMediaItemAt(int)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"getMediaItemCount()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getMediaItemCount()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getMediaItemCount()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getMediaMetadata()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getMediaMetadata()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getMediaMetadata()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getMediaMetadata()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getMediaMetadata()"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"getMediaMimeType(String)","url":"getMediaMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"getMediaPeriodIdForChildMediaPeriodId(ConcatenatingMediaSource.MediaSourceHolder, MediaSource.MediaPeriodId)","url":"getMediaPeriodIdForChildMediaPeriodId(com.google.android.exoplayer2.source.ConcatenatingMediaSource.MediaSourceHolder,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"getMediaPeriodIdForChildMediaPeriodId(Integer, MediaSource.MediaPeriodId)","url":"getMediaPeriodIdForChildMediaPeriodId(java.lang.Integer,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource","l":"getMediaPeriodIdForChildMediaPeriodId(MediaSource.MediaPeriodId, MediaSource.MediaPeriodId)","url":"getMediaPeriodIdForChildMediaPeriodId(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"getMediaPeriodIdForChildMediaPeriodId(T, MediaSource.MediaPeriodId)","url":"getMediaPeriodIdForChildMediaPeriodId(T,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source","c":"LoopingMediaSource","l":"getMediaPeriodIdForChildMediaPeriodId(Void, MediaSource.MediaPeriodId)","url":"getMediaPeriodIdForChildMediaPeriodId(java.lang.Void,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource","l":"getMediaPeriodIdForChildMediaPeriodId(Void, MediaSource.MediaPeriodId)","url":"getMediaPeriodIdForChildMediaPeriodId(java.lang.Void,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsUtil","l":"getMediaPeriodPositionUs(long, MediaPeriodId, AdPlaybackState)","url":"getMediaPeriodPositionUs(long,com.google.android.exoplayer2.source.MediaPeriodId,com.google.android.exoplayer2.source.ads.AdPlaybackState)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsUtil","l":"getMediaPeriodPositionUsForAd(long, int, int, AdPlaybackState)","url":"getMediaPeriodPositionUsForAd(long,int,int,com.google.android.exoplayer2.source.ads.AdPlaybackState)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsUtil","l":"getMediaPeriodPositionUsForContent(long, int, AdPlaybackState)","url":"getMediaPeriodPositionUsForContent(long,int,com.google.android.exoplayer2.source.ads.AdPlaybackState)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"getMediaSource(int)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"getMediaTimeForChildMediaTime(T, long)","url":"getMediaTimeForChildMediaTime(T,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getMediaTimeMsAtRealtimeMs(long)"},{"p":"com.google.android.exoplayer2","c":"PlaybackParameters","l":"getMediaTimeUsForPlayoutTimeMs(long)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"DefaultMediaItemConverter","l":"getMetadata(MediaItem)","url":"getMetadata(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.DefaultMediaMetadataProvider","l":"getMetadata(Player)","url":"getMetadata(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.MediaMetadataProvider","l":"getMetadata(Player)","url":"getMetadata(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getMetadataComponent()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getMetadataComponent()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getMetadataComponent()"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"getMetadataCopyWithAppendedEntriesFrom(Metadata)","url":"getMetadataCopyWithAppendedEntriesFrom(com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"getMetrics()"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"getMetrics()"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"getMetrics()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"getMetrics()"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"getMimeTypeFromMp4ObjectType(int)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPayloadFormat","l":"getMimeTypeFromRtpMediaType(String)","url":"getMimeTypeFromRtpMediaType(java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"getMinDurationToRetainAfterDiscardUs()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultLoadErrorHandlingPolicy","l":"getMinimumLoadableRetryCount(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy","l":"getMinimumLoadableRetryCount(int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"getMinRetryCount()"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil","l":"getNalUnitType(byte[], int)","url":"getNalUnitType(byte[],int)"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"getName()"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"getName()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"getName()"},{"p":"com.google.android.exoplayer2.decoder","c":"Decoder","l":"getName()"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Gav1Decoder","l":"getName()"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Libgav1VideoRenderer","l":"getName()"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegAudioRenderer","l":"getName()"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacDecoder","l":"getName()"},{"p":"com.google.android.exoplayer2.ext.flac","c":"LibflacAudioRenderer","l":"getName()"},{"p":"com.google.android.exoplayer2.ext.opus","c":"LibopusAudioRenderer","l":"getName()"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusDecoder","l":"getName()"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"LibvpxVideoRenderer","l":"getName()"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxDecoder","l":"getName()"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataRenderer","l":"getName()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.TestResource","l":"getName()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"getName()"},{"p":"com.google.android.exoplayer2.text","c":"SimpleSubtitleDecoder","l":"getName()"},{"p":"com.google.android.exoplayer2.text","c":"TextRenderer","l":"getName()"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea608Decoder","l":"getName()"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea708Decoder","l":"getName()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"getName()"},{"p":"com.google.android.exoplayer2.video.spherical","c":"CameraMotionRenderer","l":"getName()"},{"p":"com.google.android.exoplayer2.util","c":"NetworkTypeObserver","l":"getNetworkType()"},{"p":"com.google.android.exoplayer2.source","c":"LoadEventInfo","l":"getNewId()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getNextAdIndexToPlay(int, int)","url":"getNextAdIndexToPlay(int,int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"getNextAdIndexToPlay(int)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSource","l":"getNextChunk(long, long, List, ChunkHolder)","url":"getNextChunk(long,long,java.util.List,com.google.android.exoplayer2.source.chunk.ChunkHolder)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"getNextChunk(long, long, List, ChunkHolder)","url":"getNextChunk(long,long,java.util.List,com.google.android.exoplayer2.source.chunk.ChunkHolder)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource","l":"getNextChunk(long, long, List, ChunkHolder)","url":"getNextChunk(long,long,java.util.List,com.google.android.exoplayer2.source.chunk.ChunkHolder)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource","l":"getNextChunk(long, long, List, ChunkHolder)","url":"getNextChunk(long,long,java.util.List,com.google.android.exoplayer2.source.chunk.ChunkHolder)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ContainerMediaChunk","l":"getNextChunkIndex()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaChunk","l":"getNextChunkIndex()"},{"p":"com.google.android.exoplayer2.text","c":"Subtitle","l":"getNextEventTimeIndex(long)"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleOutputBuffer","l":"getNextEventTimeIndex(long)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder","l":"getNextIndex(int)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.DefaultShuffleOrder","l":"getNextIndex(int)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.UnshuffledShuffleOrder","l":"getNextIndex(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeShuffleOrder","l":"getNextIndex(int)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"getNextLoadPositionUs()"},{"p":"com.google.android.exoplayer2.source","c":"CompositeSequenceableLoader","l":"getNextLoadPositionUs()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"getNextLoadPositionUs()"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"getNextLoadPositionUs()"},{"p":"com.google.android.exoplayer2.source","c":"SequenceableLoader","l":"getNextLoadPositionUs()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"getNextLoadPositionUs()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"getNextLoadPositionUs()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"getNextLoadPositionUs()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"getNextLoadPositionUs()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getNextMediaItemIndex()"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getNextPeriodIndex(int, Timeline.Period, Timeline.Window, int, boolean)","url":"getNextPeriodIndex(int,com.google.android.exoplayer2.Timeline.Period,com.google.android.exoplayer2.Timeline.Window,int,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"RepeatModeUtil","l":"getNextRepeatMode(int, int)","url":"getNextRepeatMode(int,int)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashSegmentIndex","l":"getNextSegmentAvailableTimeUs(long, long)","url":"getNextSegmentAvailableTimeUs(long,long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashWrappingSegmentIndex","l":"getNextSegmentAvailableTimeUs(long, long)","url":"getNextSegmentAvailableTimeUs(long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"getNextSegmentAvailableTimeUs(long, long)","url":"getNextSegmentAvailableTimeUs(long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.MultiSegmentBase","l":"getNextSegmentAvailableTimeUs(long, long)","url":"getNextSegmentAvailableTimeUs(long,long)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"getNextWindowIndex()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getNextWindowIndex()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getNextWindowIndex()"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getNextWindowIndex(int, int, boolean)","url":"getNextWindowIndex(int,int,boolean)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getNextWindowIndex(int, int, boolean)","url":"getNextWindowIndex(int,int,boolean)"},{"p":"com.google.android.exoplayer2","c":"Timeline.RemotableTimeline","l":"getNextWindowIndex(int, int, boolean)","url":"getNextWindowIndex(int,int,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"ForwardingTimeline","l":"getNextWindowIndex(int, int, boolean)","url":"getNextWindowIndex(int,int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"getNextWindowIndex(int, int, boolean)","url":"getNextWindowIndex(int,int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"HttpDataSourceTestEnv","l":"getNonexistentUrl()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getNonFatalErrorRate()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"getNotFoundUri()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"getNotMetRequirements()"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"getNotMetRequirements(Context)","url":"getNotMetRequirements(android.content.Context)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getNowUnixTimeMs(long)"},{"p":"com.google.android.exoplayer2.util","c":"SntpClient","l":"getNtpHost()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"getOfflineLicenseKeySetId()"},{"p":"com.google.android.exoplayer2.drm","c":"ErrorStateDrmSession","l":"getOfflineLicenseKeySetId()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"getOngoing(Player)","url":"getOngoing(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor","l":"getOutput()"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"getOutput()"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"getOutput()"},{"p":"com.google.android.exoplayer2.ext.gvr","c":"GvrAudioProcessor","l":"getOutput()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunk","l":"getOutput()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"getOutputBuffer(int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"getOutputBuffer(int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"getOutputFormat()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"getOutputFormat()"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegAudioRenderer","l":"getOutputFormat(FfmpegAudioDecoder)","url":"getOutputFormat(com.google.android.exoplayer2.ext.ffmpeg.FfmpegAudioDecoder)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"LibflacAudioRenderer","l":"getOutputFormat(FlacDecoder)","url":"getOutputFormat(com.google.android.exoplayer2.ext.flac.FlacDecoder)"},{"p":"com.google.android.exoplayer2.ext.opus","c":"LibopusAudioRenderer","l":"getOutputFormat(OpusDecoder)","url":"getOutputFormat(com.google.android.exoplayer2.ext.opus.OpusDecoder)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"getOutputFormat(T)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"getOutputStreamOffsetUs()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getOverlayFrameLayout()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getOverlayFrameLayout()"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionView","l":"getOverrides()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"getParameters()"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource","l":"getPath()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getPauseAtEndOfMediaItems()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getPauseAtEndOfMediaItems()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getPauseAtEndOfMediaItems()"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"getPayload()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getPcmEncoding(int)"},{"p":"com.google.android.exoplayer2.audio","c":"WavUtil","l":"getPcmEncodingForType(int, int)","url":"getPcmEncodingForType(int,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getPcmFormat(int, int, int)","url":"getPcmFormat(int,int,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getPcmFrameSize(int, int)","url":"getPcmFrameSize(int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"getPeekPosition()"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"getPeekPosition()"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"getPeekPosition()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"getPeekPosition()"},{"p":"com.google.android.exoplayer2","c":"PercentageRating","l":"getPercent()"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"getPercentDownloaded()"},{"p":"com.google.android.exoplayer2.util","c":"SlidingPercentile","l":"getPercentile(float)"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getPeriod(int, Timeline.Period, boolean)","url":"getPeriod(int,com.google.android.exoplayer2.Timeline.Period,boolean)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getPeriod(int, Timeline.Period, boolean)","url":"getPeriod(int,com.google.android.exoplayer2.Timeline.Period,boolean)"},{"p":"com.google.android.exoplayer2","c":"Timeline.RemotableTimeline","l":"getPeriod(int, Timeline.Period, boolean)","url":"getPeriod(int,com.google.android.exoplayer2.Timeline.Period,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"ForwardingTimeline","l":"getPeriod(int, Timeline.Period, boolean)","url":"getPeriod(int,com.google.android.exoplayer2.Timeline.Period,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource.PlaceholderTimeline","l":"getPeriod(int, Timeline.Period, boolean)","url":"getPeriod(int,com.google.android.exoplayer2.Timeline.Period,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"getPeriod(int, Timeline.Period, boolean)","url":"getPeriod(int,com.google.android.exoplayer2.Timeline.Period,boolean)"},{"p":"com.google.android.exoplayer2.source.ads","c":"SinglePeriodAdTimeline","l":"getPeriod(int, Timeline.Period, boolean)","url":"getPeriod(int,com.google.android.exoplayer2.Timeline.Period,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"getPeriod(int, Timeline.Period, boolean)","url":"getPeriod(int,com.google.android.exoplayer2.Timeline.Period,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"NoUidTimeline","l":"getPeriod(int, Timeline.Period, boolean)","url":"getPeriod(int,com.google.android.exoplayer2.Timeline.Period,boolean)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getPeriod(int, Timeline.Period)","url":"getPeriod(int,com.google.android.exoplayer2.Timeline.Period)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"getPeriod(int)"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getPeriodByUid(Object, Timeline.Period)","url":"getPeriodByUid(java.lang.Object,com.google.android.exoplayer2.Timeline.Period)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getPeriodByUid(Object, Timeline.Period)","url":"getPeriodByUid(java.lang.Object,com.google.android.exoplayer2.Timeline.Period)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getPeriodCount()"},{"p":"com.google.android.exoplayer2","c":"Timeline.RemotableTimeline","l":"getPeriodCount()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"getPeriodCount()"},{"p":"com.google.android.exoplayer2.source","c":"ForwardingTimeline","l":"getPeriodCount()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource.PlaceholderTimeline","l":"getPeriodCount()"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"getPeriodCount()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"getPeriodCount()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"getPeriodCount()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"getPeriodDurationMs(int)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"getPeriodDurationUs(int)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getPeriodPosition(Timeline.Window, Timeline.Period, int, long, long)","url":"getPeriodPosition(com.google.android.exoplayer2.Timeline.Window,com.google.android.exoplayer2.Timeline.Period,int,long,long)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getPeriodPosition(Timeline.Window, Timeline.Period, int, long)","url":"getPeriodPosition(com.google.android.exoplayer2.Timeline.Window,com.google.android.exoplayer2.Timeline.Period,int,long)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"getPixelCount()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getPlaybackLooper()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getPlaybackLooper()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getPlaybackLooper()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getPlaybackParameters()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getPlaybackParameters()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getPlaybackParameters()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"getPlaybackParameters()"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"getPlaybackParameters()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"getPlaybackParameters()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"getPlaybackParameters()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"getPlaybackParameters()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getPlaybackParameters()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getPlaybackParameters()"},{"p":"com.google.android.exoplayer2.util","c":"MediaClock","l":"getPlaybackParameters()"},{"p":"com.google.android.exoplayer2.util","c":"StandaloneMediaClock","l":"getPlaybackParameters()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getPlaybackSpeed()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"getPlaybackSpeed()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getPlaybackState()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getPlaybackState()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getPlaybackState()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getPlaybackState()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getPlaybackState()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getPlaybackStateAtTime(long)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getPlaybackStateDurationMs(@com.google.android.exoplayer2.analytics.PlaybackStats.PlaybackState int)","url":"getPlaybackStateDurationMs(@com.google.android.exoplayer2.analytics.PlaybackStats.PlaybackStateint)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"getPlaybackStats()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getPlaybackSuppressionReason()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getPlaybackSuppressionReason()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getPlaybackSuppressionReason()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getPlaybackSuppressionReason()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getPlaybackSuppressionReason()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"getPlayer()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getPlayer()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"getPlayer()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getPlayer()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getPlayerError()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getPlayerError()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getPlayerError()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getPlayerError()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getPlayerError()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getPlayerError()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getPlayerState()"},{"p":"com.google.android.exoplayer2.util","c":"DebugTextViewHelper","l":"getPlayerStateString()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getPlaylist()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getPlaylistMetadata()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getPlaylistMetadata()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getPlaylistMetadata()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getPlaylistMetadata()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getPlaylistMetadata()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getPlaylistMetadata()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"getPlaylistSnapshot(Uri, boolean)","url":"getPlaylistSnapshot(android.net.Uri,boolean)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"getPlaylistSnapshot(Uri, boolean)","url":"getPlaylistSnapshot(android.net.Uri,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getPlayoutDurationForMediaDuration(long, float)","url":"getPlayoutDurationForMediaDuration(long,float)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getPlayWhenReady()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getPlayWhenReady()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getPlayWhenReady()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getPlayWhenReady()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getPlayWhenReady()"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"getPosition()"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"getPosition()"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"getPosition()"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisBitArray","l":"getPosition()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"getPosition()"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"InputReaderAdapterV30","l":"getPosition()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"getPosition()"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getPosition()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"getPosition()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"getPosition()"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getPositionAnchor()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"getPositionInFirstPeriodMs()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"getPositionInFirstPeriodUs()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getPositionInWindowMs()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getPositionInWindowUs()"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"getPositionMs()"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"getPositionUs()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"getPositionUs()"},{"p":"com.google.android.exoplayer2.util","c":"MediaClock","l":"getPositionUs()"},{"p":"com.google.android.exoplayer2.util","c":"StandaloneMediaClock","l":"getPositionUs()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSource","l":"getPreferredQueueSize(long, List)","url":"getPreferredQueueSize(long,java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"getPreferredQueueSize(long, List)","url":"getPreferredQueueSize(long,java.util.List)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource","l":"getPreferredQueueSize(long, List)","url":"getPreferredQueueSize(long,java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource","l":"getPreferredQueueSize(long, List)","url":"getPreferredQueueSize(long,java.util.List)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"getPreferredUpdateDelay()"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar","l":"getPreferredUpdateDelay()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"getPreparePositionOverrideUs()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"getPreparePositionUs()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase","l":"getPresentationTimeOffsetUs()"},{"p":"com.google.android.exoplayer2.audio","c":"OpusUtil","l":"getPreSkipSamples(List)","url":"getPreSkipSamples(java.util.List)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder","l":"getPreviousIndex(int)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.DefaultShuffleOrder","l":"getPreviousIndex(int)"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.UnshuffledShuffleOrder","l":"getPreviousIndex(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeShuffleOrder","l":"getPreviousIndex(int)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getPreviousMediaItemIndex()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"getPreviousWindowIndex()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getPreviousWindowIndex()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getPreviousWindowIndex()"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getPreviousWindowIndex(int, int, boolean)","url":"getPreviousWindowIndex(int,int,boolean)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getPreviousWindowIndex(int, int, boolean)","url":"getPreviousWindowIndex(int,int,boolean)"},{"p":"com.google.android.exoplayer2","c":"Timeline.RemotableTimeline","l":"getPreviousWindowIndex(int, int, boolean)","url":"getPreviousWindowIndex(int,int,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"ForwardingTimeline","l":"getPreviousWindowIndex(int, int, boolean)","url":"getPreviousWindowIndex(int,int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"getPreviousWindowIndex(int, int, boolean)","url":"getPreviousWindowIndex(int,int,boolean)"},{"p":"com.google.android.exoplayer2.source.dash","c":"BaseUrlExclusionList","l":"getPriorityCount(List)","url":"getPriorityCount(java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash","c":"BaseUrlExclusionList","l":"getPriorityCountAfterExclusion(List)","url":"getPriorityCountAfterExclusion(java.util.List)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"getProfileLevels()"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer","l":"getProgress(ProgressHolder)","url":"getProgress(com.google.android.exoplayer2.transformer.ProgressHolder)"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"getPropertyByteArray(String)","url":"getPropertyByteArray(java.lang.String)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"getPropertyByteArray(String)","url":"getPropertyByteArray(java.lang.String)"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"getPropertyByteArray(String)","url":"getPropertyByteArray(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"getPropertyByteArray(String)","url":"getPropertyByteArray(java.lang.String)"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"getPropertyString(String)","url":"getPropertyString(java.lang.String)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"getPropertyString(String)","url":"getPropertyString(java.lang.String)"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"getPropertyString(String)","url":"getPropertyString(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"getPropertyString(String)","url":"getPropertyString(java.lang.String)"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"getProvisionRequest()"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"getProvisionRequest()"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"getProvisionRequest()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"getProvisionRequest()"},{"p":"com.google.android.exoplayer2.database","c":"DatabaseProvider","l":"getReadableDatabase()"},{"p":"com.google.android.exoplayer2.database","c":"DefaultDatabaseProvider","l":"getReadableDatabase()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"getReadIndex()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"getReadingPositionUs()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"getReadingPositionUs()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"getReadingPositionUs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getRebufferRate()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getRebufferTimeRatio()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm.LicenseServer","l":"getReceivedSchemeDatas()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadata","l":"getRedirectedUri(ContentMetadata)","url":"getRedirectedUri(com.google.android.exoplayer2.upstream.cache.ContentMetadata)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"getReferenceCount()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CachedRegionTracker","l":"getRegionEndTimeMs(long)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"getRemovedAdGroupCount()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadataMutations","l":"getRemovedValues()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"getRendererCapabilities(RenderersFactory)","url":"getRendererCapabilities(com.google.android.exoplayer2.RenderersFactory)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getRendererCount()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getRendererCount()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getRendererCount()"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"getRendererCount()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"getRendererDisabled(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"getRendererException()"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"getRendererName(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"getRenderers()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"getRenderersFactory()"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"getRendererSupport(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getRendererType(int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getRendererType(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getRendererType(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"getRendererType(int)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getRepeatMode()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getRepeatMode()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getRepeatMode()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getRepeatMode()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getRepeatMode()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getRepeatMode()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"getRepeatToggleModes()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"getRepeatToggleModes()"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher","l":"getRequestPath(RecordedRequest)","url":"getRequestPath(okhttp3.mockwebserver.RecordedRequest)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyRequest","l":"getRequestType()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"getRequirements()"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"getRequirements()"},{"p":"com.google.android.exoplayer2.scheduler","c":"RequirementsWatcher","l":"getRequirements()"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout","l":"getResizeMode()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getResizeMode()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getResizeMode()"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"getResponseCode()"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"getResponseCode()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"getResponseCode()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource","l":"getResponseCode()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"getResponseHeaders_isEmptyWhileNotOpen()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"getResponseHeaders_resourceNotFound_isEmptyWhileNotOpen()"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSource","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSource","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.upstream","c":"PriorityDataSource","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.upstream","c":"ResolvingDataSource","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.upstream","c":"StatsDataSource","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.upstream","c":"TeeDataSource","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesCipherDataSource","l":"getResponseHeaders()"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"getResult()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultLoadErrorHandlingPolicy","l":"getRetryDelayMsFor(LoadErrorHandlingPolicy.LoadErrorInfo)","url":"getRetryDelayMsFor(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.LoadErrorInfo)"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy","l":"getRetryDelayMsFor(LoadErrorHandlingPolicy.LoadErrorInfo)","url":"getRetryDelayMsFor(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.LoadErrorInfo)"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"getRewindIncrementMs(Player)","url":"getRewindIncrementMs(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"getRubyPosition()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource.AdLoadException","l":"getRuntimeExceptionForUnexpected()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"getSampleCount()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"getSampleCryptoData(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"getSampleData(int)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"getSampleDescriptionEncryptionBox(int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsReader","l":"getSampleDurationUs()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"getSampleFlags(int)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BundledChunkExtractor","l":"getSampleFormats()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkExtractor","l":"getSampleFormats()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaParserChunkExtractor","l":"getSampleFormats()"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"getSampleFormats()"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"getSampleNumber(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"getSampleTimesUs()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"getSampleTimeUs(int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"getScheduler()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"getSchemeUuid()"},{"p":"com.google.android.exoplayer2.drm","c":"ErrorStateDrmSession","l":"getSchemeUuid()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getSeekBackIncrement()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getSeekBackIncrement()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getSeekBackIncrement()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getSeekBackIncrement()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getSeekBackIncrement()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"getSeekBackIncrementMs()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getSeekForwardIncrement()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getSeekForwardIncrement()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getSeekForwardIncrement()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getSeekForwardIncrement()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getSeekForwardIncrement()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"getSeekForwardIncrementMs()"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"getSeekMap()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getSeekParameters()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getSeekParameters()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getSeekParameters()"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.BinarySearchSeekMap","l":"getSeekPoints(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"ChunkIndex","l":"getSeekPoints(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"ConstantBitrateSeekMap","l":"getSeekPoints(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacSeekTableSeekMap","l":"getSeekPoints(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"IndexSeekMap","l":"getSeekPoints(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap","l":"getSeekPoints(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap.Unseekable","l":"getSeekPoints(long)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"getSeekPoints(long)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"getSeekPoints(long)"},{"p":"com.google.android.exoplayer2.audio","c":"OpusUtil","l":"getSeekPreRollSamples(List)","url":"getSeekPreRollSamples(java.util.List)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getSeekTimeRatio()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationHolder","l":"getSegmentCount()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashSegmentIndex","l":"getSegmentCount(long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashWrappingSegmentIndex","l":"getSegmentCount(long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"getSegmentCount(long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.MultiSegmentBase","l":"getSegmentCount(long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SegmentList","l":"getSegmentCount(long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SegmentTemplate","l":"getSegmentCount(long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.MultiSegmentBase","l":"getSegmentDurationUs(long, long)","url":"getSegmentDurationUs(long,long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationHolder","l":"getSegmentEndTimeUs(long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashSegmentIndex","l":"getSegmentNum(long, long)","url":"getSegmentNum(long,long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashWrappingSegmentIndex","l":"getSegmentNum(long, long)","url":"getSegmentNum(long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"getSegmentNum(long, long)","url":"getSegmentNum(long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.MultiSegmentBase","l":"getSegmentNum(long, long)","url":"getSegmentNum(long,long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationHolder","l":"getSegmentNum(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData","l":"getSegments()"},{"p":"com.google.android.exoplayer2.source.dash.offline","c":"DashDownloader","l":"getSegments(DataSource, DashManifest, boolean)","url":"getSegments(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.source.dash.manifest.DashManifest,boolean)"},{"p":"com.google.android.exoplayer2.source.hls.offline","c":"HlsDownloader","l":"getSegments(DataSource, HlsPlaylist, boolean)","url":"getSegments(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.source.hls.playlist.HlsPlaylist,boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"SegmentDownloader","l":"getSegments(DataSource, M, boolean)","url":"getSegments(com.google.android.exoplayer2.upstream.DataSource,M,boolean)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.offline","c":"SsDownloader","l":"getSegments(DataSource, SsManifest, boolean)","url":"getSegments(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest,boolean)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationHolder","l":"getSegmentStartTimeUs(long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.MultiSegmentBase","l":"getSegmentTimeUs(long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashSegmentIndex","l":"getSegmentUrl(long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashWrappingSegmentIndex","l":"getSegmentUrl(long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationHolder","l":"getSegmentUrl(long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"getSegmentUrl(long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.MultiSegmentBase","l":"getSegmentUrl(Representation, long)","url":"getSegmentUrl(com.google.android.exoplayer2.source.dash.manifest.Representation,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SegmentList","l":"getSegmentUrl(Representation, long)","url":"getSegmentUrl(com.google.android.exoplayer2.source.dash.manifest.Representation,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SegmentTemplate","l":"getSegmentUrl(Representation, long)","url":"getSegmentUrl(com.google.android.exoplayer2.source.dash.manifest.Representation,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"getSelectedFormat()"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"getSelectedFormat()"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"getSelectedFormat()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"getSelectedIndex()"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"getSelectedIndex()"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"getSelectedIndex()"},{"p":"com.google.android.exoplayer2.trackselection","c":"FixedTrackSelection","l":"getSelectedIndex()"},{"p":"com.google.android.exoplayer2.trackselection","c":"RandomTrackSelection","l":"getSelectedIndex()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"getSelectedIndexInTrackGroup()"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"getSelectedIndexInTrackGroup()"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"getSelectedIndexInTrackGroup()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"getSelectionData()"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"getSelectionData()"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"getSelectionData()"},{"p":"com.google.android.exoplayer2.trackselection","c":"FixedTrackSelection","l":"getSelectionData()"},{"p":"com.google.android.exoplayer2.trackselection","c":"RandomTrackSelection","l":"getSelectionData()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"getSelectionOverride(int, TrackGroupArray)","url":"getSelectionOverride(int,com.google.android.exoplayer2.source.TrackGroupArray)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"getSelectionReason()"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"getSelectionReason()"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"getSelectionReason()"},{"p":"com.google.android.exoplayer2.trackselection","c":"FixedTrackSelection","l":"getSelectionReason()"},{"p":"com.google.android.exoplayer2.trackselection","c":"RandomTrackSelection","l":"getSelectionReason()"},{"p":"com.google.android.exoplayer2.testutil","c":"HttpDataSourceTestEnv","l":"getServedResources()"},{"p":"com.google.android.exoplayer2.analytics","c":"DefaultPlaybackSessionManager","l":"getSessionForMediaPeriodId(Timeline, MediaSource.MediaPeriodId)","url":"getSessionForMediaPeriodId(com.google.android.exoplayer2.Timeline,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackSessionManager","l":"getSessionForMediaPeriodId(Timeline, MediaSource.MediaPeriodId)","url":"getSessionForMediaPeriodId(com.google.android.exoplayer2.Timeline,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"getShowShuffleButton()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"getShowShuffleButton()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"getShowSubtitleButton()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"getShowTimeoutMs()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"getShowTimeoutMs()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"getShowVrButton()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"getShowVrButton()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"getShuffleMode()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getShuffleModeEnabled()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getShuffleModeEnabled()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getShuffleModeEnabled()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getShuffleModeEnabled()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getShuffleModeEnabled()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"getSingletonInstance(Context)","url":"getSingletonInstance(android.content.Context)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"getSinkFormatSupport(Format)","url":"getSinkFormatSupport(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"getSize()"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getSize()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"getSkipCount(long, boolean)","url":"getSkipCount(long,boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"getSkippedFrames()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink.AudioProcessorChain","l":"getSkippedOutputFrameCount()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink.DefaultAudioProcessorChain","l":"getSkippedOutputFrameCount()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioComponent","l":"getSkipSilenceEnabled()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getSkipSilenceEnabled()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"getSkipSilenceEnabled()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"getSkipSilenceEnabled()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"getSkipSilenceEnabled()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.RequestProperties","l":"getSnapshot()"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"getSourceException()"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"getSpecificityScore(String, String, Set, String)","url":"getSpecificityScore(java.lang.String,java.lang.String,java.util.Set,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"StarRating","l":"getStarRating()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveDataSet","l":"getStartTime(int)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"getStartTimeUs(int)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"getState()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"getState()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"getState()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"getState()"},{"p":"com.google.android.exoplayer2.drm","c":"ErrorStateDrmSession","l":"getState()"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyStatus","l":"getStatusCode()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"getStream()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"getStream()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"getStream()"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsUtil","l":"getStreamDurationUs(Player, AdPlaybackState)","url":"getStreamDurationUs(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.source.ads.AdPlaybackState)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"getStreamFormats()"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"getStreamKeys(List)","url":"getStreamKeys(java.util.List)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"getStreamKeys(List)","url":"getStreamKeys(java.util.List)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacDecoder","l":"getStreamMetadata()"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsUtil","l":"getStreamPositionUs(long, MediaPeriodId, AdPlaybackState)","url":"getStreamPositionUs(long,com.google.android.exoplayer2.source.MediaPeriodId,com.google.android.exoplayer2.source.ads.AdPlaybackState)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsUtil","l":"getStreamPositionUs(Player, AdPlaybackState)","url":"getStreamPositionUs(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.source.ads.AdPlaybackState)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsUtil","l":"getStreamPositionUsForAd(long, int, int, AdPlaybackState)","url":"getStreamPositionUsForAd(long,int,int,com.google.android.exoplayer2.source.ads.AdPlaybackState)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsUtil","l":"getStreamPositionUsForContent(long, int, AdPlaybackState)","url":"getStreamPositionUsForContent(long,int,com.google.android.exoplayer2.source.ads.AdPlaybackState)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getStreamTypeForAudioUsage(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"getString(Context, String)","url":"getString(android.content.Context,java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"getStringForHttpMethod(int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getStringForTime(StringBuilder, Formatter, long)","url":"getStringForTime(java.lang.StringBuilder,java.util.Formatter,long)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"getStyle()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"getSubFrame(int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterTocFrame","l":"getSubFrame(int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"getSubFrameCount()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterTocFrame","l":"getSubFrameCount()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getSubtitleView()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getSubtitleView()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.PlaybackPreparer","l":"getSupportedPrepareActions()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.QueueNavigator","l":"getSupportedQueueNavigatorActions(Player)","url":"getSupportedQueueNavigatorActions(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueNavigator","l":"getSupportedQueueNavigatorActions(Player)","url":"getSupportedQueueNavigatorActions(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ext.workmanager","c":"WorkManagerScheduler","l":"getSupportedRequirements(Requirements)","url":"getSupportedRequirements(com.google.android.exoplayer2.scheduler.Requirements)"},{"p":"com.google.android.exoplayer2.scheduler","c":"PlatformScheduler","l":"getSupportedRequirements(Requirements)","url":"getSupportedRequirements(com.google.android.exoplayer2.scheduler.Requirements)"},{"p":"com.google.android.exoplayer2.scheduler","c":"Scheduler","l":"getSupportedRequirements(Requirements)","url":"getSupportedRequirements(com.google.android.exoplayer2.scheduler.Requirements)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"getSupportedTypes()"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceFactory","l":"getSupportedTypes()"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"getSupportedTypes()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"getSupportedTypes()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"getSupportedTypes()"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.Factory","l":"getSupportedTypes()"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"getSupportedTypes()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"getSurface()"},{"p":"com.google.android.exoplayer2.util","c":"EGLSurfaceTexture","l":"getSurfaceTexture()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getSystemLanguageCodes()"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"getTarget()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock.HandlerMessage","l":"getTarget()"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper.Message","l":"getTarget()"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl","l":"getTargetLiveOffsetUs()"},{"p":"com.google.android.exoplayer2","c":"LivePlaybackSpeedControl","l":"getTargetLiveOffsetUs()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"getTestResources()"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getText()"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getTextAlignment()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getTextComponent()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getTextComponent()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getTextComponent()"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"getTextMediaMimeType(String)","url":"getTextMediaMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getTextSize()"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getTextSizeType()"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"getThrowableString(Throwable)","url":"getThrowableString(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"getTimeline()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource","l":"getTimeline()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"getTimeline()"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getTimelineByChildIndex(int)"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"getTimestampOffsetUs()"},{"p":"com.google.android.exoplayer2.upstream","c":"BandwidthMeter","l":"getTimeToFirstByteEstimateUs()"},{"p":"com.google.android.exoplayer2.upstream","c":"TimeToFirstByteEstimator","l":"getTimeToFirstByteEstimateUs()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashSegmentIndex","l":"getTimeUs(long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashWrappingSegmentIndex","l":"getTimeUs(long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"getTimeUs(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"ConstantBitrateSeekMap","l":"getTimeUsAtPosition(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"DecoderCountersUtil","l":"getTotalBufferCount(DecoderCounters)","url":"getTotalBufferCount(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getTotalBufferedDuration()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getTotalBufferedDuration()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getTotalBufferedDuration()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getTotalBufferedDuration()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getTotalBufferedDuration()"},{"p":"com.google.android.exoplayer2.upstream","c":"Allocator","l":"getTotalBytesAllocated()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultAllocator","l":"getTotalBytesAllocated()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getTotalElapsedTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getTotalJoinTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getTotalPausedTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getTotalPlayAndWaitTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getTotalPlayTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getTotalRebufferTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getTotalSeekTimeMs()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getTotalWaitTimeMs()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"getTrackGroup()"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"getTrackGroup()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelection","l":"getTrackGroup()"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"getTrackGroups()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"getTrackGroups()"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"getTrackGroups()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"getTrackGroups()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"getTrackGroups()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"getTrackGroups()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"getTrackGroups(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"getTrackGroups(int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.TrackIdGenerator","l":"getTrackId()"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTrackNameProvider","l":"getTrackName(Format)","url":"getTrackName(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackNameProvider","l":"getTrackName(Format)","url":"getTrackName(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ContainerMediaChunk","l":"getTrackOutputProvider(BaseMediaChunkOutput)","url":"getTrackOutputProvider(com.google.android.exoplayer2.source.chunk.BaseMediaChunkOutput)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"getTrackSelections(int, int)","url":"getTrackSelections(int,int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getTrackSelector()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getTrackSelector()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getTrackSelector()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"getTrackSelector()"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"getTrackSupport(int, int, int)","url":"getTrackSupport(int,int,int)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"getTrackType()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"getTrackType()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"getTrackType()"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"getTrackType()"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"getTrackType(String)","url":"getTrackType(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"getTrackTypeOfCodec(String)","url":"getTrackTypeOfCodec(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getTrackTypeString(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"BandwidthMeter","l":"getTransferListener()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"getTransferListener()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"getTransferListenerDataSource()"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"getTunnelingSupport(int)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"getType()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"getType()"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"getType()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelection","l":"getType()"},{"p":"com.google.android.exoplayer2.audio","c":"WavUtil","l":"getTypeForPcmEncoding(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"getTypeSupport(int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"getUid()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"getUid()"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getUidOfPeriod(int)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getUidOfPeriod(int)"},{"p":"com.google.android.exoplayer2","c":"Timeline.RemotableTimeline","l":"getUidOfPeriod(int)"},{"p":"com.google.android.exoplayer2.source","c":"ForwardingTimeline","l":"getUidOfPeriod(int)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource.PlaceholderTimeline","l":"getUidOfPeriod(int)"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"getUidOfPeriod(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"getUidOfPeriod(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"getUnexpectedException()"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil","l":"getUniforms(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"getUnmappedTrackGroups()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"getUpstreamFormat()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"getUpstreamPriorityTaskManager()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"getUri_resourceNotFound_returnsNullIfNotOpened()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"getUri_returnsNonNullValueOnlyWhileOpen()"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.ext.rtmp","c":"RtmpDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"getUri()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.TestResource","l":"getUri()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"AssetDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"ByteArrayDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"ContentDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSchemeDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"DummyDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"PriorityDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"RawResourceDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"ResolvingDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"StatsDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"TeeDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream","c":"UdpDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesCipherDataSource","l":"getUri()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveDataSet","l":"getUri(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getUseArtwork()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getUseArtwork()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getUseController()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getUseController()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"getUseLazyPreparation()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getUserAgent(Context, String)","url":"getUserAgent(android.content.Context,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"getUtf8Bytes(String)","url":"getUtf8Bytes(java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegLibrary","l":"getVersion()"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusLibrary","l":"getVersion()"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxLibrary","l":"getVersion()"},{"p":"com.google.android.exoplayer2.database","c":"VersionTable","l":"getVersion(SQLiteDatabase, int, String)","url":"getVersion(android.database.sqlite.SQLiteDatabase,int,java.lang.String)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getVerticalType()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"getVideoComponent()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getVideoComponent()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getVideoComponent()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getVideoDecoderCounters()"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderGLSurfaceView","l":"getVideoDecoderOutputBufferRenderer()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getVideoFormat()"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView","l":"getVideoFrameMetadataListener()"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"getVideoMediaMimeType(String)","url":"getVideoMediaMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"getVideoScalingMode()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getVideoScalingMode()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"getVideoSize()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getVideoSize()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getVideoSize()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getVideoSize()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getVideoSize()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getVideoSize()"},{"p":"com.google.android.exoplayer2.util","c":"DebugTextViewHelper","l":"getVideoString()"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView","l":"getVideoSurface()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"getVideoSurfaceView()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"getVideoSurfaceView()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioComponent","l":"getVolume()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"getVolume()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"getVolume()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"getVolume()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"getVolume()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"getVolume()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"getWaitTimeRatio()"},{"p":"com.google.android.exoplayer2","c":"AbstractConcatenatedTimeline","l":"getWindow(int, Timeline.Window, long)","url":"getWindow(int,com.google.android.exoplayer2.Timeline.Window,long)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getWindow(int, Timeline.Window, long)","url":"getWindow(int,com.google.android.exoplayer2.Timeline.Window,long)"},{"p":"com.google.android.exoplayer2","c":"Timeline.RemotableTimeline","l":"getWindow(int, Timeline.Window, long)","url":"getWindow(int,com.google.android.exoplayer2.Timeline.Window,long)"},{"p":"com.google.android.exoplayer2.source","c":"ForwardingTimeline","l":"getWindow(int, Timeline.Window, long)","url":"getWindow(int,com.google.android.exoplayer2.Timeline.Window,long)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource.PlaceholderTimeline","l":"getWindow(int, Timeline.Window, long)","url":"getWindow(int,com.google.android.exoplayer2.Timeline.Window,long)"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"getWindow(int, Timeline.Window, long)","url":"getWindow(int,com.google.android.exoplayer2.Timeline.Window,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource.InitialTimeline","l":"getWindow(int, Timeline.Window, long)","url":"getWindow(int,com.google.android.exoplayer2.Timeline.Window,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"getWindow(int, Timeline.Window, long)","url":"getWindow(int,com.google.android.exoplayer2.Timeline.Window,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"NoUidTimeline","l":"getWindow(int, Timeline.Window, long)","url":"getWindow(int,com.google.android.exoplayer2.Timeline.Window,long)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getWindow(int, Timeline.Window)","url":"getWindow(int,com.google.android.exoplayer2.Timeline.Window)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"getWindowColor()"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"getWindowCount()"},{"p":"com.google.android.exoplayer2","c":"Timeline.RemotableTimeline","l":"getWindowCount()"},{"p":"com.google.android.exoplayer2.source","c":"ForwardingTimeline","l":"getWindowCount()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource.PlaceholderTimeline","l":"getWindowCount()"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"getWindowCount()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline","l":"getWindowCount()"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"getWindowIndex()"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"getWindowIndexForChildWindowIndex(ConcatenatingMediaSource.MediaSourceHolder, int)","url":"getWindowIndexForChildWindowIndex(com.google.android.exoplayer2.source.ConcatenatingMediaSource.MediaSourceHolder,int)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"getWindowIndexForChildWindowIndex(T, int)","url":"getWindowIndexForChildWindowIndex(T,int)"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata.Entry","l":"getWrappedMetadataBytes()"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"getWrappedMetadataBytes()"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata.Entry","l":"getWrappedMetadataFormat()"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"getWrappedMetadataFormat()"},{"p":"com.google.android.exoplayer2.database","c":"DatabaseProvider","l":"getWritableDatabase()"},{"p":"com.google.android.exoplayer2.database","c":"DefaultDatabaseProvider","l":"getWritableDatabase()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"getWriteIndex()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunkOutput","l":"getWriteIndices()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayerLibraryInfo","l":"GL_ASSERTIONS_ENABLED"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"group"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection.Definition","l":"group"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"GROUP_INDEX_AUDIO"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"GROUP_INDEX_SUBTITLE"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"GROUP_INDEX_VARIANT"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry","l":"groupId"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Rendition","l":"groupId"},{"p":"com.google.android.exoplayer2.offline","c":"StreamKey","l":"groupIndex"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.SelectionOverride","l":"groupIndex"},{"p":"com.google.android.exoplayer2.ext.gvr","c":"GvrAudioProcessor","l":"GvrAudioProcessor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource","l":"GZIP_SUPPORT_DISABLED"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource","l":"GZIP_SUPPORT_ENABLED"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource","l":"GZIP_SUPPORT_FORCED"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"gzip(byte[])"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H262Reader","l":"H262Reader()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H263Reader","l":"H263Reader()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H264Reader","l":"H264Reader(SeiReader, boolean, boolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.ts.SeiReader,boolean,boolean)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H265Reader","l":"H265Reader(SeiReader)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.ts.SeiReader)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"handleBlockAddIDExtraData(MatroskaExtractor.Track, ExtractorInput, int)","url":"handleBlockAddIDExtraData(com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor.Track,com.google.android.exoplayer2.extractor.ExtractorInput,int)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"handleBlockAdditionalData(MatroskaExtractor.Track, int, ExtractorInput, int)","url":"handleBlockAdditionalData(com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor.Track,int,com.google.android.exoplayer2.extractor.ExtractorInput,int)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"handleBuffer(ByteBuffer, long, int)","url":"handleBuffer(java.nio.ByteBuffer,long,int)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"handleBuffer(ByteBuffer, long, int)","url":"handleBuffer(java.nio.ByteBuffer,long,int)"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"handleBuffer(ByteBuffer, long, int)","url":"handleBuffer(java.nio.ByteBuffer,long,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"CapturingAudioSink","l":"handleBuffer(ByteBuffer, long, int)","url":"handleBuffer(java.nio.ByteBuffer,long,int)"},{"p":"com.google.android.exoplayer2.audio","c":"TeeAudioProcessor.AudioBufferSink","l":"handleBuffer(ByteBuffer)","url":"handleBuffer(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.audio","c":"TeeAudioProcessor.WavFileAudioBufferSink","l":"handleBuffer(ByteBuffer)","url":"handleBuffer(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"handleDiscontinuity()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"handleDiscontinuity()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"handleDiscontinuity()"},{"p":"com.google.android.exoplayer2.testutil","c":"CapturingAudioSink","l":"handleDiscontinuity()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"handleInputBufferSupplementalData(DecoderInputBuffer)","url":"handleInputBufferSupplementalData(com.google.android.exoplayer2.decoder.DecoderInputBuffer)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"handleInputBufferSupplementalData(DecoderInputBuffer)","url":"handleInputBufferSupplementalData(com.google.android.exoplayer2.decoder.DecoderInputBuffer)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"handleMessage(int, Object)","url":"handleMessage(int,java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"handleMessage(int, Object)","url":"handleMessage(int,java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage.Target","l":"handleMessage(int, Object)","url":"handleMessage(int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"handleMessage(int, Object)","url":"handleMessage(int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"handleMessage(int, Object)","url":"handleMessage(int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.PlayerTarget","l":"handleMessage(int, Object)","url":"handleMessage(int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeVideoRenderer","l":"handleMessage(int, Object)","url":"handleMessage(int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"handleMessage(int, Object)","url":"handleMessage(int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"handleMessage(int, Object)","url":"handleMessage(int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.video.spherical","c":"CameraMotionRenderer","l":"handleMessage(int, Object)","url":"handleMessage(int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataRenderer","l":"handleMessage(Message)","url":"handleMessage(android.os.Message)"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler","l":"handleMessage(Message)","url":"handleMessage(android.os.Message)"},{"p":"com.google.android.exoplayer2.text","c":"TextRenderer","l":"handleMessage(Message)","url":"handleMessage(android.os.Message)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.PlayerTarget","l":"handleMessage(SimpleExoPlayer, int, Object)","url":"handleMessage(com.google.android.exoplayer2.SimpleExoPlayer,int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"handlePendingSeek(ExtractorInput, PositionHolder)","url":"handlePendingSeek(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"handlePrepareComplete(AdsMediaSource, int, int)","url":"handlePrepareComplete(com.google.android.exoplayer2.source.ads.AdsMediaSource,int,int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsLoader","l":"handlePrepareComplete(AdsMediaSource, int, int)","url":"handlePrepareComplete(com.google.android.exoplayer2.source.ads.AdsMediaSource,int,int)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"handlePrepareError(AdsMediaSource, int, int, IOException)","url":"handlePrepareError(com.google.android.exoplayer2.source.ads.AdsMediaSource,int,int,java.io.IOException)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsLoader","l":"handlePrepareError(AdsMediaSource, int, int, IOException)","url":"handlePrepareError(com.google.android.exoplayer2.source.ads.AdsMediaSource,int,int,java.io.IOException)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock.HandlerMessage","l":"HandlerMessage(long, FakeClock.ClockHandler, int, int, int, Object, Runnable)","url":"%3Cinit%3E(long,com.google.android.exoplayer2.testutil.FakeClock.ClockHandler,int,int,int,java.lang.Object,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"hardwareAccelerated"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasAbsoluteSizeSpanBetween(int, int)","url":"hasAbsoluteSizeSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasAlignmentSpanBetween(int, int)","url":"hasAlignmentSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"hasBackgroundColor()"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasBackgroundColorSpanBetween(int, int)","url":"hasBackgroundColorSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasBoldItalicSpanBetween(int, int)","url":"hasBoldItalicSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasBoldSpanBetween(int, int)","url":"hasBoldSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.CaptionCallback","l":"hasCaptions(Player)","url":"hasCaptions(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"hasData()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"hasDiscontinuitySequence"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"hasEndTag"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"hasFatalError()"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"hasFontColor()"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasForegroundColorSpanBetween(int, int)","url":"hasForegroundColorSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"GaplessInfoHolder","l":"hasGaplessInfo()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.SegmentBase","l":"hasGapTag"},{"p":"com.google.android.exoplayer2","c":"Format","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"HeartRating","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.AdsConfiguration","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.ClippingProperties","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.DrmConfiguration","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.LiveConfiguration","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.PlaybackProperties","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Subtitle","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"PercentageRating","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"PlaybackParameters","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"Player.Commands","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"Player.Events","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"RendererConfiguration","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"SeekParameters","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"StarRating","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"ThumbRating","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"hashCode()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"hashCode()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"hashCode()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndException","l":"hashCode()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndFormat","l":"hashCode()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndPlaybackState","l":"hashCode()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes","l":"hashCode()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioCapabilities","l":"hashCode()"},{"p":"com.google.android.exoplayer2.audio","c":"AuxEffectInfo","l":"hashCode()"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"hashCode()"},{"p":"com.google.android.exoplayer2.device","c":"DeviceInfo","l":"hashCode()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"hashCode()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"hashCode()"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap.SeekPoints","l":"hashCode()"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekPoint","l":"hashCode()"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput.CryptoData","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"VorbisComment","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyInfo","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ApicFrame","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"BinaryFrame","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterTocFrame","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"CommentFrame","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"GeobFrame","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"InternalFrame","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"MlltFrame","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"PrivFrame","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"TextInformationFrame","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"UrlLinkFrame","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MdtaMetadataEntry","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MotionPhotoMetadata","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData.Segment","l":"hashCode()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SmtaMetadataEntry","l":"hashCode()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"hashCode()"},{"p":"com.google.android.exoplayer2.offline","c":"StreamKey","l":"hashCode()"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroup","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroupArray","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"BaseUrl","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Descriptor","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ProgramInformation","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"RangedUri","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SegmentTimelineElement","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry.VariantInfo","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"hashCode()"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPayloadFormat","l":"hashCode()"},{"p":"com.google.android.exoplayer2.testutil","c":"DumpableFormat","l":"hashCode()"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"hashCode()"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection.AdaptationCheckpoint","l":"hashCode()"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"hashCode()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"hashCode()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.SelectionOverride","l":"hashCode()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionArray","l":"hashCode()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"hashCode()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"DefaultContentMetadata","l":"hashCode()"},{"p":"com.google.android.exoplayer2.util","c":"FlagSet","l":"hashCode()"},{"p":"com.google.android.exoplayer2.video","c":"ColorInfo","l":"hashCode()"},{"p":"com.google.android.exoplayer2.video","c":"VideoSize","l":"hashCode()"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasHorizontalTextInVerticalContextSpanBetween(int, int)","url":"hasHorizontalTextInVerticalContextSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylist","l":"hasIndependentSegments"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasItalicSpanBetween(int, int)","url":"hasItalicSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"hasMessages(int)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"hasNext()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"hasNext()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"hasNext()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"hasNextWindow()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"hasNextWindow()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"hasNextWindow()"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoAbsoluteSizeSpanBetween(int, int)","url":"hasNoAbsoluteSizeSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoAlignmentSpanBetween(int, int)","url":"hasNoAlignmentSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoBackgroundColorSpanBetween(int, int)","url":"hasNoBackgroundColorSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoForegroundColorSpanBetween(int, int)","url":"hasNoForegroundColorSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoHorizontalTextInVerticalContextSpanBetween(int, int)","url":"hasNoHorizontalTextInVerticalContextSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoRelativeSizeSpanBetween(int, int)","url":"hasNoRelativeSizeSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoRubySpanBetween(int, int)","url":"hasNoRubySpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoSpans()"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoStrikethroughSpanBetween(int, int)","url":"hasNoStrikethroughSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoStyleSpanBetween(int, int)","url":"hasNoStyleSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoTextEmphasisSpanBetween(int, int)","url":"hasNoTextEmphasisSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoTypefaceSpanBetween(int, int)","url":"hasNoTypefaceSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasNoUnderlineSpanBetween(int, int)","url":"hasNoUnderlineSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"hasPendingData()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"hasPendingData()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"hasPendingData()"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"hasPendingOutput()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"hasPlayedAdGroup(int)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"hasPositiveStartOffset"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"hasPrevious()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"hasPrevious()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"hasPrevious()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"hasPreviousWindow()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"hasPreviousWindow()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"hasPreviousWindow()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"hasProgramDateTime"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"hasReadStreamToEnd()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"hasReadStreamToEnd()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"hasReadStreamToEnd()"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasRelativeSizeSpanBetween(int, int)","url":"hasRelativeSizeSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasRubySpanBetween(int, int)","url":"hasRubySpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"hasSelectionOverride(int, TrackGroupArray)","url":"hasSelectionOverride(int,com.google.android.exoplayer2.source.TrackGroupArray)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasStrikethroughSpanBetween(int, int)","url":"hasStrikethroughSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.decoder","c":"Buffer","l":"hasSupplementalData()"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasTextEmphasisSpanBetween(int, int)","url":"hasTextEmphasisSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionUtil","l":"hasTrackOfType(TrackSelectionArray, int)","url":"hasTrackOfType(com.google.android.exoplayer2.trackselection.TrackSelectionArray,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasTypefaceSpanBetween(int, int)","url":"hasTypefaceSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"hasUnderlineSpanBetween(int, int)","url":"hasUnderlineSpanBetween(int,int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"hasUnplayedAds()"},{"p":"com.google.android.exoplayer2.video","c":"ColorInfo","l":"hdrStaticInfo"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util","l":"HEADER_SIZE_FOR_PARSER"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil.Header","l":"Header()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.InvalidResponseCodeException","l":"headerFields"},{"p":"com.google.android.exoplayer2","c":"HeartRating","l":"HeartRating()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"HeartRating","l":"HeartRating(boolean)","url":"%3Cinit%3E(boolean)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"height"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"height"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"height"},{"p":"com.google.android.exoplayer2.video","c":"AvcConfig","l":"height"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer.CodecMaxValues","l":"height"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"height"},{"p":"com.google.android.exoplayer2.video","c":"VideoSize","l":"height"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"hide()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"hide()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"hideController()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"hideController()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"hideImmediately()"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"hideScrubber(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"hideScrubber(long)"},{"p":"com.google.android.exoplayer2.source.hls.offline","c":"HlsDownloader","l":"HlsDownloader(MediaItem, CacheDataSource.Factory, Executor)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.source.hls.offline","c":"HlsDownloader","l":"HlsDownloader(MediaItem, CacheDataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.hls.offline","c":"HlsDownloader","l":"HlsDownloader(MediaItem, ParsingLoadable.Parser, CacheDataSource.Factory, Executor)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.upstream.ParsingLoadable.Parser,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"HlsMasterPlaylist(String, List, List, List, List, List, List, Format, List, boolean, Map, List)","url":"%3Cinit%3E(java.lang.String,java.util.List,java.util.List,java.util.List,java.util.List,java.util.List,java.util.List,com.google.android.exoplayer2.Format,java.util.List,boolean,java.util.Map,java.util.List)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"HlsMediaPeriod(HlsExtractorFactory, HlsPlaylistTracker, HlsDataSourceFactory, TransferListener, DrmSessionManager, DrmSessionEventListener.EventDispatcher, LoadErrorHandlingPolicy, MediaSourceEventListener.EventDispatcher, Allocator, CompositeSequenceableLoaderFactory, boolean, int, boolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.hls.HlsExtractorFactory,com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker,com.google.android.exoplayer2.source.hls.HlsDataSourceFactory,com.google.android.exoplayer2.upstream.TransferListener,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher,com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy,com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher,com.google.android.exoplayer2.upstream.Allocator,com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory,boolean,int,boolean)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"HlsMediaPlaylist(int, String, List, long, boolean, long, boolean, int, long, int, long, long, boolean, boolean, boolean, DrmInitData, List, List, HlsMediaPlaylist.ServerControl, Map)","url":"%3Cinit%3E(int,java.lang.String,java.util.List,long,boolean,long,boolean,int,long,int,long,long,boolean,boolean,boolean,com.google.android.exoplayer2.drm.DrmInitData,java.util.List,java.util.List,com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.ServerControl,java.util.Map)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylist","l":"HlsPlaylist(String, List, boolean)","url":"%3Cinit%3E(java.lang.String,java.util.List,boolean)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistParser","l":"HlsPlaylistParser()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistParser","l":"HlsPlaylistParser(HlsMasterPlaylist, HlsMediaPlaylist)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist,com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry","l":"HlsTrackMetadataEntry(String, String, List)","url":"%3Cinit%3E(java.lang.String,java.lang.String,java.util.List)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.ServerControl","l":"holdBackUs"},{"p":"com.google.android.exoplayer2.text.span","c":"HorizontalTextInVerticalContextSpan","l":"HorizontalTextInVerticalContextSpan()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity","l":"HostActivity()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"HTTP_METHOD_GET"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"HTTP_METHOD_HEAD"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"HTTP_METHOD_POST"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"httpBody"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.HttpDataSourceException","l":"HttpDataSourceException(DataSpec, int, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSpec,int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.HttpDataSourceException","l":"HttpDataSourceException(DataSpec, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSpec,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.HttpDataSourceException","l":"HttpDataSourceException(IOException, DataSpec, int, int)","url":"%3Cinit%3E(java.io.IOException,com.google.android.exoplayer2.upstream.DataSpec,int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.HttpDataSourceException","l":"HttpDataSourceException(IOException, DataSpec, int)","url":"%3Cinit%3E(java.io.IOException,com.google.android.exoplayer2.upstream.DataSpec,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.HttpDataSourceException","l":"HttpDataSourceException(String, DataSpec, int, int)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.upstream.DataSpec,int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.HttpDataSourceException","l":"HttpDataSourceException(String, DataSpec, int)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.upstream.DataSpec,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.HttpDataSourceException","l":"HttpDataSourceException(String, IOException, DataSpec, int, int)","url":"%3Cinit%3E(java.lang.String,java.io.IOException,com.google.android.exoplayer2.upstream.DataSpec,int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.HttpDataSourceException","l":"HttpDataSourceException(String, IOException, DataSpec, int)","url":"%3Cinit%3E(java.lang.String,java.io.IOException,com.google.android.exoplayer2.upstream.DataSpec,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"HttpDataSourceTestEnv","l":"HttpDataSourceTestEnv()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.drm","c":"HttpMediaDrmCallback","l":"HttpMediaDrmCallback(String, boolean, HttpDataSource.Factory)","url":"%3Cinit%3E(java.lang.String,boolean,com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.drm","c":"HttpMediaDrmCallback","l":"HttpMediaDrmCallback(String, HttpDataSource.Factory)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"httpMethod"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"httpRequestHeaders"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"i(String, String, Throwable)","url":"i(java.lang.String,java.lang.String,java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"i(String, String)","url":"i(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyDecoder","l":"IcyDecoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"IcyHeaders(int, String, String, String, boolean, int)","url":"%3Cinit%3E(int,java.lang.String,java.lang.String,java.lang.String,boolean,int)"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyInfo","l":"IcyInfo(byte[], String, String)","url":"%3Cinit%3E(byte[],java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"id"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"id"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"id"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"id"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"Id3Frame","l":"id"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"id"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"id"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"AdaptationSet","l":"id"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Descriptor","l":"id"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Period","l":"id"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"id"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ApicFrame","l":"ID"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"ID"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterTocFrame","l":"ID"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"CommentFrame","l":"ID"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"GeobFrame","l":"ID"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"InternalFrame","l":"ID"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"MlltFrame","l":"ID"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"PrivFrame","l":"ID"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"AdaptationSet","l":"ID_UNSET"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"EventStream","l":"id()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"Id3Decoder","l":"ID3_HEADER_LENGTH"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"ID3_SCHEME_ID_AOM"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"Id3Decoder","l":"ID3_TAG"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"Id3Decoder","l":"Id3Decoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"Id3Decoder","l":"Id3Decoder(Id3Decoder.FramePredicate)","url":"%3Cinit%3E(com.google.android.exoplayer2.metadata.id3.Id3Decoder.FramePredicate)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"Id3Frame","l":"Id3Frame(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.extractor","c":"Id3Peeker","l":"Id3Peeker()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Id3Reader","l":"Id3Reader()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"PrivateCommand","l":"identifier"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource.IllegalClippingException","l":"IllegalClippingException(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource.IllegalMergeException","l":"IllegalMergeException(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2","c":"IllegalSeekPositionException","l":"IllegalSeekPositionException(Timeline, int, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.Timeline,int,long)"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil","l":"iLog(int)"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"IMAGE_JPEG"},{"p":"com.google.android.exoplayer2.util","c":"NotificationUtil","l":"IMPORTANCE_DEFAULT"},{"p":"com.google.android.exoplayer2.util","c":"NotificationUtil","l":"IMPORTANCE_HIGH"},{"p":"com.google.android.exoplayer2.util","c":"NotificationUtil","l":"IMPORTANCE_LOW"},{"p":"com.google.android.exoplayer2.util","c":"NotificationUtil","l":"IMPORTANCE_MIN"},{"p":"com.google.android.exoplayer2.util","c":"NotificationUtil","l":"IMPORTANCE_NONE"},{"p":"com.google.android.exoplayer2.util","c":"NotificationUtil","l":"IMPORTANCE_UNSPECIFIED"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser.RepresentationInfo","l":"inbandEventStreams"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"inbandEventStreams"},{"p":"com.google.android.exoplayer2.decoder","c":"CryptoInfo","l":"increaseClearDataFirstSubSampleBy(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.DeviceComponent","l":"increaseDeviceVolume()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"increaseDeviceVolume()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"increaseDeviceVolume()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"increaseDeviceVolume()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"increaseDeviceVolume()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"increaseDeviceVolume()"},{"p":"com.google.android.exoplayer2.testutil","c":"DumpableFormat","l":"index"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashSegmentIndex","l":"INDEX_UNBOUNDED"},{"p":"com.google.android.exoplayer2","c":"C","l":"INDEX_UNSET"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroup","l":"indexOf(Format)","url":"indexOf(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"indexOf(Format)","url":"indexOf(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"indexOf(Format)","url":"indexOf(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelection","l":"indexOf(Format)","url":"indexOf(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"indexOf(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"indexOf(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelection","l":"indexOf(int)"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroupArray","l":"indexOf(TrackGroup)","url":"indexOf(com.google.android.exoplayer2.source.TrackGroup)"},{"p":"com.google.android.exoplayer2.extractor","c":"IndexSeekMap","l":"IndexSeekMap(long[], long[], long)","url":"%3Cinit%3E(long[],long[],long)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"inferContentType(String)","url":"inferContentType(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"inferContentType(Uri, String)","url":"inferContentType(android.net.Uri,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"inferContentType(Uri)","url":"inferContentType(android.net.Uri)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"inferContentTypeForUriAndMimeType(Uri, String)","url":"inferContentTypeForUriAndMimeType(android.net.Uri,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"inferFileTypeFromMimeType(String)","url":"inferFileTypeFromMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"inferFileTypeFromResponseHeaders(Map>)","url":"inferFileTypeFromResponseHeaders(java.util.Map)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"inferFileTypeFromUri(Uri)","url":"inferFileTypeFromUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"inflate(ParsableByteArray, ParsableByteArray, Inflater)","url":"inflate(com.google.android.exoplayer2.util.ParsableByteArray,com.google.android.exoplayer2.util.ParsableByteArray,java.util.zip.Inflater)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectorResult","l":"info"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunk","l":"init(BaseMediaChunkOutput)","url":"init(com.google.android.exoplayer2.source.chunk.BaseMediaChunkOutput)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BundledChunkExtractor","l":"init(ChunkExtractor.TrackOutputProvider, long, long)","url":"init(com.google.android.exoplayer2.source.chunk.ChunkExtractor.TrackOutputProvider,long,long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkExtractor","l":"init(ChunkExtractor.TrackOutputProvider, long, long)","url":"init(com.google.android.exoplayer2.source.chunk.ChunkExtractor.TrackOutputProvider,long,long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaParserChunkExtractor","l":"init(ChunkExtractor.TrackOutputProvider, long, long)","url":"init(com.google.android.exoplayer2.source.chunk.ChunkExtractor.TrackOutputProvider,long,long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"InitializationChunk","l":"init(ChunkExtractor.TrackOutputProvider)","url":"init(com.google.android.exoplayer2.source.chunk.ChunkExtractor.TrackOutputProvider)"},{"p":"com.google.android.exoplayer2.source","c":"BundledExtractorsAdapter","l":"init(DataReader, Uri, Map>, long, long, ExtractorOutput)","url":"init(com.google.android.exoplayer2.upstream.DataReader,android.net.Uri,java.util.Map,long,long,com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.source","c":"MediaParserExtractorAdapter","l":"init(DataReader, Uri, Map>, long, long, ExtractorOutput)","url":"init(com.google.android.exoplayer2.upstream.DataReader,android.net.Uri,java.util.Map,long,long,com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaExtractor","l":"init(DataReader, Uri, Map>, long, long, ExtractorOutput)","url":"init(com.google.android.exoplayer2.upstream.DataReader,android.net.Uri,java.util.Map,long,long,com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor","c":"Extractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.amr","c":"AmrExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.flac","c":"FlacExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.flv","c":"FlvExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.jpeg","c":"JpegExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.ogg","c":"OggExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.rawcc","c":"RawCcExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Extractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Extractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.extractor.wav","c":"WavExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.source.hls","c":"BundledHlsMediaChunkExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaChunkExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.source.hls","c":"MediaParserHlsMediaChunkExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.source.hls","c":"WebvttExtractor","l":"init(ExtractorOutput)","url":"init(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.util","c":"EGLSurfaceTexture","l":"init(int)"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"init(long, int, ByteBuffer)","url":"init(long,int,java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleOutputBuffer","l":"init(long, int)","url":"init(long,int)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionView","l":"init(MappingTrackSelector.MappedTrackInfo, int, boolean, List, Comparator, TrackSelectionView.TrackSelectionListener)","url":"init(com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo,int,boolean,java.util.List,java.util.Comparator,com.google.android.exoplayer2.ui.TrackSelectionView.TrackSelectionListener)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PassthroughSectionPayloadReader","l":"init(TimestampAdjuster, ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"init(com.google.android.exoplayer2.util.TimestampAdjuster,com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PesReader","l":"init(TimestampAdjuster, ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"init(com.google.android.exoplayer2.util.TimestampAdjuster,com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"SectionPayloadReader","l":"init(TimestampAdjuster, ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"init(com.google.android.exoplayer2.util.TimestampAdjuster,com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"SectionReader","l":"init(TimestampAdjuster, ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"init(com.google.android.exoplayer2.util.TimestampAdjuster,com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader","l":"init(TimestampAdjuster, ExtractorOutput, TsPayloadReader.TrackIdGenerator)","url":"init(com.google.android.exoplayer2.util.TimestampAdjuster,com.google.android.exoplayer2.extractor.ExtractorOutput,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelector","l":"init(TrackSelector.InvalidationListener, BandwidthMeter)","url":"init(com.google.android.exoplayer2.trackselection.TrackSelector.InvalidationListener,com.google.android.exoplayer2.upstream.BandwidthMeter)"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"initForPrivateFrame(int, int)","url":"initForPrivateFrame(int,int)"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"initForYuvFrame(int, int, int, int, int)","url":"initForYuvFrame(int,int,int,int,int)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"INITIAL_DRM_REQUEST_RETRY_COUNT"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"initialAudioFormatBitrateCount"},{"p":"com.google.android.exoplayer2.source.chunk","c":"InitializationChunk","l":"InitializationChunk(DataSource, DataSpec, Format, int, Object, ChunkExtractor)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,com.google.android.exoplayer2.Format,int,java.lang.Object,com.google.android.exoplayer2.source.chunk.ChunkExtractor)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"initializationData"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.DvbSubtitleInfo","l":"initializationData"},{"p":"com.google.android.exoplayer2.video","c":"AvcConfig","l":"initializationData"},{"p":"com.google.android.exoplayer2.video","c":"HevcConfig","l":"initializationData"},{"p":"com.google.android.exoplayer2","c":"Format","l":"initializationDataEquals(Format)","url":"initializationDataEquals(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.InitializationException","l":"InitializationException(int, int, int, int, Format, boolean, Exception)","url":"%3Cinit%3E(int,int,int,int,com.google.android.exoplayer2.Format,boolean,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.SegmentBase","l":"initializationSegment"},{"p":"com.google.android.exoplayer2.util","c":"SntpClient","l":"initialize(Loader, SntpClient.InitializationCallback)","url":"initialize(com.google.android.exoplayer2.upstream.Loader,com.google.android.exoplayer2.util.SntpClient.InitializationCallback)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"initialSeek(int, long)","url":"initialSeek(int,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource.InitialTimeline","l":"InitialTimeline(Timeline)","url":"%3Cinit%3E(com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"initialVideoFormatBitrateCount"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"initialVideoFormatHeightCount"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"inputAudioFormat"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"inputBufferCount"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener.EventDispatcher","l":"inputFormatChanged(Format, DecoderReuseEvaluation)","url":"inputFormatChanged(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.decoder.DecoderReuseEvaluation)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener.EventDispatcher","l":"inputFormatChanged(Format, DecoderReuseEvaluation)","url":"inputFormatChanged(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.decoder.DecoderReuseEvaluation)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"InputReaderAdapterV30","l":"InputReaderAdapterV30()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer.CodecMaxValues","l":"inputSize"},{"p":"com.google.android.exoplayer2.upstream","c":"DummyDataSource","l":"INSTANCE"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer.InsufficientCapacityException","l":"InsufficientCapacityException(int, int)","url":"%3Cinit%3E(int,int)"},{"p":"com.google.android.exoplayer2.util","c":"IntArrayQueue","l":"IntArrayQueue()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"integerElement(int, long)","url":"integerElement(int,long)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"integerElement(int, long)","url":"integerElement(int,long)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"InternalFrame","l":"InternalFrame(String, String, String)","url":"%3Cinit%3E(java.lang.String,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelector","l":"invalidate()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"invalidate()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"invalidateForegroundNotification()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"invalidateMediaSessionMetadata()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"invalidateMediaSessionPlaybackState()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"invalidateMediaSessionQueue()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"invalidateUpstreamFormatAdjustment()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.InvalidContentTypeException","l":"InvalidContentTypeException(String, DataSpec)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.InvalidResponseCodeException","l":"InvalidResponseCodeException(int, Map>, DataSpec)","url":"%3Cinit%3E(int,java.util.Map,com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.InvalidResponseCodeException","l":"InvalidResponseCodeException(int, String, IOException, Map>, DataSpec, byte[])","url":"%3Cinit%3E(int,java.lang.String,java.io.IOException,java.util.Map,com.google.android.exoplayer2.upstream.DataSpec,byte[])"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.InvalidResponseCodeException","l":"InvalidResponseCodeException(int, String, Map>, DataSpec)","url":"%3Cinit%3E(int,java.lang.String,java.util.Map,com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.util","c":"ListenerSet.IterationFinishedEvent","l":"invoke(T, FlagSet)","url":"invoke(T,com.google.android.exoplayer2.util.FlagSet)"},{"p":"com.google.android.exoplayer2.util","c":"ListenerSet.Event","l":"invoke(T)"},{"p":"com.google.android.exoplayer2.util","c":"UriUtil","l":"isAbsolute(String)","url":"isAbsolute(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData.Segment","l":"isActionSegment()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor","l":"isActive()"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"isActive()"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"isActive()"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"isActive()"},{"p":"com.google.android.exoplayer2.ext.gvr","c":"GvrAudioProcessor","l":"isActive()"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"isAd()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"isAdInErrorState(int, int)","url":"isAdInErrorState(int,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsReader","l":"isAdtsSyncWord(int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"isAfterLast()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"isAnimationEnabled()"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"isAudio(String)","url":"isAudio(java.lang.String)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"isAudioChannelCountSupportedV21(int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"isAudioSampleRateSupportedV21(int)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Gav1Library","l":"isAvailable()"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegLibrary","l":"isAvailable()"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacLibrary","l":"isAvailable()"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusLibrary","l":"isAvailable()"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxLibrary","l":"isAvailable()"},{"p":"com.google.android.exoplayer2.util","c":"LibraryLoader","l":"isAvailable()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"isBeforeFirst()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"isBlacklisted(int, long)","url":"isBlacklisted(int,long)"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"isBlacklisted(int, long)","url":"isBlacklisted(int,long)"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"isBlacklisted(int, long)","url":"isBlacklisted(int,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheSpan","l":"isCached"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"isCached(String, long, long)","url":"isCached(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"isCached(String, long, long)","url":"isCached(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"isCacheFolderLocked(File)","url":"isCacheFolderLocked(java.io.File)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"isCanceled()"},{"p":"com.google.android.exoplayer2.util","c":"RunnableFutureTask","l":"isCancelled()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"isCastSessionAvailable()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceException","l":"isCausedByPositionOutOfRange(IOException)","url":"isCausedByPositionOutOfRange(java.io.IOException)"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"isChargingRequired()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"isClosed()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"isCodecSupported(Format)","url":"isCodecSupported(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"isCommandAvailable(int)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"isCommandAvailable(int)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"isCommandAvailable(int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"isControllerFullyVisible()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"isControllerVisible()"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"isCryptoSchemeSupported(UUID)","url":"isCryptoSchemeSupported(java.util.UUID)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"isCurrentStreamFinal()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"isCurrentStreamFinal()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"isCurrentStreamFinal()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"isCurrentWindowDynamic()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"isCurrentWindowDynamic()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"isCurrentWindowDynamic()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"isCurrentWindowLive()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"isCurrentWindowLive()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"isCurrentWindowLive()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"isCurrentWindowSeekable()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"isCurrentWindowSeekable()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"isCurrentWindowSeekable()"},{"p":"com.google.android.exoplayer2.decoder","c":"Buffer","l":"isDecodeOnly()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.DeviceComponent","l":"isDeviceMuted()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"isDeviceMuted()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"isDeviceMuted()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"isDeviceMuted()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"isDeviceMuted()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"isDeviceMuted()"},{"p":"com.google.android.exoplayer2.util","c":"RunnableFutureTask","l":"isDone()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"isDynamic"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"isDynamic"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultLoadErrorHandlingPolicy","l":"isEligibleForFallback(IOException)","url":"isEligibleForFallback(java.io.IOException)"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"isEmpty()"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroupArray","l":"isEmpty()"},{"p":"com.google.android.exoplayer2.util","c":"IntArrayQueue","l":"isEmpty()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"isEnabled"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"isEnabled()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"isEncodingHighResolutionPcm(int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"isEncodingLinearPcm(int)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"TrackEncryptionBox","l":"isEncrypted"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"isEncrypted()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"isEnded"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"isEnded()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"isEnded()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor","l":"isEnded()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"isEnded()"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"isEnded()"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"isEnded()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"isEnded()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"isEnded()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"isEnded()"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"isEnded()"},{"p":"com.google.android.exoplayer2.ext.gvr","c":"GvrAudioProcessor","l":"isEnded()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"isEnded()"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataRenderer","l":"isEnded()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunkIterator","l":"isEnded()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaChunkIterator","l":"isEnded()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"isEnded()"},{"p":"com.google.android.exoplayer2.text","c":"TextRenderer","l":"isEnded()"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"isEnded()"},{"p":"com.google.android.exoplayer2.video.spherical","c":"CameraMotionRenderer","l":"isEnded()"},{"p":"com.google.android.exoplayer2.decoder","c":"Buffer","l":"isEndOfStream()"},{"p":"com.google.android.exoplayer2.util","c":"XmlPullParserUtil","l":"isEndTag(XmlPullParser, String)","url":"isEndTag(org.xmlpull.v1.XmlPullParser,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"XmlPullParserUtil","l":"isEndTag(XmlPullParser)","url":"isEndTag(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectorResult","l":"isEquivalent(TrackSelectorResult, int)","url":"isEquivalent(com.google.android.exoplayer2.trackselection.TrackSelectorResult,int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectorResult","l":"isEquivalent(TrackSelectorResult)","url":"isEquivalent(com.google.android.exoplayer2.trackselection.TrackSelectorResult)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData.Segment","l":"isErrorSegment()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashSegmentIndex","l":"isExplicit()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashWrappingSegmentIndex","l":"isExplicit()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"isExplicit()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.MultiSegmentBase","l":"isExplicit()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SegmentList","l":"isExplicit()"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy.FallbackOptions","l":"isFallbackAvailable(int)"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"isFastForwardEnabled()"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"isFastForwardEnabled()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"isFirst()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"isFlagSet(int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"isFormatSupported(Format)","url":"isFormatSupported(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPayloadFormat","l":"isFormatSupported(MediaDescription)","url":"isFormatSupported(com.google.android.exoplayer2.source.rtsp.MediaDescription)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"isFullyVisible()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"isHdr10PlusOutOfBandMetadataSupported()"},{"p":"com.google.android.exoplayer2","c":"HeartRating","l":"isHeart()"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxLibrary","l":"isHighBitDepthSupported()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheSpan","l":"isHoleSpan()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"isIdle()"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"isIdleRequired()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.Part","l":"isIndependent"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"isInitialized()"},{"p":"com.google.android.exoplayer2.util","c":"SntpClient","l":"isInitialized()"},{"p":"com.google.android.exoplayer2.decoder","c":"Buffer","l":"isKeyFrame()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"isLast()"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"isLastPeriod(int, Timeline.Period, Timeline.Window, int, boolean)","url":"isLastPeriod(int,com.google.android.exoplayer2.Timeline.Period,com.google.android.exoplayer2.Timeline.Window,int,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"isLastSampleQueued()"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"isLevel1Element(int)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"isLevel1Element(int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"isLinebreak(int)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"isLinethrough()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"isLive"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest","l":"isLive"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"isLive"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"isLive()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"isLive()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"isLive()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ContainerMediaChunk","l":"isLoadCompleted()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaChunk","l":"isLoadCompleted()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"SingleSampleMediaChunk","l":"isLoadCompleted()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaChunk","l":"isLoadCompleted()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"isLoading()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"isLoading()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"isLoading()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"isLoading()"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"isLoading()"},{"p":"com.google.android.exoplayer2.source","c":"CompositeSequenceableLoader","l":"isLoading()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"isLoading()"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"isLoading()"},{"p":"com.google.android.exoplayer2.source","c":"SequenceableLoader","l":"isLoading()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"isLoading()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"isLoading()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"isLoading()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"isLoading()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"isLoading()"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"isLoading()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"isLoadingFinished()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"isLocalFileUri(Uri)","url":"isLocalFileUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"isMatroska(String)","url":"isMatroska(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil","l":"isNalUnitSei(String, byte)","url":"isNalUnitSei(java.lang.String,byte)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource.Factory","l":"isNetwork"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"isNetworkRequired()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"isNewerThan(HlsMediaPlaylist)","url":"isNewerThan(com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist)"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea608Decoder","l":"isNewSubtitleDataAvailable()"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea708Decoder","l":"isNewSubtitleDataAvailable()"},{"p":"com.google.android.exoplayer2","c":"C","l":"ISO88591_NAME"},{"p":"com.google.android.exoplayer2.video","c":"ColorInfo","l":"isoColorPrimariesToColorSpace(int)"},{"p":"com.google.android.exoplayer2.util","c":"ConditionVariable","l":"isOpen()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource","l":"isOpened()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheSpan","l":"isOpenEnded()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterTocFrame","l":"isOrdered"},{"p":"com.google.android.exoplayer2.video","c":"ColorInfo","l":"isoTransferCharacteristicsToColorTransfer(int)"},{"p":"com.google.android.exoplayer2.source.hls","c":"BundledHlsMediaChunkExtractor","l":"isPackedAudioExtractor()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaChunkExtractor","l":"isPackedAudioExtractor()"},{"p":"com.google.android.exoplayer2.source.hls","c":"MediaParserHlsMediaChunkExtractor","l":"isPackedAudioExtractor()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"isPlaceholder"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"isPlaceholder"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"isPlaceholder"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"isPlayable"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"isPlaying()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"isPlaying()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"isPlaying()"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"isPlaying()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"isPlayingAd()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"isPlayingAd()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"isPlayingAd()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"isPlayingAd()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"isPlayingAd()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.Part","l":"isPreload"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"isPrepared()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"isPrepared()"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil","l":"isProtectedContentExtensionSupported(Context)","url":"isProtectedContentExtensionSupported(android.content.Context)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"PsshAtomUtil","l":"isPsshAtom(byte[])"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"isPublic"},{"p":"com.google.android.exoplayer2","c":"HeartRating","l":"isRated()"},{"p":"com.google.android.exoplayer2","c":"PercentageRating","l":"isRated()"},{"p":"com.google.android.exoplayer2","c":"Rating","l":"isRated()"},{"p":"com.google.android.exoplayer2","c":"StarRating","l":"isRated()"},{"p":"com.google.android.exoplayer2","c":"ThumbRating","l":"isRated()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"isReady()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"isReady()"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"isReady()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"isReady()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"isReady()"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataRenderer","l":"isReady()"},{"p":"com.google.android.exoplayer2.source","c":"EmptySampleStream","l":"isReady()"},{"p":"com.google.android.exoplayer2.source","c":"SampleStream","l":"isReady()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"isReady()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream.EmbeddedSampleStream","l":"isReady()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"isReady()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"isReady()"},{"p":"com.google.android.exoplayer2.text","c":"TextRenderer","l":"isReady()"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"isReady()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"isReady()"},{"p":"com.google.android.exoplayer2.video.spherical","c":"CameraMotionRenderer","l":"isReady()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"isReady(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.InitializationException","l":"isRecoverable"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.WriteException","l":"isRecoverable"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectorResult","l":"isRendererEnabled(int)"},{"p":"com.google.android.exoplayer2.util","c":"RepeatModeUtil","l":"isRepeatModeEnabled(int, int)","url":"isRepeatModeEnabled(int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader.LoadErrorAction","l":"isRetry()"},{"p":"com.google.android.exoplayer2.source.hls","c":"BundledHlsMediaChunkExtractor","l":"isReusable()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaChunkExtractor","l":"isReusable()"},{"p":"com.google.android.exoplayer2.source.hls","c":"MediaParserHlsMediaChunkExtractor","l":"isReusable()"},{"p":"com.google.android.exoplayer2","c":"ControlDispatcher","l":"isRewindEnabled()"},{"p":"com.google.android.exoplayer2","c":"DefaultControlDispatcher","l":"isRewindEnabled()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterTocFrame","l":"isRoot"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"isSeamlessAdaptationSupported(Format, Format, boolean)","url":"isSeamlessAdaptationSupported(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.Format,boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"isSeamlessAdaptationSupported(Format)","url":"isSeamlessAdaptationSupported(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.video","c":"DummySurface","l":"isSecureSupported(Context)","url":"isSecureSupported(android.content.Context)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"isSeekable"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"isSeekable"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.BinarySearchSeekMap","l":"isSeekable()"},{"p":"com.google.android.exoplayer2.extractor","c":"ChunkIndex","l":"isSeekable()"},{"p":"com.google.android.exoplayer2.extractor","c":"ConstantBitrateSeekMap","l":"isSeekable()"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacSeekTableSeekMap","l":"isSeekable()"},{"p":"com.google.android.exoplayer2.extractor","c":"IndexSeekMap","l":"isSeekable()"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap","l":"isSeekable()"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap.Unseekable","l":"isSeekable()"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"isSeekable()"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"isSeeking()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationHolder","l":"isSegmentAvailableAtFullNetworkSpeed(long, long)","url":"isSegmentAvailableAtFullNetworkSpeed(long,long)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"isServerSideInserted"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"isServerSideInsertedAdGroup(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData","l":"isSimulatingUnknownLength()"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"isSingleWindow()"},{"p":"com.google.android.exoplayer2.source","c":"LoopingMediaSource","l":"isSingleWindow()"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"isSingleWindow()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"isSingleWindow()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"isSnapshotValid(Uri)","url":"isSnapshotValid(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"isSnapshotValid(Uri)","url":"isSnapshotValid(android.net.Uri)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"isSourceReady()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsUtil","l":"isStartOfTsPacket(byte[], int, int, int)","url":"isStartOfTsPacket(byte[],int,int,int)"},{"p":"com.google.android.exoplayer2.util","c":"XmlPullParserUtil","l":"isStartTag(XmlPullParser, String)","url":"isStartTag(org.xmlpull.v1.XmlPullParser,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"XmlPullParserUtil","l":"isStartTag(XmlPullParser)","url":"isStartTag(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.util","c":"XmlPullParserUtil","l":"isStartTagIgnorePrefix(XmlPullParser, String)","url":"isStartTagIgnorePrefix(org.xmlpull.v1.XmlPullParser,java.lang.String)"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"isStorageNotLowRequired()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"isSupported(int, boolean)","url":"isSupported(int,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil","l":"isSurfacelessContextExtensionSupported()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoDecoderException","l":"isSurfaceValid"},{"p":"com.google.android.exoplayer2.audio","c":"DtsUtil","l":"isSyncWord(int)"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"isTerminalState()"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"isText(String)","url":"isText(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"ThumbRating","l":"isThumbsUp()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"isTv(Context)","url":"isTv(android.content.Context)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"isUnderline()"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"isUnmeteredNetworkRequired()"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"isVideo(String)","url":"isVideo(java.lang.String)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"isVideoSizeAndRateSupportedV21(int, int, double)","url":"isVideoSizeAndRateSupportedV21(int,int,double)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"isVisible()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"isVisible()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"isWaitingForRequirements()"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttParserUtil","l":"isWebvttHeaderLine(ParsableByteArray)","url":"isWebvttHeaderLine(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"isWindowColorSet()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.AudioTrackScore","l":"isWithinConstraints"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.TextTrackScore","l":"isWithinConstraints"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.VideoTrackScore","l":"isWithinMaxConstraints"},{"p":"com.google.android.exoplayer2.util","c":"CopyOnWriteMultiset","l":"iterator()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveDataSet.Iterator","l":"Iterator(FakeAdaptiveDataSet, int, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.testutil.FakeAdaptiveDataSet,int,int)"},{"p":"com.google.android.exoplayer2.decoder","c":"CryptoInfo","l":"iv"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"JPEG"},{"p":"com.google.android.exoplayer2.extractor.jpeg","c":"JpegExtractor","l":"JpegExtractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"jumpDrawablesToCurrentState()"},{"p":"com.google.android.exoplayer2.decoder","c":"CryptoInfo","l":"key"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"VorbisComment","l":"key"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MdtaMetadataEntry","l":"key"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"key"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheSpan","l":"key"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MdtaMetadataEntry","l":"KEY_ANDROID_CAPTURE_FPS"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"KEY_CONTENT_ID"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadata","l":"KEY_CONTENT_LENGTH"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadata","l":"KEY_CUSTOM_PREFIX"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"KEY_DOWNLOAD_REQUEST"},{"p":"com.google.android.exoplayer2.util","c":"MediaFormatUtil","l":"KEY_EXO_PCM_ENCODING"},{"p":"com.google.android.exoplayer2.util","c":"MediaFormatUtil","l":"KEY_EXO_PIXEL_WIDTH_HEIGHT_RATIO_FLOAT"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"KEY_FOREGROUND"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadata","l":"KEY_REDIRECTED_URI"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"KEY_REQUIREMENTS"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"KEY_STATUS_AVAILABLE"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"KEY_STATUS_KEY"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"KEY_STATUS_UNAVAILABLE"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"KEY_STOP_REASON"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"KEY_TYPE_OFFLINE"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"KEY_TYPE_RELEASE"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"KEY_TYPE_STREAMING"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"keyForField(int)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyRequest","l":"KeyRequest(byte[], String, int)","url":"%3Cinit%3E(byte[],java.lang.String,int)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyRequest","l":"KeyRequest(byte[], String)","url":"%3Cinit%3E(byte[],java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"keySetId"},{"p":"com.google.android.exoplayer2.drm","c":"KeysExpiredException","l":"KeysExpiredException()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyStatus","l":"KeyStatus(int, byte[])","url":"%3Cinit%3E(int,byte[])"},{"p":"com.google.android.exoplayer2","c":"Format","l":"label"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Subtitle","l":"label"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ProgramInformation","l":"lang"},{"p":"com.google.android.exoplayer2","c":"Format","l":"language"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Subtitle","l":"language"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.DvbSubtitleInfo","l":"language"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.EsInfo","l":"language"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"CommentFrame","l":"language"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"language"},{"p":"com.google.android.exoplayer2","c":"C","l":"LANGUAGE_UNDETERMINED"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"lastFormat"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.RenditionReport","l":"lastMediaSequence"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.RenditionReport","l":"lastPartIndex"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"lastPeriodIndex"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheSpan","l":"lastTouchTimestamp"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"LatmReader","l":"LatmReader(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"LeanbackPlayerAdapter(Context, Player, int)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.Player,int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"LeastRecentlyUsedCacheEvictor","l":"LeastRecentlyUsedCacheEvictor(long)","url":"%3Cinit%3E(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"ChunkIndex","l":"length"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.CommentHeader","l":"length"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroup","l":"length"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroupArray","l":"length"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"RangedUri","l":"length"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData.Segment","l":"length"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"length"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.SelectionOverride","l":"length"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionArray","l":"length"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectorResult","l":"length"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"length"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheSpan","l":"length"},{"p":"com.google.android.exoplayer2","c":"C","l":"LENGTH_UNSET"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata","l":"length()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"length()"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"length()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelection","l":"length()"},{"p":"com.google.android.exoplayer2.video","c":"DolbyVisionConfig","l":"level"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"levelIdc"},{"p":"com.google.android.exoplayer2.ext.flac","c":"LibflacAudioRenderer","l":"LibflacAudioRenderer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.flac","c":"LibflacAudioRenderer","l":"LibflacAudioRenderer(Handler, AudioRendererEventListener, AudioProcessor...)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioProcessor...)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"LibflacAudioRenderer","l":"LibflacAudioRenderer(Handler, AudioRendererEventListener, AudioSink)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioSink)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Libgav1VideoRenderer","l":"Libgav1VideoRenderer(long, Handler, VideoRendererEventListener, int, int, int, int)","url":"%3Cinit%3E(long,android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener,int,int,int,int)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Libgav1VideoRenderer","l":"Libgav1VideoRenderer(long, Handler, VideoRendererEventListener, int)","url":"%3Cinit%3E(long,android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener,int)"},{"p":"com.google.android.exoplayer2.ext.opus","c":"LibopusAudioRenderer","l":"LibopusAudioRenderer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.opus","c":"LibopusAudioRenderer","l":"LibopusAudioRenderer(Handler, AudioRendererEventListener, AudioProcessor...)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioProcessor...)"},{"p":"com.google.android.exoplayer2.ext.opus","c":"LibopusAudioRenderer","l":"LibopusAudioRenderer(Handler, AudioRendererEventListener, AudioSink)","url":"%3Cinit%3E(android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioSink)"},{"p":"com.google.android.exoplayer2.util","c":"LibraryLoader","l":"LibraryLoader(String...)","url":"%3Cinit%3E(java.lang.String...)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"LibvpxVideoRenderer","l":"LibvpxVideoRenderer(long, Handler, VideoRendererEventListener, int, int, int, int)","url":"%3Cinit%3E(long,android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener,int,int,int,int)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"LibvpxVideoRenderer","l":"LibvpxVideoRenderer(long, Handler, VideoRendererEventListener, int)","url":"%3Cinit%3E(long,android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener,int)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"LibvpxVideoRenderer","l":"LibvpxVideoRenderer(long)","url":"%3Cinit%3E(long)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"licenseServerUrl"},{"p":"com.google.android.exoplayer2","c":"MediaItem.DrmConfiguration","l":"licenseUri"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"limit()"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"line"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"LINE_TYPE_FRACTION"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"LINE_TYPE_NUMBER"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"lineAnchor"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"linearSearch(int[], int)","url":"linearSearch(int[],int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"linearSearch(long[], long)","url":"linearSearch(long[],long)"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"lineType"},{"p":"com.google.android.exoplayer2.util","c":"ListenerSet","l":"ListenerSet(Looper, Clock, ListenerSet.IterationFinishedEvent)","url":"%3Cinit%3E(android.os.Looper,com.google.android.exoplayer2.util.Clock,com.google.android.exoplayer2.util.ListenerSet.IterationFinishedEvent)"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"liveConfiguration"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"liveConfiguration"},{"p":"com.google.android.exoplayer2","c":"MediaItem.LiveConfiguration","l":"LiveConfiguration(long, long, long, float, float)","url":"%3Cinit%3E(long,long,long,float,float)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper.LiveContentUnsupportedException","l":"LiveContentUnsupportedException()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ContainerMediaChunk","l":"load()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"DataChunk","l":"load()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"InitializationChunk","l":"load()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"SingleSampleMediaChunk","l":"load()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaChunk","l":"load()"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader.Loadable","l":"load()"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"load()"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"load(DataSource, ParsingLoadable.Parser, DataSpec, int)","url":"load(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.ParsingLoadable.Parser,com.google.android.exoplayer2.upstream.DataSpec,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"load(DataSource, ParsingLoadable.Parser, Uri, int)","url":"load(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.ParsingLoadable.Parser,android.net.Uri,int)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"loadCanceled(LoadEventInfo, int, int, Format, int, Object, long, long)","url":"loadCanceled(com.google.android.exoplayer2.source.LoadEventInfo,int,int,com.google.android.exoplayer2.Format,int,java.lang.Object,long,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"loadCanceled(LoadEventInfo, int)","url":"loadCanceled(com.google.android.exoplayer2.source.LoadEventInfo,int)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"loadCanceled(LoadEventInfo, MediaLoadData)","url":"loadCanceled(com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashUtil","l":"loadChunkIndex(DataSource, int, Representation, int)","url":"loadChunkIndex(com.google.android.exoplayer2.upstream.DataSource,int,com.google.android.exoplayer2.source.dash.manifest.Representation,int)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashUtil","l":"loadChunkIndex(DataSource, int, Representation)","url":"loadChunkIndex(com.google.android.exoplayer2.upstream.DataSource,int,com.google.android.exoplayer2.source.dash.manifest.Representation)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"loadCompleted(LoadEventInfo, int, int, Format, int, Object, long, long)","url":"loadCompleted(com.google.android.exoplayer2.source.LoadEventInfo,int,int,com.google.android.exoplayer2.Format,int,java.lang.Object,long,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"loadCompleted(LoadEventInfo, int)","url":"loadCompleted(com.google.android.exoplayer2.source.LoadEventInfo,int)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"loadCompleted(LoadEventInfo, MediaLoadData)","url":"loadCompleted(com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source","c":"LoadEventInfo","l":"loadDurationMs"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"Loader(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"loadError(LoadEventInfo, int, int, Format, int, Object, long, long, IOException, boolean)","url":"loadError(com.google.android.exoplayer2.source.LoadEventInfo,int,int,com.google.android.exoplayer2.Format,int,java.lang.Object,long,long,java.io.IOException,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"loadError(LoadEventInfo, int, IOException, boolean)","url":"loadError(com.google.android.exoplayer2.source.LoadEventInfo,int,java.io.IOException,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"loadError(LoadEventInfo, MediaLoadData, IOException, boolean)","url":"loadError(com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData,java.io.IOException,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy.LoadErrorInfo","l":"LoadErrorInfo(LoadEventInfo, MediaLoadData, IOException, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData,java.io.IOException,int)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeSequenceableLoader","l":"loaders"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy.LoadErrorInfo","l":"loadEventInfo"},{"p":"com.google.android.exoplayer2.source","c":"LoadEventInfo","l":"LoadEventInfo(long, DataSpec, long)","url":"%3Cinit%3E(long,com.google.android.exoplayer2.upstream.DataSpec,long)"},{"p":"com.google.android.exoplayer2.source","c":"LoadEventInfo","l":"LoadEventInfo(long, DataSpec, Uri, Map>, long, long, long)","url":"%3Cinit%3E(long,com.google.android.exoplayer2.upstream.DataSpec,android.net.Uri,java.util.Map,long,long,long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashUtil","l":"loadFormatWithDrmInitData(DataSource, Period)","url":"loadFormatWithDrmInitData(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.source.dash.manifest.Period)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashUtil","l":"loadInitializationData(ChunkExtractor, DataSource, Representation, boolean)","url":"loadInitializationData(com.google.android.exoplayer2.source.chunk.ChunkExtractor,com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.source.dash.manifest.Representation,boolean)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashUtil","l":"loadManifest(DataSource, Uri)","url":"loadManifest(com.google.android.exoplayer2.upstream.DataSource,android.net.Uri)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashUtil","l":"loadSampleFormat(DataSource, int, Representation, int)","url":"loadSampleFormat(com.google.android.exoplayer2.upstream.DataSource,int,com.google.android.exoplayer2.source.dash.manifest.Representation,int)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashUtil","l":"loadSampleFormat(DataSource, int, Representation)","url":"loadSampleFormat(com.google.android.exoplayer2.upstream.DataSource,int,com.google.android.exoplayer2.source.dash.manifest.Representation)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"loadStarted(LoadEventInfo, int, int, Format, int, Object, long, long)","url":"loadStarted(com.google.android.exoplayer2.source.LoadEventInfo,int,int,com.google.android.exoplayer2.Format,int,java.lang.Object,long,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"loadStarted(LoadEventInfo, int)","url":"loadStarted(com.google.android.exoplayer2.source.LoadEventInfo,int)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"loadStarted(LoadEventInfo, MediaLoadData)","url":"loadStarted(com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source","c":"LoadEventInfo","l":"loadTaskId"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"loadTaskId"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"loadTaskId"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MdtaMetadataEntry","l":"localeIndicator"},{"p":"com.google.android.exoplayer2.drm","c":"LocalMediaDrmCallback","l":"LocalMediaDrmCallback(byte[])","url":"%3Cinit%3E(byte[])"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"location"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"LOG_LEVEL_ALL"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"LOG_LEVEL_ERROR"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"LOG_LEVEL_INFO"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"LOG_LEVEL_OFF"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"LOG_LEVEL_WARNING"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"logd(String)","url":"logd(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"loge(String)","url":"loge(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"logMetrics(DecoderCounters, DecoderCounters)","url":"logMetrics(com.google.android.exoplayer2.decoder.DecoderCounters,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.util","c":"LongArray","l":"LongArray()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.util","c":"LongArray","l":"LongArray(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest","l":"lookAheadCount"},{"p":"com.google.android.exoplayer2.source","c":"LoopingMediaSource","l":"LoopingMediaSource(MediaSource, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaSource,int)"},{"p":"com.google.android.exoplayer2.source","c":"LoopingMediaSource","l":"LoopingMediaSource(MediaSource)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest","l":"majorVersion"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"manifest"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"MANUFACTURER"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.Mode","l":"mapping"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector","l":"MappingTrackSelector()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.text.span","c":"TextEmphasisSpan","l":"MARK_FILL_FILLED"},{"p":"com.google.android.exoplayer2.text.span","c":"TextEmphasisSpan","l":"MARK_FILL_OPEN"},{"p":"com.google.android.exoplayer2.text.span","c":"TextEmphasisSpan","l":"MARK_FILL_UNKNOWN"},{"p":"com.google.android.exoplayer2.text.span","c":"TextEmphasisSpan","l":"MARK_SHAPE_CIRCLE"},{"p":"com.google.android.exoplayer2.text.span","c":"TextEmphasisSpan","l":"MARK_SHAPE_DOT"},{"p":"com.google.android.exoplayer2.text.span","c":"TextEmphasisSpan","l":"MARK_SHAPE_NONE"},{"p":"com.google.android.exoplayer2.text.span","c":"TextEmphasisSpan","l":"MARK_SHAPE_SESAME"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"markAsProcessed(boolean)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"marker"},{"p":"com.google.android.exoplayer2.text.span","c":"TextEmphasisSpan","l":"markFill"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"markSeekOperationFinished(boolean, long)","url":"markSeekOperationFinished(boolean,long)"},{"p":"com.google.android.exoplayer2.text.span","c":"TextEmphasisSpan","l":"markShape"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"MaskingMediaPeriod(MediaSource.MediaPeriodId, Allocator, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.upstream.Allocator,long)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource","l":"MaskingMediaSource(MediaSource, boolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaSource,boolean)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsManifest","l":"masterPlaylist"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"matches(UUID)","url":"matches(java.util.UUID)"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusLibrary","l":"matchesExpectedExoMediaCryptoType(Class)","url":"matchesExpectedExoMediaCryptoType(java.lang.Class)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxLibrary","l":"matchesExpectedExoMediaCryptoType(Class)","url":"matchesExpectedExoMediaCryptoType(java.lang.Class)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"MATROSKA"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"MatroskaExtractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"MatroskaExtractor(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY"},{"p":"com.google.android.exoplayer2.util","c":"FlacConstants","l":"MAX_FRAME_HEADER_SIZE"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil","l":"MAX_FRAME_SIZE_BYTES"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"MAX_PITCH"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"MAX_PLAYBACK_SPEED"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"MAX_PLAYING_TIME_DISCREPANCY_MS"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util","l":"MAX_RATE_BYTES_PER_SECOND"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil","l":"MAX_RATE_BYTES_PER_SECOND"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"MAX_SEQUENCE_NUMBER"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"MAX_SIZE"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"MAX_SUPPORTED_INSTANCES_UNKNOWN"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"MAX_WINDOWS_FOR_MULTI_WINDOW_TIME_BAR"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"MAX_WINDOWS_FOR_MULTI_WINDOW_TIME_BAR"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"maxAudioBitrate"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"maxAudioChannelCount"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"maxBlockSizeSamples"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"maxConsecutiveDroppedBufferCount"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"maxFrameSize"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecUtil","l":"maxH264DecodableFrameSize()"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"maxHeight"},{"p":"com.google.android.exoplayer2","c":"Format","l":"maxInputSize"},{"p":"com.google.android.exoplayer2","c":"MediaItem.LiveConfiguration","l":"maxOffsetMs"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ServiceDescriptionElement","l":"maxOffsetMs"},{"p":"com.google.android.exoplayer2","c":"MediaItem.LiveConfiguration","l":"maxPlaybackSpeed"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ServiceDescriptionElement","l":"maxPlaybackSpeed"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"maxRebufferTimeMs"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"maxVideoBitrate"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"maxVideoFrameRate"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"maxVideoHeight"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"maxVideoWidth"},{"p":"com.google.android.exoplayer2.device","c":"DeviceInfo","l":"maxVolume"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"maxWidth"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"maybeDropBuffersToKeyframe(long, boolean)","url":"maybeDropBuffersToKeyframe(long,boolean)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"maybeDropBuffersToKeyframe(long)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"maybeInitCodecOrBypass()"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler.PlayerTrackEmsgHandler","l":"maybeRefreshManifestBeforeLoadingNextChunk(long)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"maybeRequestReadExternalStoragePermission(Activity, MediaItem...)","url":"maybeRequestReadExternalStoragePermission(android.app.Activity,com.google.android.exoplayer2.MediaItem...)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"maybeRequestReadExternalStoragePermission(Activity, Uri...)","url":"maybeRequestReadExternalStoragePermission(android.app.Activity,android.net.Uri...)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"maybeSetArtworkData(byte[], int)","url":"maybeSetArtworkData(byte[],int)"},{"p":"com.google.android.exoplayer2.util","c":"MediaFormatUtil","l":"maybeSetByteBuffer(MediaFormat, String, byte[])","url":"maybeSetByteBuffer(android.media.MediaFormat,java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.util","c":"MediaFormatUtil","l":"maybeSetColorInfo(MediaFormat, ColorInfo)","url":"maybeSetColorInfo(android.media.MediaFormat,com.google.android.exoplayer2.video.ColorInfo)"},{"p":"com.google.android.exoplayer2.util","c":"MediaFormatUtil","l":"maybeSetFloat(MediaFormat, String, float)","url":"maybeSetFloat(android.media.MediaFormat,java.lang.String,float)"},{"p":"com.google.android.exoplayer2.util","c":"MediaFormatUtil","l":"maybeSetInteger(MediaFormat, String, int)","url":"maybeSetInteger(android.media.MediaFormat,java.lang.String,int)"},{"p":"com.google.android.exoplayer2.util","c":"MediaFormatUtil","l":"maybeSetString(MediaFormat, String, String)","url":"maybeSetString(android.media.MediaFormat,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"maybeSkipTag(XmlPullParser)","url":"maybeSkipTag(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.source","c":"EmptySampleStream","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.source","c":"SampleStream","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream.EmbeddedSampleStream","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSource","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.upstream","c":"LoaderErrorThrower","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.upstream","c":"LoaderErrorThrower.Dummy","l":"maybeThrowError()"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"maybeThrowError(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"LoaderErrorThrower","l":"maybeThrowError(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"LoaderErrorThrower.Dummy","l":"maybeThrowError(int)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"maybeThrowPlaylistRefreshError(Uri)","url":"maybeThrowPlaylistRefreshError(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"maybeThrowPlaylistRefreshError(Uri)","url":"maybeThrowPlaylistRefreshError(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"maybeThrowPrepareError()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"maybeThrowPrepareError()"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"maybeThrowPrepareError()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"maybeThrowPrepareError()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"maybeThrowPrepareError()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"maybeThrowPrepareError()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"maybeThrowPrimaryPlaylistRefreshError()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"maybeThrowPrimaryPlaylistRefreshError()"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"maybeThrowSourceInfoRefreshError()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"maybeThrowStreamError()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"maybeThrowStreamError()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"maybeThrowStreamError()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MdtaMetadataEntry","l":"MdtaMetadataEntry(String, byte[], int, int)","url":"%3Cinit%3E(java.lang.String,byte[],int,int)"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource","l":"MEDIA_ID"},{"p":"com.google.android.exoplayer2","c":"Player","l":"MEDIA_ITEM_TRANSITION_REASON_AUTO"},{"p":"com.google.android.exoplayer2","c":"Player","l":"MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"MEDIA_ITEM_TRANSITION_REASON_REPEAT"},{"p":"com.google.android.exoplayer2","c":"Player","l":"MEDIA_ITEM_TRANSITION_REASON_SEEK"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaChunk","l":"MediaChunk(DataSource, DataSpec, Format, int, Object, long, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,com.google.android.exoplayer2.Format,int,java.lang.Object,long,long,long)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"MediaCodecAudioRenderer(Context, MediaCodecAdapter.Factory, MediaCodecSelector, boolean, Handler, AudioRendererEventListener, AudioSink)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.mediacodec.MediaCodecAdapter.Factory,com.google.android.exoplayer2.mediacodec.MediaCodecSelector,boolean,android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioSink)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"MediaCodecAudioRenderer(Context, MediaCodecSelector, boolean, Handler, AudioRendererEventListener, AudioSink)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.mediacodec.MediaCodecSelector,boolean,android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioSink)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"MediaCodecAudioRenderer(Context, MediaCodecSelector, Handler, AudioRendererEventListener, AudioCapabilities, AudioProcessor...)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.mediacodec.MediaCodecSelector,android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioCapabilities,com.google.android.exoplayer2.audio.AudioProcessor...)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"MediaCodecAudioRenderer(Context, MediaCodecSelector, Handler, AudioRendererEventListener, AudioSink)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.mediacodec.MediaCodecSelector,android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener,com.google.android.exoplayer2.audio.AudioSink)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"MediaCodecAudioRenderer(Context, MediaCodecSelector, Handler, AudioRendererEventListener)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.mediacodec.MediaCodecSelector,android.os.Handler,com.google.android.exoplayer2.audio.AudioRendererEventListener)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"MediaCodecAudioRenderer(Context, MediaCodecSelector)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.mediacodec.MediaCodecSelector)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecDecoderException","l":"MediaCodecDecoderException(Throwable, MediaCodecInfo)","url":"%3Cinit%3E(java.lang.Throwable,com.google.android.exoplayer2.mediacodec.MediaCodecInfo)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"MediaCodecRenderer(int, MediaCodecAdapter.Factory, MediaCodecSelector, boolean, float)","url":"%3Cinit%3E(int,com.google.android.exoplayer2.mediacodec.MediaCodecAdapter.Factory,com.google.android.exoplayer2.mediacodec.MediaCodecSelector,boolean,float)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoDecoderException","l":"MediaCodecVideoDecoderException(Throwable, MediaCodecInfo, Surface)","url":"%3Cinit%3E(java.lang.Throwable,com.google.android.exoplayer2.mediacodec.MediaCodecInfo,android.view.Surface)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"MediaCodecVideoRenderer(Context, MediaCodecAdapter.Factory, MediaCodecSelector, long, boolean, Handler, VideoRendererEventListener, int)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.mediacodec.MediaCodecAdapter.Factory,com.google.android.exoplayer2.mediacodec.MediaCodecSelector,long,boolean,android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener,int)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"MediaCodecVideoRenderer(Context, MediaCodecSelector, long, boolean, Handler, VideoRendererEventListener, int)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.mediacodec.MediaCodecSelector,long,boolean,android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener,int)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"MediaCodecVideoRenderer(Context, MediaCodecSelector, long, Handler, VideoRendererEventListener, int)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.mediacodec.MediaCodecSelector,long,android.os.Handler,com.google.android.exoplayer2.video.VideoRendererEventListener,int)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"MediaCodecVideoRenderer(Context, MediaCodecSelector, long)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.mediacodec.MediaCodecSelector,long)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"MediaCodecVideoRenderer(Context, MediaCodecSelector)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.mediacodec.MediaCodecSelector)"},{"p":"com.google.android.exoplayer2.drm","c":"MediaDrmCallbackException","l":"MediaDrmCallbackException(DataSpec, Uri, Map>, long, Throwable)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSpec,android.net.Uri,java.util.Map,long,java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.source","c":"MediaLoadData","l":"mediaEndTimeMs"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter.Configuration","l":"mediaFormat"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"mediaId"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor.MediaIdEqualityChecker","l":"MediaIdEqualityChecker()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.MediaIdMediaItemProvider","l":"MediaIdMediaItemProvider()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"mediaItem"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"mediaItem"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy.LoadErrorInfo","l":"mediaLoadData"},{"p":"com.google.android.exoplayer2.source","c":"MediaLoadData","l":"MediaLoadData(int, int, Format, int, Object, long, long)","url":"%3Cinit%3E(int,int,com.google.android.exoplayer2.Format,int,java.lang.Object,long,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaLoadData","l":"MediaLoadData(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"mediaMetadata"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaParserChunkExtractor","l":"MediaParserChunkExtractor(int, Format, List)","url":"%3Cinit%3E(int,com.google.android.exoplayer2.Format,java.util.List)"},{"p":"com.google.android.exoplayer2.source","c":"MediaParserExtractorAdapter","l":"MediaParserExtractorAdapter()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.hls","c":"MediaParserHlsMediaChunkExtractor","l":"MediaParserHlsMediaChunkExtractor(MediaParser, OutputConsumerAdapterV30, Format, boolean, ImmutableList, int)","url":"%3Cinit%3E(android.media.MediaParser,com.google.android.exoplayer2.source.mediaparser.OutputConsumerAdapterV30,com.google.android.exoplayer2.Format,boolean,com.google.common.collect.ImmutableList,int)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"mediaPeriod"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"mediaPeriodId"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"mediaPeriodId"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener.EventDispatcher","l":"mediaPeriodId"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"mediaPeriodId"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"MediaPeriodId(MediaPeriodId)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource.MediaPeriodId","l":"MediaPeriodId(MediaPeriodId)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"MediaPeriodId(Object, int, int, long)","url":"%3Cinit%3E(java.lang.Object,int,int,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource.MediaPeriodId","l":"MediaPeriodId(Object, int, int, long)","url":"%3Cinit%3E(java.lang.Object,int,int,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"MediaPeriodId(Object, long, int)","url":"%3Cinit%3E(java.lang.Object,long,int)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource.MediaPeriodId","l":"MediaPeriodId(Object, long, int)","url":"%3Cinit%3E(java.lang.Object,long,int)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"MediaPeriodId(Object, long)","url":"%3Cinit%3E(java.lang.Object,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource.MediaPeriodId","l":"MediaPeriodId(Object, long)","url":"%3Cinit%3E(java.lang.Object,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"MediaPeriodId(Object)","url":"%3Cinit%3E(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource.MediaPeriodId","l":"MediaPeriodId(Object)","url":"%3Cinit%3E(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsManifest","l":"mediaPlaylist"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"mediaPlaylistUrls"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"mediaSequence"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"mediaSession"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"MediaSessionConnector(MediaSessionCompat)","url":"%3Cinit%3E(android.support.v4.media.session.MediaSessionCompat)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"MediaSourceTestRunner(MediaSource, Allocator)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaSource,com.google.android.exoplayer2.upstream.Allocator)"},{"p":"com.google.android.exoplayer2.source","c":"MediaLoadData","l":"mediaStartTimeMs"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"mediaTimeHistory"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"mediaUri"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"merge(DecoderCounters)","url":"merge(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"merge(DrmInitData)","url":"merge(com.google.android.exoplayer2.drm.DrmInitData)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"merge(PlaybackStats...)","url":"merge(com.google.android.exoplayer2.analytics.PlaybackStats...)"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"MergingMediaSource(boolean, boolean, CompositeSequenceableLoaderFactory, MediaSource...)","url":"%3Cinit%3E(boolean,boolean,com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory,com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"MergingMediaSource(boolean, boolean, MediaSource...)","url":"%3Cinit%3E(boolean,boolean,com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"MergingMediaSource(boolean, MediaSource...)","url":"%3Cinit%3E(boolean,com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"MergingMediaSource(MediaSource...)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"messageData"},{"p":"com.google.android.exoplayer2","c":"Format","l":"metadata"},{"p":"com.google.android.exoplayer2.util","c":"FlacConstants","l":"METADATA_BLOCK_HEADER_SIZE"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource","l":"METADATA_TYPE_EMSG"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource","l":"METADATA_TYPE_ID3"},{"p":"com.google.android.exoplayer2.util","c":"FlacConstants","l":"METADATA_TYPE_PICTURE"},{"p":"com.google.android.exoplayer2.util","c":"FlacConstants","l":"METADATA_TYPE_SEEK_TABLE"},{"p":"com.google.android.exoplayer2.util","c":"FlacConstants","l":"METADATA_TYPE_STREAM_INFO"},{"p":"com.google.android.exoplayer2.util","c":"FlacConstants","l":"METADATA_TYPE_VORBIS_COMMENT"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata","l":"Metadata(List)","url":"%3Cinit%3E(java.util.List)"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata","l":"Metadata(Metadata.Entry...)","url":"%3Cinit%3E(com.google.android.exoplayer2.metadata.Metadata.Entry...)"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataInputBuffer","l":"MetadataInputBuffer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"metadataInterval"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataRenderer","l":"MetadataRenderer(MetadataOutput, Looper, MetadataDecoderFactory)","url":"%3Cinit%3E(com.google.android.exoplayer2.metadata.MetadataOutput,android.os.Looper,com.google.android.exoplayer2.metadata.MetadataDecoderFactory)"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataRenderer","l":"MetadataRenderer(MetadataOutput, Looper)","url":"%3Cinit%3E(com.google.android.exoplayer2.metadata.MetadataOutput,android.os.Looper)"},{"p":"com.google.android.exoplayer2","c":"C","l":"MICROS_PER_SECOND"},{"p":"com.google.android.exoplayer2","c":"C","l":"MILLIS_PER_SECOND"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"MlltFrame","l":"millisecondsBetweenReference"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"MlltFrame","l":"millisecondsDeviations"},{"p":"com.google.android.exoplayer2","c":"MediaItem.PlaybackProperties","l":"mimeType"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Subtitle","l":"mimeType"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util.SyncFrameInfo","l":"mimeType"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil.Header","l":"mimeType"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"mimeType"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"mimeType"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer.DecoderInitializationException","l":"mimeType"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"mimeType"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ApicFrame","l":"mimeType"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"GeobFrame","l":"mimeType"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"mimeType"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea608Decoder","l":"MIN_DATA_CHANNEL_TIMEOUT_MS"},{"p":"com.google.android.exoplayer2.util","c":"FlacConstants","l":"MIN_FRAME_HEADER_SIZE"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"MIN_HEADER_SIZE"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"MIN_PITCH"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"MIN_PLAYBACK_SPEED"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"MIN_SEQUENCE_NUMBER"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"minBlockSizeSamples"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"minBufferTimeMs"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"minFrameSize"},{"p":"com.google.android.exoplayer2","c":"MediaItem.LiveConfiguration","l":"minOffsetMs"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ServiceDescriptionElement","l":"minOffsetMs"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest","l":"minorVersion"},{"p":"com.google.android.exoplayer2","c":"MediaItem.LiveConfiguration","l":"minPlaybackSpeed"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ServiceDescriptionElement","l":"minPlaybackSpeed"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"minUpdatePeriodMs"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"minValue(SparseLongArray)","url":"minValue(android.util.SparseLongArray)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"minVideoBitrate"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"minVideoFrameRate"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"minVideoHeight"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"minVideoWidth"},{"p":"com.google.android.exoplayer2.device","c":"DeviceInfo","l":"minVolume"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifestParser.MissingFieldException","l":"MissingFieldException(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"MlltFrame","l":"MlltFrame(int, int, int, int[], int[])","url":"%3Cinit%3E(int,int,int,int[],int[])"},{"p":"com.google.android.exoplayer2.decoder","c":"CryptoInfo","l":"mode"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"mode"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"MODE_DOWNLOAD"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"MODE_HLS"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"MODE_MULTI_PMT"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"MODE_NO_OFFSET"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"MODE_PLAYBACK"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"MODE_QUERY"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"MODE_RELEASE"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"MODE_SHARED"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"MODE_SINGLE_PMT"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.Mode","l":"Mode(boolean, int, int, int)","url":"%3Cinit%3E(boolean,int,int,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"MODEL"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"modifyTrack(Track)","url":"modifyTrack(com.google.android.exoplayer2.extractor.mp4.Track)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ProgramInformation","l":"moreInformationURL"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MotionPhotoMetadata","l":"MotionPhotoMetadata(long, long, long, long, long)","url":"%3Cinit%3E(long,long,long,long,long)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor.QueueDataAdapter","l":"move(int, int)","url":"move(int,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"moveItems(List, int, int, int)","url":"moveItems(java.util.List,int,int,int)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"moveMediaItem(int, int)","url":"moveMediaItem(int,int)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"moveMediaItem(int, int)","url":"moveMediaItem(int,int)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"moveMediaItem(int, int)","url":"moveMediaItem(int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"moveMediaItem(int, int)","url":"moveMediaItem(int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.MoveMediaItem","l":"MoveMediaItem(String, int, int)","url":"%3Cinit%3E(java.lang.String,int,int)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"moveMediaItems(int, int, int)","url":"moveMediaItems(int,int,int)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"moveMediaItems(int, int, int)","url":"moveMediaItems(int,int,int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"moveMediaItems(int, int, int)","url":"moveMediaItems(int,int,int)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"moveMediaItems(int, int, int)","url":"moveMediaItems(int,int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"moveMediaItems(int, int, int)","url":"moveMediaItems(int,int,int)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"moveMediaSource(int, int, Handler, Runnable)","url":"moveMediaSource(int,int,android.os.Handler,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"moveMediaSource(int, int)","url":"moveMediaSource(int,int)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"movePlaylistItem(int, int)","url":"movePlaylistItem(int,int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"moveToFirst()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"moveToLast()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"moveToNext()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"moveToPosition(int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadCursor","l":"moveToPrevious()"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"movieTimescale"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"MP3"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"Mp3Extractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"Mp3Extractor(int, long)","url":"%3Cinit%3E(int,long)"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"Mp3Extractor(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"MP4"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"Mp4Extractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"Mp4Extractor(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"Mp4WebvttDecoder","l":"Mp4WebvttDecoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"MpegAudioReader","l":"MpegAudioReader()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"MpegAudioReader","l":"MpegAudioReader(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"MlltFrame","l":"mpegFramesBetweenReference"},{"p":"com.google.android.exoplayer2","c":"C","l":"MSG_CUSTOM_BASE"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"MSG_CUSTOM_BASE"},{"p":"com.google.android.exoplayer2","c":"C","l":"MSG_SET_AUDIO_ATTRIBUTES"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"MSG_SET_AUDIO_ATTRIBUTES"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"MSG_SET_AUDIO_SESSION_ID"},{"p":"com.google.android.exoplayer2","c":"C","l":"MSG_SET_AUX_EFFECT_INFO"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"MSG_SET_AUX_EFFECT_INFO"},{"p":"com.google.android.exoplayer2","c":"C","l":"MSG_SET_CAMERA_MOTION_LISTENER"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"MSG_SET_CAMERA_MOTION_LISTENER"},{"p":"com.google.android.exoplayer2","c":"C","l":"MSG_SET_SCALING_MODE"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"MSG_SET_SCALING_MODE"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"MSG_SET_SKIP_SILENCE_ENABLED"},{"p":"com.google.android.exoplayer2","c":"C","l":"MSG_SET_SURFACE"},{"p":"com.google.android.exoplayer2","c":"C","l":"MSG_SET_VIDEO_FRAME_METADATA_LISTENER"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"MSG_SET_VIDEO_FRAME_METADATA_LISTENER"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"MSG_SET_VIDEO_OUTPUT"},{"p":"com.google.android.exoplayer2","c":"C","l":"MSG_SET_VOLUME"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"MSG_SET_VOLUME"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"MSG_SET_WAKEUP_LISTENER"},{"p":"com.google.android.exoplayer2","c":"C","l":"msToUs(long)"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"multiRowAlignment"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.MultiSegmentBase","l":"MultiSegmentBase(RangedUri, long, long, long, long, List, long, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.dash.manifest.RangedUri,long,long,long,long,java.util.List,long,long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.MultiSegmentRepresentation","l":"MultiSegmentRepresentation(long, Format, List, SegmentBase.MultiSegmentBase, List)","url":"%3Cinit%3E(long,com.google.android.exoplayer2.Format,java.util.List,com.google.android.exoplayer2.source.dash.manifest.SegmentBase.MultiSegmentBase,java.util.List)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.DrmConfiguration","l":"multiSession"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"muxedAudioFormat"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"muxedCaptionFormats"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil","l":"NAL_START_CODE"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"nalUnitLengthFieldLength"},{"p":"com.google.android.exoplayer2.video","c":"AvcConfig","l":"nalUnitLengthFieldLength"},{"p":"com.google.android.exoplayer2.video","c":"HevcConfig","l":"nalUnitLengthFieldLength"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"name"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"name"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry","l":"name"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Rendition","l":"name"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"name"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil.Attribute","l":"name"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil.Uniform","l":"name"},{"p":"com.google.android.exoplayer2","c":"C","l":"NANOS_PER_SECOND"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"needsReconfiguration()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"needsReconfiguration()"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"NETWORK"},{"p":"com.google.android.exoplayer2","c":"C","l":"NETWORK_TYPE_2G"},{"p":"com.google.android.exoplayer2","c":"C","l":"NETWORK_TYPE_3G"},{"p":"com.google.android.exoplayer2","c":"C","l":"NETWORK_TYPE_4G"},{"p":"com.google.android.exoplayer2","c":"C","l":"NETWORK_TYPE_5G_NSA"},{"p":"com.google.android.exoplayer2","c":"C","l":"NETWORK_TYPE_5G_SA"},{"p":"com.google.android.exoplayer2","c":"C","l":"NETWORK_TYPE_CELLULAR_UNKNOWN"},{"p":"com.google.android.exoplayer2","c":"C","l":"NETWORK_TYPE_ETHERNET"},{"p":"com.google.android.exoplayer2","c":"C","l":"NETWORK_TYPE_OFFLINE"},{"p":"com.google.android.exoplayer2","c":"C","l":"NETWORK_TYPE_OTHER"},{"p":"com.google.android.exoplayer2","c":"C","l":"NETWORK_TYPE_UNKNOWN"},{"p":"com.google.android.exoplayer2","c":"C","l":"NETWORK_TYPE_WIFI"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"NETWORK_UNMETERED"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet","l":"newData(String)","url":"newData(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet","l":"newData(Uri)","url":"newData(android.net.Uri)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet","l":"newDefaultData()"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"newFormat"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"newInitializationChunk(DefaultDashChunkSource.RepresentationHolder, DataSource, Format, int, Object, RangedUri, RangedUri)","url":"newInitializationChunk(com.google.android.exoplayer2.source.dash.DefaultDashChunkSource.RepresentationHolder,com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.Format,int,java.lang.Object,com.google.android.exoplayer2.source.dash.manifest.RangedUri,com.google.android.exoplayer2.source.dash.manifest.RangedUri)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"newInstance(long, Format, List, SegmentBase, List, String)","url":"newInstance(long,com.google.android.exoplayer2.Format,java.util.List,com.google.android.exoplayer2.source.dash.manifest.SegmentBase,java.util.List,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"newInstance(long, Format, List, SegmentBase, List)","url":"newInstance(long,com.google.android.exoplayer2.Format,java.util.List,com.google.android.exoplayer2.source.dash.manifest.SegmentBase,java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"newInstance(long, Format, List, SegmentBase)","url":"newInstance(long,com.google.android.exoplayer2.Format,java.util.List,com.google.android.exoplayer2.source.dash.manifest.SegmentBase)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.SingleSegmentRepresentation","l":"newInstance(long, Format, String, long, long, long, long, List, String, long)","url":"newInstance(long,com.google.android.exoplayer2.Format,java.lang.String,long,long,long,long,java.util.List,java.lang.String,long)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"newInstance(String, String, String, MediaCodecInfo.CodecCapabilities, boolean, boolean, boolean, boolean, boolean)","url":"newInstance(java.lang.String,java.lang.String,java.lang.String,android.media.MediaCodecInfo.CodecCapabilities,boolean,boolean,boolean,boolean,boolean)"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"newInstance(UUID)","url":"newInstance(java.util.UUID)"},{"p":"com.google.android.exoplayer2.video","c":"DummySurface","l":"newInstanceV17(Context, boolean)","url":"newInstanceV17(android.content.Context,boolean)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"newMediaChunk(DefaultDashChunkSource.RepresentationHolder, DataSource, int, Format, int, Object, long, int, long, long)","url":"newMediaChunk(com.google.android.exoplayer2.source.dash.DefaultDashChunkSource.RepresentationHolder,com.google.android.exoplayer2.upstream.DataSource,int,com.google.android.exoplayer2.Format,int,java.lang.Object,long,int,long,long)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"newNoDataInstance()"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler","l":"newPlayerTrackEmsgHandler()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"newSingleThreadExecutor(String)","url":"newSingleThreadExecutor(java.lang.String)"},{"p":"com.google.android.exoplayer2.drm","c":"OfflineLicenseHelper","l":"newWidevineInstance(String, boolean, HttpDataSource.Factory, DrmSessionEventListener.EventDispatcher)","url":"newWidevineInstance(java.lang.String,boolean,com.google.android.exoplayer2.upstream.HttpDataSource.Factory,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2.drm","c":"OfflineLicenseHelper","l":"newWidevineInstance(String, boolean, HttpDataSource.Factory, Map, DrmSessionEventListener.EventDispatcher)","url":"newWidevineInstance(java.lang.String,boolean,com.google.android.exoplayer2.upstream.HttpDataSource.Factory,java.util.Map,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2.drm","c":"OfflineLicenseHelper","l":"newWidevineInstance(String, HttpDataSource.Factory, DrmSessionEventListener.EventDispatcher)","url":"newWidevineInstance(java.lang.String,com.google.android.exoplayer2.upstream.HttpDataSource.Factory,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2","c":"SeekParameters","l":"NEXT_SYNC"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"next()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"next()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"next()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunkIterator","l":"next()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaChunkIterator","l":"next()"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"nextAdGroupIndex"},{"p":"com.google.android.exoplayer2.audio","c":"AuxEffectInfo","l":"NO_AUX_EFFECT_ID"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"Id3Decoder","l":"NO_FRAMES_PREDICATE"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.TimestampSearchResult","l":"NO_TIMESTAMP_IN_RANGE_RESULT"},{"p":"com.google.android.exoplayer2","c":"Format","l":"NO_VALUE"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"NONE"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"nonFatalErrorCount"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"nonFatalErrorHistory"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"NoOpCacheEvictor","l":"NoOpCacheEvictor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"normalizeLanguageCode(String)","url":"normalizeLanguageCode(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"normalizeMimeType(String)","url":"normalizeMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"normalizeUndeterminedLanguageToNull(String)","url":"normalizeUndeterminedLanguageToNull(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"NoSampleRenderer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CachedRegionTracker","l":"NOT_CACHED"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"NOT_IN_LOOKUP_TABLE"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor.AudioFormat","l":"NOT_SET"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl","l":"notifyRebuffer()"},{"p":"com.google.android.exoplayer2","c":"LivePlaybackSpeedControl","l":"notifyRebuffer()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"notifySeekStarted()"},{"p":"com.google.android.exoplayer2.testutil","c":"NoUidTimeline","l":"NoUidTimeline(Timeline)","url":"%3Cinit%3E(com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"nullSafeArrayAppend(T[], T)","url":"nullSafeArrayAppend(T[],T)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"nullSafeArrayConcatenation(T[], T[])","url":"nullSafeArrayConcatenation(T[],T[])"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"nullSafeArrayCopy(T[], int)","url":"nullSafeArrayCopy(T[],int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"nullSafeArrayCopyOfRange(T[], int, int)","url":"nullSafeArrayCopyOfRange(T[],int,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"nullSafeListToArray(List, T[])","url":"nullSafeListToArray(java.util.List,T[])"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy.FallbackOptions","l":"numberOfExcludedLocations"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy.FallbackOptions","l":"numberOfExcludedTracks"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy.FallbackOptions","l":"numberOfLocations"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorOutput","l":"numberOfTracks"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy.FallbackOptions","l":"numberOfTracks"},{"p":"com.google.android.exoplayer2.decoder","c":"CryptoInfo","l":"numBytesOfClearData"},{"p":"com.google.android.exoplayer2.decoder","c":"CryptoInfo","l":"numBytesOfEncryptedData"},{"p":"com.google.android.exoplayer2.decoder","c":"CryptoInfo","l":"numSubSamples"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"obtainMessage(int, int, int, Object)","url":"obtainMessage(int,int,int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"obtainMessage(int, int, int)","url":"obtainMessage(int,int,int)"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"obtainMessage(int, Object)","url":"obtainMessage(int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"obtainMessage(int)"},{"p":"com.google.android.exoplayer2.drm","c":"OfflineLicenseHelper","l":"OfflineLicenseHelper(DefaultDrmSessionManager, DrmSessionEventListener.EventDispatcher)","url":"%3Cinit%3E(com.google.android.exoplayer2.drm.DefaultDrmSessionManager,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2.drm","c":"OfflineLicenseHelper","l":"OfflineLicenseHelper(UUID, ExoMediaDrm.Provider, MediaDrmCallback, Map, DrmSessionEventListener.EventDispatcher)","url":"%3Cinit%3E(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm.Provider,com.google.android.exoplayer2.drm.MediaDrmCallback,java.util.Map,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"OFFLOAD_MODE_DISABLED"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"OFFLOAD_MODE_ENABLED_GAPLESS_DISABLED"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"OFFLOAD_MODE_ENABLED_GAPLESS_NOT_REQUIRED"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"OFFLOAD_MODE_ENABLED_GAPLESS_REQUIRED"},{"p":"com.google.android.exoplayer2.upstream","c":"Allocation","l":"offset"},{"p":"com.google.android.exoplayer2","c":"Format","l":"OFFSET_SAMPLE_RELATIVE"},{"p":"com.google.android.exoplayer2.extractor","c":"ChunkIndex","l":"offsets"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"OGG"},{"p":"com.google.android.exoplayer2.extractor.ogg","c":"OggExtractor","l":"OggExtractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"OkHttpDataSource(Call.Factory, String, CacheControl, HttpDataSource.RequestProperties)","url":"%3Cinit%3E(okhttp3.Call.Factory,java.lang.String,okhttp3.CacheControl,com.google.android.exoplayer2.upstream.HttpDataSource.RequestProperties)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"OkHttpDataSource(Call.Factory, String)","url":"%3Cinit%3E(okhttp3.Call.Factory,java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"OkHttpDataSource(Call.Factory)","url":"%3Cinit%3E(okhttp3.Call.Factory)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSourceFactory","l":"OkHttpDataSourceFactory(Call.Factory, String, CacheControl)","url":"%3Cinit%3E(okhttp3.Call.Factory,java.lang.String,okhttp3.CacheControl)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSourceFactory","l":"OkHttpDataSourceFactory(Call.Factory, String, TransferListener, CacheControl)","url":"%3Cinit%3E(okhttp3.Call.Factory,java.lang.String,com.google.android.exoplayer2.upstream.TransferListener,okhttp3.CacheControl)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSourceFactory","l":"OkHttpDataSourceFactory(Call.Factory, String, TransferListener)","url":"%3Cinit%3E(okhttp3.Call.Factory,java.lang.String,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSourceFactory","l":"OkHttpDataSourceFactory(Call.Factory, String)","url":"%3Cinit%3E(okhttp3.Call.Factory,java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSourceFactory","l":"OkHttpDataSourceFactory(Call.Factory)","url":"%3Cinit%3E(okhttp3.Call.Factory)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"oldFormat"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Callback","l":"onActionScheduleFinished()"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"onActionScheduleFinished()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsLoader.EventListener","l":"onAdClicked()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.QueueEditor","l":"onAddQueueItem(Player, MediaDescriptionCompat, int)","url":"onAddQueueItem(com.google.android.exoplayer2.Player,android.support.v4.media.MediaDescriptionCompat,int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor","l":"onAddQueueItem(Player, MediaDescriptionCompat, int)","url":"onAddQueueItem(com.google.android.exoplayer2.Player,android.support.v4.media.MediaDescriptionCompat,int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.QueueEditor","l":"onAddQueueItem(Player, MediaDescriptionCompat)","url":"onAddQueueItem(com.google.android.exoplayer2.Player,android.support.v4.media.MediaDescriptionCompat)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor","l":"onAddQueueItem(Player, MediaDescriptionCompat)","url":"onAddQueueItem(com.google.android.exoplayer2.Player,android.support.v4.media.MediaDescriptionCompat)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsLoader.EventListener","l":"onAdLoadError(AdsMediaSource.AdLoadException, DataSpec)","url":"onAdLoadError(com.google.android.exoplayer2.source.ads.AdsMediaSource.AdLoadException,com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackSessionManager.Listener","l":"onAdPlaybackStarted(AnalyticsListener.EventTime, String, String)","url":"onAdPlaybackStarted(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"onAdPlaybackStarted(AnalyticsListener.EventTime, String, String)","url":"onAdPlaybackStarted(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsLoader.EventListener","l":"onAdPlaybackState(AdPlaybackState)","url":"onAdPlaybackState(com.google.android.exoplayer2.source.ads.AdPlaybackState)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsLoader.EventListener","l":"onAdTapped()"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout.AspectRatioListener","l":"onAspectRatioUpdated(float, float, boolean)","url":"onAspectRatioUpdated(float,float,boolean)"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"onAttachedToHost(PlaybackGlueHost)","url":"onAttachedToHost(androidx.leanback.media.PlaybackGlueHost)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"onAttachedToWindow()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"onAttachedToWindow()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioAttributesChanged(AnalyticsListener.EventTime, AudioAttributes)","url":"onAudioAttributesChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.audio.AudioAttributes)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onAudioAttributesChanged(AnalyticsListener.EventTime, AudioAttributes)","url":"onAudioAttributesChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.audio.AudioAttributes)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onAudioAttributesChanged(AudioAttributes)","url":"onAudioAttributesChanged(com.google.android.exoplayer2.audio.AudioAttributes)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onAudioAttributesChanged(AudioAttributes)","url":"onAudioAttributesChanged(com.google.android.exoplayer2.audio.AudioAttributes)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioListener","l":"onAudioAttributesChanged(AudioAttributes)","url":"onAudioAttributesChanged(com.google.android.exoplayer2.audio.AudioAttributes)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioCapabilitiesReceiver.Listener","l":"onAudioCapabilitiesChanged(AudioCapabilities)","url":"onAudioCapabilitiesChanged(com.google.android.exoplayer2.audio.AudioCapabilities)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioCodecError(AnalyticsListener.EventTime, Exception)","url":"onAudioCodecError(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onAudioCodecError(Exception)","url":"onAudioCodecError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener","l":"onAudioCodecError(Exception)","url":"onAudioCodecError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioDecoderInitialized(AnalyticsListener.EventTime, String, long, long)","url":"onAudioDecoderInitialized(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioDecoderInitialized(AnalyticsListener.EventTime, String, long)","url":"onAudioDecoderInitialized(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String,long)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onAudioDecoderInitialized(AnalyticsListener.EventTime, String, long)","url":"onAudioDecoderInitialized(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onAudioDecoderInitialized(String, long, long)","url":"onAudioDecoderInitialized(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener","l":"onAudioDecoderInitialized(String, long, long)","url":"onAudioDecoderInitialized(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioDecoderReleased(AnalyticsListener.EventTime, String)","url":"onAudioDecoderReleased(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onAudioDecoderReleased(AnalyticsListener.EventTime, String)","url":"onAudioDecoderReleased(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onAudioDecoderReleased(String)","url":"onAudioDecoderReleased(java.lang.String)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener","l":"onAudioDecoderReleased(String)","url":"onAudioDecoderReleased(java.lang.String)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioDisabled(AnalyticsListener.EventTime, DecoderCounters)","url":"onAudioDisabled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"onAudioDisabled(AnalyticsListener.EventTime, DecoderCounters)","url":"onAudioDisabled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onAudioDisabled(AnalyticsListener.EventTime, DecoderCounters)","url":"onAudioDisabled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onAudioDisabled(DecoderCounters)","url":"onAudioDisabled(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener","l":"onAudioDisabled(DecoderCounters)","url":"onAudioDisabled(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioEnabled(AnalyticsListener.EventTime, DecoderCounters)","url":"onAudioEnabled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onAudioEnabled(AnalyticsListener.EventTime, DecoderCounters)","url":"onAudioEnabled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onAudioEnabled(DecoderCounters)","url":"onAudioEnabled(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener","l":"onAudioEnabled(DecoderCounters)","url":"onAudioEnabled(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioInputFormatChanged(AnalyticsListener.EventTime, Format, DecoderReuseEvaluation)","url":"onAudioInputFormatChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.decoder.DecoderReuseEvaluation)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onAudioInputFormatChanged(AnalyticsListener.EventTime, Format, DecoderReuseEvaluation)","url":"onAudioInputFormatChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.decoder.DecoderReuseEvaluation)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioInputFormatChanged(AnalyticsListener.EventTime, Format)","url":"onAudioInputFormatChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onAudioInputFormatChanged(Format, DecoderReuseEvaluation)","url":"onAudioInputFormatChanged(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.decoder.DecoderReuseEvaluation)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener","l":"onAudioInputFormatChanged(Format, DecoderReuseEvaluation)","url":"onAudioInputFormatChanged(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.decoder.DecoderReuseEvaluation)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener","l":"onAudioInputFormatChanged(Format)","url":"onAudioInputFormatChanged(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioPositionAdvancing(AnalyticsListener.EventTime, long)","url":"onAudioPositionAdvancing(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onAudioPositionAdvancing(long)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener","l":"onAudioPositionAdvancing(long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioSessionIdChanged(AnalyticsListener.EventTime, int)","url":"onAudioSessionIdChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onAudioSessionIdChanged(AnalyticsListener.EventTime, int)","url":"onAudioSessionIdChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onAudioSessionIdChanged(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onAudioSessionIdChanged(int)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioListener","l":"onAudioSessionIdChanged(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioSinkError(AnalyticsListener.EventTime, Exception)","url":"onAudioSinkError(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onAudioSinkError(Exception)","url":"onAudioSinkError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener","l":"onAudioSinkError(Exception)","url":"onAudioSinkError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.Listener","l":"onAudioSinkError(Exception)","url":"onAudioSinkError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAudioUnderrun(AnalyticsListener.EventTime, int, long, long)","url":"onAudioUnderrun(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,long,long)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onAudioUnderrun(AnalyticsListener.EventTime, int, long, long)","url":"onAudioUnderrun(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,long,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onAudioUnderrun(int, long, long)","url":"onAudioUnderrun(int,long,long)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener","l":"onAudioUnderrun(int, long, long)","url":"onAudioUnderrun(int,long,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onAvailableCommandsChanged(AnalyticsListener.EventTime, Player.Commands)","url":"onAvailableCommandsChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.Player.Commands)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onAvailableCommandsChanged(Player.Commands)","url":"onAvailableCommandsChanged(com.google.android.exoplayer2.Player.Commands)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onAvailableCommandsChanged(Player.Commands)","url":"onAvailableCommandsChanged(com.google.android.exoplayer2.Player.Commands)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onAvailableCommandsChanged(Player.Commands)","url":"onAvailableCommandsChanged(com.google.android.exoplayer2.Player.Commands)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onBandwidthEstimate(AnalyticsListener.EventTime, int, long, long)","url":"onBandwidthEstimate(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,long,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"onBandwidthEstimate(AnalyticsListener.EventTime, int, long, long)","url":"onBandwidthEstimate(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,long,long)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onBandwidthEstimate(AnalyticsListener.EventTime, int, long, long)","url":"onBandwidthEstimate(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,long,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onBandwidthSample(int, long, long)","url":"onBandwidthSample(int,long,long)"},{"p":"com.google.android.exoplayer2.upstream","c":"BandwidthMeter.EventListener","l":"onBandwidthSample(int, long, long)","url":"onBandwidthSample(int,long,long)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"onBind(Intent)","url":"onBind(android.content.Intent)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.BitmapCallback","l":"onBitmap(Bitmap)","url":"onBitmap(android.graphics.Bitmap)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.FakeTransferListener","l":"onBytesTransferred(DataSource, DataSpec, boolean, int)","url":"onBytesTransferred(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"onBytesTransferred(DataSource, DataSpec, boolean, int)","url":"onBytesTransferred(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"TransferListener","l":"onBytesTransferred(DataSource, DataSpec, boolean, int)","url":"onBytesTransferred(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean,int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.EventListener","l":"onCachedBytesRead(long, long)","url":"onCachedBytesRead(long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.EventListener","l":"onCacheIgnored(int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheEvictor","l":"onCacheInitialized()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"LeastRecentlyUsedCacheEvictor","l":"onCacheInitialized()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"NoOpCacheEvictor","l":"onCacheInitialized()"},{"p":"com.google.android.exoplayer2.video.spherical","c":"CameraMotionListener","l":"onCameraMotion(long, float[])","url":"onCameraMotion(long,float[])"},{"p":"com.google.android.exoplayer2.video.spherical","c":"CameraMotionListener","l":"onCameraMotionReset()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"SessionAvailabilityListener","l":"onCastSessionAvailable()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"SessionAvailabilityListener","l":"onCastSessionUnavailable()"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"onChildSourceInfoRefreshed(ConcatenatingMediaSource.MediaSourceHolder, MediaSource, Timeline)","url":"onChildSourceInfoRefreshed(com.google.android.exoplayer2.source.ConcatenatingMediaSource.MediaSourceHolder,com.google.android.exoplayer2.source.MediaSource,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"onChildSourceInfoRefreshed(Integer, MediaSource, Timeline)","url":"onChildSourceInfoRefreshed(java.lang.Integer,com.google.android.exoplayer2.source.MediaSource,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource","l":"onChildSourceInfoRefreshed(MediaSource.MediaPeriodId, MediaSource, Timeline)","url":"onChildSourceInfoRefreshed(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.MediaSource,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"onChildSourceInfoRefreshed(T, MediaSource, Timeline)","url":"onChildSourceInfoRefreshed(T,com.google.android.exoplayer2.source.MediaSource,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource","l":"onChildSourceInfoRefreshed(Void, MediaSource, Timeline)","url":"onChildSourceInfoRefreshed(java.lang.Void,com.google.android.exoplayer2.source.MediaSource,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.source","c":"LoopingMediaSource","l":"onChildSourceInfoRefreshed(Void, MediaSource, Timeline)","url":"onChildSourceInfoRefreshed(java.lang.Void,com.google.android.exoplayer2.source.MediaSource,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource","l":"onChildSourceInfoRefreshed(Void, MediaSource, Timeline)","url":"onChildSourceInfoRefreshed(java.lang.Void,com.google.android.exoplayer2.source.MediaSource,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSource","l":"onChunkLoadCompleted(Chunk)","url":"onChunkLoadCompleted(com.google.android.exoplayer2.source.chunk.Chunk)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"onChunkLoadCompleted(Chunk)","url":"onChunkLoadCompleted(com.google.android.exoplayer2.source.chunk.Chunk)"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler.PlayerTrackEmsgHandler","l":"onChunkLoadCompleted(Chunk)","url":"onChunkLoadCompleted(com.google.android.exoplayer2.source.chunk.Chunk)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource","l":"onChunkLoadCompleted(Chunk)","url":"onChunkLoadCompleted(com.google.android.exoplayer2.source.chunk.Chunk)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource","l":"onChunkLoadCompleted(Chunk)","url":"onChunkLoadCompleted(com.google.android.exoplayer2.source.chunk.Chunk)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSource","l":"onChunkLoadError(Chunk, boolean, LoadErrorHandlingPolicy.LoadErrorInfo, LoadErrorHandlingPolicy)","url":"onChunkLoadError(com.google.android.exoplayer2.source.chunk.Chunk,boolean,com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.LoadErrorInfo,com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"onChunkLoadError(Chunk, boolean, LoadErrorHandlingPolicy.LoadErrorInfo, LoadErrorHandlingPolicy)","url":"onChunkLoadError(com.google.android.exoplayer2.source.chunk.Chunk,boolean,com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.LoadErrorInfo,com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource","l":"onChunkLoadError(Chunk, boolean, LoadErrorHandlingPolicy.LoadErrorInfo, LoadErrorHandlingPolicy)","url":"onChunkLoadError(com.google.android.exoplayer2.source.chunk.Chunk,boolean,com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.LoadErrorInfo,com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource","l":"onChunkLoadError(Chunk, boolean, LoadErrorHandlingPolicy.LoadErrorInfo, LoadErrorHandlingPolicy)","url":"onChunkLoadError(com.google.android.exoplayer2.source.chunk.Chunk,boolean,com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.LoadErrorInfo,com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy)"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler.PlayerTrackEmsgHandler","l":"onChunkLoadError(Chunk)","url":"onChunkLoadError(com.google.android.exoplayer2.source.chunk.Chunk)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource","l":"onClosed()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onCodecError(Exception)","url":"onCodecError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onCodecError(Exception)","url":"onCodecError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onCodecError(Exception)","url":"onCodecError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onCodecInitialized(String, long, long)","url":"onCodecInitialized(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onCodecInitialized(String, long, long)","url":"onCodecInitialized(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onCodecInitialized(String, long, long)","url":"onCodecInitialized(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onCodecReleased(String)","url":"onCodecReleased(java.lang.String)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onCodecReleased(String)","url":"onCodecReleased(java.lang.String)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onCodecReleased(String)","url":"onCodecReleased(java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.CommandReceiver","l":"onCommand(Player, ControlDispatcher, String, Bundle, ResultReceiver)","url":"onCommand(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ControlDispatcher,java.lang.String,android.os.Bundle,android.os.ResultReceiver)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor","l":"onCommand(Player, ControlDispatcher, String, Bundle, ResultReceiver)","url":"onCommand(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ControlDispatcher,java.lang.String,android.os.Bundle,android.os.ResultReceiver)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueNavigator","l":"onCommand(Player, ControlDispatcher, String, Bundle, ResultReceiver)","url":"onCommand(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ControlDispatcher,java.lang.String,android.os.Bundle,android.os.ResultReceiver)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.AllowedCommandProvider","l":"onCommandRequest(MediaSession, MediaSession.ControllerInfo, SessionCommand)","url":"onCommandRequest(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo,androidx.media2.session.SessionCommand)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.DefaultAllowedCommandProvider","l":"onCommandRequest(MediaSession, MediaSession.ControllerInfo, SessionCommand)","url":"onCommandRequest(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo,androidx.media2.session.SessionCommand)"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"onConfigure(AudioProcessor.AudioFormat)","url":"onConfigure(com.google.android.exoplayer2.audio.AudioProcessor.AudioFormat)"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"onConfigure(AudioProcessor.AudioFormat)","url":"onConfigure(com.google.android.exoplayer2.audio.AudioProcessor.AudioFormat)"},{"p":"com.google.android.exoplayer2.audio","c":"TeeAudioProcessor","l":"onConfigure(AudioProcessor.AudioFormat)","url":"onConfigure(com.google.android.exoplayer2.audio.AudioProcessor.AudioFormat)"},{"p":"com.google.android.exoplayer2.robolectric","c":"RandomizedMp3Decoder","l":"onConfigured(MediaFormat, Surface, MediaCrypto, int)","url":"onConfigured(android.media.MediaFormat,android.view.Surface,android.media.MediaCrypto,int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"onContentAspectRatioChanged(AspectRatioFrameLayout, float)","url":"onContentAspectRatioChanged(com.google.android.exoplayer2.ui.AspectRatioFrameLayout,float)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"onContentAspectRatioChanged(AspectRatioFrameLayout, float)","url":"onContentAspectRatioChanged(com.google.android.exoplayer2.ui.AspectRatioFrameLayout,float)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"onContinueLoadingRequested(ChunkSampleStream)","url":"onContinueLoadingRequested(com.google.android.exoplayer2.source.chunk.ChunkSampleStream)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"onContinueLoadingRequested(HlsSampleStreamWrapper)","url":"onContinueLoadingRequested(com.google.android.exoplayer2.source.hls.HlsSampleStreamWrapper)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"onContinueLoadingRequested(MediaPeriod)","url":"onContinueLoadingRequested(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"onContinueLoadingRequested(MediaPeriod)","url":"onContinueLoadingRequested(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source","c":"SequenceableLoader.Callback","l":"onContinueLoadingRequested(T)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"onCreate()"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity","l":"onCreate(Bundle)","url":"onCreate(android.os.Bundle)"},{"p":"com.google.android.exoplayer2.database","c":"ExoDatabaseProvider","l":"onCreate(SQLiteDatabase)","url":"onCreate(android.database.sqlite.SQLiteDatabase)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.MediaIdMediaItemProvider","l":"onCreateMediaItem(MediaSession, MediaSession.ControllerInfo, String)","url":"onCreateMediaItem(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo,java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.MediaItemProvider","l":"onCreateMediaItem(MediaSession, MediaSession.ControllerInfo, String)","url":"onCreateMediaItem(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onCues(List)","url":"onCues(java.util.List)"},{"p":"com.google.android.exoplayer2.text","c":"TextOutput","l":"onCues(List)","url":"onCues(java.util.List)"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"onCues(List)","url":"onCues(java.util.List)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.QueueNavigator","l":"onCurrentWindowIndexChanged(Player)","url":"onCurrentWindowIndexChanged(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueNavigator","l":"onCurrentWindowIndexChanged(Player)","url":"onCurrentWindowIndexChanged(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.CustomActionProvider","l":"onCustomAction(Player, ControlDispatcher, String, Bundle)","url":"onCustomAction(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ControlDispatcher,java.lang.String,android.os.Bundle)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"RepeatModeActionProvider","l":"onCustomAction(Player, ControlDispatcher, String, Bundle)","url":"onCustomAction(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ControlDispatcher,java.lang.String,android.os.Bundle)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.CustomActionReceiver","l":"onCustomAction(Player, String, Intent)","url":"onCustomAction(com.google.android.exoplayer2.Player,java.lang.String,android.content.Intent)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.CustomCommandProvider","l":"onCustomCommand(MediaSession, MediaSession.ControllerInfo, SessionCommand, Bundle)","url":"onCustomCommand(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo,androidx.media2.session.SessionCommand,android.os.Bundle)"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler.PlayerEmsgCallback","l":"onDashManifestPublishTimeExpired(long)"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler.PlayerEmsgCallback","l":"onDashManifestRefreshRequested()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource","l":"onDataRead(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDecoderDisabled(AnalyticsListener.EventTime, int, DecoderCounters)","url":"onDecoderDisabled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDecoderEnabled(AnalyticsListener.EventTime, int, DecoderCounters)","url":"onDecoderEnabled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDecoderInitialized(AnalyticsListener.EventTime, int, String, long)","url":"onDecoderInitialized(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,java.lang.String,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDecoderInputFormatChanged(AnalyticsListener.EventTime, int, Format)","url":"onDecoderInputFormatChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"onDestroy()"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"onDetachedFromHost()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"onDetachedFromWindow()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"onDetachedFromWindow()"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView","l":"onDetachedFromWindow()"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onDeviceInfoChanged(DeviceInfo)","url":"onDeviceInfoChanged(com.google.android.exoplayer2.device.DeviceInfo)"},{"p":"com.google.android.exoplayer2.device","c":"DeviceListener","l":"onDeviceInfoChanged(DeviceInfo)","url":"onDeviceInfoChanged(com.google.android.exoplayer2.device.DeviceInfo)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onDeviceVolumeChanged(int, boolean)","url":"onDeviceVolumeChanged(int,boolean)"},{"p":"com.google.android.exoplayer2.device","c":"DeviceListener","l":"onDeviceVolumeChanged(int, boolean)","url":"onDeviceVolumeChanged(int,boolean)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAudioRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeVideoRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.text","c":"TextRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.video","c":"VideoFrameReleaseHelper","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.video.spherical","c":"CameraMotionRenderer","l":"onDisabled()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.DisconnectedCallback","l":"onDisconnected(MediaSession, MediaSession.ControllerInfo)","url":"onDisconnected(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo)"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"onDiscontinuity()"},{"p":"com.google.android.exoplayer2.database","c":"ExoDatabaseProvider","l":"onDowngrade(SQLiteDatabase, int, int)","url":"onDowngrade(android.database.sqlite.SQLiteDatabase,int,int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"onDownloadChanged(Download)","url":"onDownloadChanged(com.google.android.exoplayer2.offline.Download)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager.Listener","l":"onDownloadChanged(DownloadManager, Download, Exception)","url":"onDownloadChanged(com.google.android.exoplayer2.offline.DownloadManager,com.google.android.exoplayer2.offline.Download,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestDownloadManagerListener","l":"onDownloadChanged(DownloadManager, Download, Exception)","url":"onDownloadChanged(com.google.android.exoplayer2.offline.DownloadManager,com.google.android.exoplayer2.offline.Download,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"onDownloadRemoved(Download)","url":"onDownloadRemoved(com.google.android.exoplayer2.offline.Download)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager.Listener","l":"onDownloadRemoved(DownloadManager, Download)","url":"onDownloadRemoved(com.google.android.exoplayer2.offline.DownloadManager,com.google.android.exoplayer2.offline.Download)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestDownloadManagerListener","l":"onDownloadRemoved(DownloadManager, Download)","url":"onDownloadRemoved(com.google.android.exoplayer2.offline.DownloadManager,com.google.android.exoplayer2.offline.Download)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager.Listener","l":"onDownloadsPausedChanged(DownloadManager, boolean)","url":"onDownloadsPausedChanged(com.google.android.exoplayer2.offline.DownloadManager,boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDownstreamFormatChanged(AnalyticsListener.EventTime, MediaLoadData)","url":"onDownstreamFormatChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"onDownstreamFormatChanged(AnalyticsListener.EventTime, MediaLoadData)","url":"onDownstreamFormatChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onDownstreamFormatChanged(AnalyticsListener.EventTime, MediaLoadData)","url":"onDownstreamFormatChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onDownstreamFormatChanged(int, MediaSource.MediaPeriodId, MediaLoadData)","url":"onDownstreamFormatChanged(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener","l":"onDownstreamFormatChanged(int, MediaSource.MediaPeriodId, MediaLoadData)","url":"onDownstreamFormatChanged(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsMediaSource","l":"onDownstreamFormatChanged(int, MediaSource.MediaPeriodId, MediaLoadData)","url":"onDownstreamFormatChanged(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"onDraw(Canvas)","url":"onDraw(android.graphics.Canvas)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDrmKeysLoaded(AnalyticsListener.EventTime)","url":"onDrmKeysLoaded(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onDrmKeysLoaded(AnalyticsListener.EventTime)","url":"onDrmKeysLoaded(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onDrmKeysLoaded(int, MediaSource.MediaPeriodId)","url":"onDrmKeysLoaded(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener","l":"onDrmKeysLoaded(int, MediaSource.MediaPeriodId)","url":"onDrmKeysLoaded(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsMediaSource","l":"onDrmKeysLoaded(int, MediaSource.MediaPeriodId)","url":"onDrmKeysLoaded(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDrmKeysRemoved(AnalyticsListener.EventTime)","url":"onDrmKeysRemoved(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onDrmKeysRemoved(AnalyticsListener.EventTime)","url":"onDrmKeysRemoved(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onDrmKeysRemoved(int, MediaSource.MediaPeriodId)","url":"onDrmKeysRemoved(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener","l":"onDrmKeysRemoved(int, MediaSource.MediaPeriodId)","url":"onDrmKeysRemoved(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsMediaSource","l":"onDrmKeysRemoved(int, MediaSource.MediaPeriodId)","url":"onDrmKeysRemoved(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDrmKeysRestored(AnalyticsListener.EventTime)","url":"onDrmKeysRestored(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onDrmKeysRestored(AnalyticsListener.EventTime)","url":"onDrmKeysRestored(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onDrmKeysRestored(int, MediaSource.MediaPeriodId)","url":"onDrmKeysRestored(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener","l":"onDrmKeysRestored(int, MediaSource.MediaPeriodId)","url":"onDrmKeysRestored(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsMediaSource","l":"onDrmKeysRestored(int, MediaSource.MediaPeriodId)","url":"onDrmKeysRestored(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDrmSessionAcquired(AnalyticsListener.EventTime, int)","url":"onDrmSessionAcquired(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onDrmSessionAcquired(AnalyticsListener.EventTime, int)","url":"onDrmSessionAcquired(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDrmSessionAcquired(AnalyticsListener.EventTime)","url":"onDrmSessionAcquired(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onDrmSessionAcquired(int, MediaSource.MediaPeriodId, int)","url":"onDrmSessionAcquired(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,int)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener","l":"onDrmSessionAcquired(int, MediaSource.MediaPeriodId, int)","url":"onDrmSessionAcquired(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsMediaSource","l":"onDrmSessionAcquired(int, MediaSource.MediaPeriodId, int)","url":"onDrmSessionAcquired(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,int)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener","l":"onDrmSessionAcquired(int, MediaSource.MediaPeriodId)","url":"onDrmSessionAcquired(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDrmSessionManagerError(AnalyticsListener.EventTime, Exception)","url":"onDrmSessionManagerError(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"onDrmSessionManagerError(AnalyticsListener.EventTime, Exception)","url":"onDrmSessionManagerError(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onDrmSessionManagerError(AnalyticsListener.EventTime, Exception)","url":"onDrmSessionManagerError(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onDrmSessionManagerError(int, MediaSource.MediaPeriodId, Exception)","url":"onDrmSessionManagerError(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener","l":"onDrmSessionManagerError(int, MediaSource.MediaPeriodId, Exception)","url":"onDrmSessionManagerError(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsMediaSource","l":"onDrmSessionManagerError(int, MediaSource.MediaPeriodId, Exception)","url":"onDrmSessionManagerError(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDrmSessionReleased(AnalyticsListener.EventTime)","url":"onDrmSessionReleased(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onDrmSessionReleased(AnalyticsListener.EventTime)","url":"onDrmSessionReleased(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onDrmSessionReleased(int, MediaSource.MediaPeriodId)","url":"onDrmSessionReleased(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener","l":"onDrmSessionReleased(int, MediaSource.MediaPeriodId)","url":"onDrmSessionReleased(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsMediaSource","l":"onDrmSessionReleased(int, MediaSource.MediaPeriodId)","url":"onDrmSessionReleased(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onDroppedFrames(int, long)","url":"onDroppedFrames(int,long)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener","l":"onDroppedFrames(int, long)","url":"onDroppedFrames(int,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onDroppedVideoFrames(AnalyticsListener.EventTime, int, long)","url":"onDroppedVideoFrames(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"onDroppedVideoFrames(AnalyticsListener.EventTime, int, long)","url":"onDroppedVideoFrames(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,long)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onDroppedVideoFrames(AnalyticsListener.EventTime, int, long)","url":"onDroppedVideoFrames(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream.FakeSampleStreamItem","l":"oneByteSample(long, int)","url":"oneByteSample(long,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream.FakeSampleStreamItem","l":"oneByteSample(long)"},{"p":"com.google.android.exoplayer2.video","c":"VideoFrameReleaseHelper","l":"onEnabled()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"onEnabled(boolean, boolean)","url":"onEnabled(boolean,boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"onEnabled(boolean, boolean)","url":"onEnabled(boolean,boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onEnabled(boolean, boolean)","url":"onEnabled(boolean,boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onEnabled(boolean, boolean)","url":"onEnabled(boolean,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAudioRenderer","l":"onEnabled(boolean, boolean)","url":"onEnabled(boolean,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeVideoRenderer","l":"onEnabled(boolean, boolean)","url":"onEnabled(boolean,boolean)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"onEnabled(boolean, boolean)","url":"onEnabled(boolean,boolean)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onEnabled(boolean, boolean)","url":"onEnabled(boolean,boolean)"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"onEnabled(boolean)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.OnEventListener","l":"onEvent(ExoMediaDrm, byte[], int, int, byte[])","url":"onEvent(com.google.android.exoplayer2.drm.ExoMediaDrm,byte[],int,int,byte[])"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onEvents(Player, AnalyticsListener.Events)","url":"onEvents(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.analytics.AnalyticsListener.Events)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"onEvents(Player, AnalyticsListener.Events)","url":"onEvents(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.analytics.AnalyticsListener.Events)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"onEvents(Player, AnalyticsListener.Events)","url":"onEvents(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.analytics.AnalyticsListener.Events)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onEvents(Player, Player.Events)","url":"onEvents(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.Player.Events)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onEvents(Player, Player.Events)","url":"onEvents(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.Player.Events)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioOffloadListener","l":"onExperimentalOffloadSchedulingEnabledChanged(boolean)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioOffloadListener","l":"onExperimentalSleepingForOffloadChanged(boolean)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.OnExpirationUpdateListener","l":"onExpirationUpdate(ExoMediaDrm, byte[], long)","url":"onExpirationUpdate(com.google.android.exoplayer2.drm.ExoMediaDrm,byte[],long)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"onFinished()"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity.HostedTest","l":"onFinished()"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"onFlush()"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"onFlush()"},{"p":"com.google.android.exoplayer2.audio","c":"TeeAudioProcessor","l":"onFlush()"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"onFocusChanged(boolean, int, Rect)","url":"onFocusChanged(boolean,int,android.graphics.Rect)"},{"p":"com.google.android.exoplayer2.video","c":"VideoFrameReleaseHelper","l":"onFormatChanged(float)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAudioRenderer","l":"onFormatChanged(Format)","url":"onFormatChanged(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"onFormatChanged(Format)","url":"onFormatChanged(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeVideoRenderer","l":"onFormatChanged(Format)","url":"onFormatChanged(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.util","c":"EGLSurfaceTexture.TextureImageListener","l":"onFrameAvailable()"},{"p":"com.google.android.exoplayer2.util","c":"EGLSurfaceTexture","l":"onFrameAvailable(SurfaceTexture)","url":"onFrameAvailable(android.graphics.SurfaceTexture)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter.OnFrameRenderedListener","l":"onFrameRendered(MediaCodecAdapter, long, long)","url":"onFrameRendered(com.google.android.exoplayer2.mediacodec.MediaCodecAdapter,long,long)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView.OnFullScreenModeChangedListener","l":"onFullScreenModeChanged(boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager.Listener","l":"onIdle(DownloadManager)","url":"onIdle(com.google.android.exoplayer2.offline.DownloadManager)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestDownloadManagerListener","l":"onIdle(DownloadManager)","url":"onIdle(com.google.android.exoplayer2.offline.DownloadManager)"},{"p":"com.google.android.exoplayer2.util","c":"SntpClient.InitializationCallback","l":"onInitializationFailed(IOException)","url":"onInitializationFailed(java.io.IOException)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"onInitializeAccessibilityEvent(AccessibilityEvent)","url":"onInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)","url":"onInitializeAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo)"},{"p":"com.google.android.exoplayer2.util","c":"SntpClient.InitializationCallback","l":"onInitialized()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager.Listener","l":"onInitialized(DownloadManager)","url":"onInitialized(com.google.android.exoplayer2.offline.DownloadManager)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestDownloadManagerListener","l":"onInitialized(DownloadManager)","url":"onInitialized(com.google.android.exoplayer2.offline.DownloadManager)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onInputFormatChanged(FormatHolder)","url":"onInputFormatChanged(com.google.android.exoplayer2.FormatHolder)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onInputFormatChanged(FormatHolder)","url":"onInputFormatChanged(com.google.android.exoplayer2.FormatHolder)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"onInputFormatChanged(FormatHolder)","url":"onInputFormatChanged(com.google.android.exoplayer2.FormatHolder)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onInputFormatChanged(FormatHolder)","url":"onInputFormatChanged(com.google.android.exoplayer2.FormatHolder)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onIsLoadingChanged(AnalyticsListener.EventTime, boolean)","url":"onIsLoadingChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onIsLoadingChanged(AnalyticsListener.EventTime, boolean)","url":"onIsLoadingChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,boolean)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onIsLoadingChanged(boolean)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onIsLoadingChanged(boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onIsLoadingChanged(boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onIsPlayingChanged(AnalyticsListener.EventTime, boolean)","url":"onIsPlayingChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onIsPlayingChanged(AnalyticsListener.EventTime, boolean)","url":"onIsPlayingChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,boolean)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onIsPlayingChanged(boolean)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onIsPlayingChanged(boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onIsPlayingChanged(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"onKeyDown(int, KeyEvent)","url":"onKeyDown(int,android.view.KeyEvent)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.OnKeyStatusChangeListener","l":"onKeyStatusChange(ExoMediaDrm, byte[], List, boolean)","url":"onKeyStatusChange(com.google.android.exoplayer2.drm.ExoMediaDrm,byte[],java.util.List,boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"onLayout(boolean, int, int, int, int)","url":"onLayout(boolean,int,int,int,int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"onLayout(boolean, int, int, int, int)","url":"onLayout(boolean,int,int,int,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onLoadCanceled(AnalyticsListener.EventTime, LoadEventInfo, MediaLoadData)","url":"onLoadCanceled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onLoadCanceled(AnalyticsListener.EventTime, LoadEventInfo, MediaLoadData)","url":"onLoadCanceled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"onLoadCanceled(Chunk, long, long, boolean)","url":"onLoadCanceled(com.google.android.exoplayer2.source.chunk.Chunk,long,long,boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onLoadCanceled(int, MediaSource.MediaPeriodId, LoadEventInfo, MediaLoadData)","url":"onLoadCanceled(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener","l":"onLoadCanceled(int, MediaSource.MediaPeriodId, LoadEventInfo, MediaLoadData)","url":"onLoadCanceled(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsMediaSource","l":"onLoadCanceled(int, MediaSource.MediaPeriodId, LoadEventInfo, MediaLoadData)","url":"onLoadCanceled(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"onLoadCanceled(ParsingLoadable, long, long, boolean)","url":"onLoadCanceled(com.google.android.exoplayer2.upstream.ParsingLoadable,long,long,boolean)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource","l":"onLoadCanceled(ParsingLoadable, long, long, boolean)","url":"onLoadCanceled(com.google.android.exoplayer2.upstream.ParsingLoadable,long,long,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader.Callback","l":"onLoadCanceled(T, long, long, boolean)","url":"onLoadCanceled(T,long,long,boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onLoadCompleted(AnalyticsListener.EventTime, LoadEventInfo, MediaLoadData)","url":"onLoadCompleted(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onLoadCompleted(AnalyticsListener.EventTime, LoadEventInfo, MediaLoadData)","url":"onLoadCompleted(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"onLoadCompleted(Chunk, long, long)","url":"onLoadCompleted(com.google.android.exoplayer2.source.chunk.Chunk,long,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onLoadCompleted(int, MediaSource.MediaPeriodId, LoadEventInfo, MediaLoadData)","url":"onLoadCompleted(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener","l":"onLoadCompleted(int, MediaSource.MediaPeriodId, LoadEventInfo, MediaLoadData)","url":"onLoadCompleted(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsMediaSource","l":"onLoadCompleted(int, MediaSource.MediaPeriodId, LoadEventInfo, MediaLoadData)","url":"onLoadCompleted(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"onLoadCompleted(ParsingLoadable, long, long)","url":"onLoadCompleted(com.google.android.exoplayer2.upstream.ParsingLoadable,long,long)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource","l":"onLoadCompleted(ParsingLoadable, long, long)","url":"onLoadCompleted(com.google.android.exoplayer2.upstream.ParsingLoadable,long,long)"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader.Callback","l":"onLoadCompleted(T, long, long)","url":"onLoadCompleted(T,long,long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"onLoaderReleased()"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader.ReleaseCallback","l":"onLoaderReleased()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onLoadError(AnalyticsListener.EventTime, LoadEventInfo, MediaLoadData, IOException, boolean)","url":"onLoadError(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData,java.io.IOException,boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"onLoadError(AnalyticsListener.EventTime, LoadEventInfo, MediaLoadData, IOException, boolean)","url":"onLoadError(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData,java.io.IOException,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onLoadError(AnalyticsListener.EventTime, LoadEventInfo, MediaLoadData, IOException, boolean)","url":"onLoadError(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData,java.io.IOException,boolean)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"onLoadError(Chunk, long, long, IOException, int)","url":"onLoadError(com.google.android.exoplayer2.source.chunk.Chunk,long,long,java.io.IOException,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onLoadError(int, MediaSource.MediaPeriodId, LoadEventInfo, MediaLoadData, IOException, boolean)","url":"onLoadError(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData,java.io.IOException,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener","l":"onLoadError(int, MediaSource.MediaPeriodId, LoadEventInfo, MediaLoadData, IOException, boolean)","url":"onLoadError(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData,java.io.IOException,boolean)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsMediaSource","l":"onLoadError(int, MediaSource.MediaPeriodId, LoadEventInfo, MediaLoadData, IOException, boolean)","url":"onLoadError(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData,java.io.IOException,boolean)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"onLoadError(ParsingLoadable, long, long, IOException, int)","url":"onLoadError(com.google.android.exoplayer2.upstream.ParsingLoadable,long,long,java.io.IOException,int)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource","l":"onLoadError(ParsingLoadable, long, long, IOException, int)","url":"onLoadError(com.google.android.exoplayer2.upstream.ParsingLoadable,long,long,java.io.IOException,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader.Callback","l":"onLoadError(T, long, long, IOException, int)","url":"onLoadError(T,long,long,java.io.IOException,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onLoadingChanged(AnalyticsListener.EventTime, boolean)","url":"onLoadingChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,boolean)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onLoadingChanged(boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onLoadStarted(AnalyticsListener.EventTime, LoadEventInfo, MediaLoadData)","url":"onLoadStarted(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onLoadStarted(AnalyticsListener.EventTime, LoadEventInfo, MediaLoadData)","url":"onLoadStarted(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onLoadStarted(int, MediaSource.MediaPeriodId, LoadEventInfo, MediaLoadData)","url":"onLoadStarted(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener","l":"onLoadStarted(int, MediaSource.MediaPeriodId, LoadEventInfo, MediaLoadData)","url":"onLoadStarted(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsMediaSource","l":"onLoadStarted(int, MediaSource.MediaPeriodId, LoadEventInfo, MediaLoadData)","url":"onLoadStarted(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.LoadEventInfo,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy","l":"onLoadTaskConcluded(long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onMaxSeekToPreviousPositionChanged(AnalyticsListener.EventTime, int)","url":"onMaxSeekToPreviousPositionChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onMaxSeekToPreviousPositionChanged(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onMaxSeekToPreviousPositionChanged(int)"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout","l":"onMeasure(int, int)","url":"onMeasure(int,int)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"onMeasure(int, int)","url":"onMeasure(int,int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.MediaButtonEventHandler","l":"onMediaButtonEvent(Player, ControlDispatcher, Intent)","url":"onMediaButtonEvent(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ControlDispatcher,android.content.Intent)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onMediaItemTransition(AnalyticsListener.EventTime, MediaItem, int)","url":"onMediaItemTransition(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.MediaItem,int)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onMediaItemTransition(AnalyticsListener.EventTime, MediaItem, int)","url":"onMediaItemTransition(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.MediaItem,int)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onMediaItemTransition(MediaItem, int)","url":"onMediaItemTransition(com.google.android.exoplayer2.MediaItem,int)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onMediaItemTransition(MediaItem, int)","url":"onMediaItemTransition(com.google.android.exoplayer2.MediaItem,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onMediaItemTransition(MediaItem, int)","url":"onMediaItemTransition(com.google.android.exoplayer2.MediaItem,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"onMediaItemTransition(MediaItem, int)","url":"onMediaItemTransition(com.google.android.exoplayer2.MediaItem,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onMediaMetadataChanged(AnalyticsListener.EventTime, MediaMetadata)","url":"onMediaMetadataChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.MediaMetadata)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onMediaMetadataChanged(MediaMetadata)","url":"onMediaMetadataChanged(com.google.android.exoplayer2.MediaMetadata)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onMediaMetadataChanged(MediaMetadata)","url":"onMediaMetadataChanged(com.google.android.exoplayer2.MediaMetadata)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onMediaMetadataChanged(MediaMetadata)","url":"onMediaMetadataChanged(com.google.android.exoplayer2.MediaMetadata)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.PlayerTarget.Callback","l":"onMessageArrived()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onMetadata(AnalyticsListener.EventTime, Metadata)","url":"onMetadata(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onMetadata(AnalyticsListener.EventTime, Metadata)","url":"onMetadata(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onMetadata(Metadata)","url":"onMetadata(com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onMetadata(Metadata)","url":"onMetadata(com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataOutput","l":"onMetadata(Metadata)","url":"onMetadata(com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2.util","c":"NetworkTypeObserver.Listener","l":"onNetworkTypeChanged(int)"},{"p":"com.google.android.exoplayer2.video","c":"VideoFrameReleaseHelper","l":"onNextFrame(long)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.NotificationListener","l":"onNotificationCancelled(int, boolean)","url":"onNotificationCancelled(int,boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.NotificationListener","l":"onNotificationPosted(int, Notification, boolean)","url":"onNotificationPosted(int,android.app.Notification,boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.Listener","l":"onOffloadBufferEmptying()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.Listener","l":"onOffloadBufferFull(long)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onOutputFormatChanged(Format, MediaFormat)","url":"onOutputFormatChanged(com.google.android.exoplayer2.Format,android.media.MediaFormat)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onOutputFormatChanged(Format, MediaFormat)","url":"onOutputFormatChanged(com.google.android.exoplayer2.Format,android.media.MediaFormat)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onOutputFormatChanged(Format, MediaFormat)","url":"onOutputFormatChanged(com.google.android.exoplayer2.Format,android.media.MediaFormat)"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity","l":"onPause()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"onPause()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"onPause()"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView","l":"onPause()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onPlaybackParametersChanged(AnalyticsListener.EventTime, PlaybackParameters)","url":"onPlaybackParametersChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onPlaybackParametersChanged(AnalyticsListener.EventTime, PlaybackParameters)","url":"onPlaybackParametersChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onPlaybackParametersChanged(PlaybackParameters)","url":"onPlaybackParametersChanged(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onPlaybackParametersChanged(PlaybackParameters)","url":"onPlaybackParametersChanged(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onPlaybackParametersChanged(PlaybackParameters)","url":"onPlaybackParametersChanged(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"onPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"onPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"onPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"onPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2.video","c":"VideoFrameReleaseHelper","l":"onPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onPlaybackStateChanged(AnalyticsListener.EventTime, int)","url":"onPlaybackStateChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onPlaybackStateChanged(AnalyticsListener.EventTime, int)","url":"onPlaybackStateChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onPlaybackStateChanged(int)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onPlaybackStateChanged(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onPlaybackStateChanged(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"onPlaybackStateChanged(int)"},{"p":"com.google.android.exoplayer2.util","c":"DebugTextViewHelper","l":"onPlaybackStateChanged(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener.Callback","l":"onPlaybackStatsReady(AnalyticsListener.EventTime, PlaybackStats)","url":"onPlaybackStatsReady(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.analytics.PlaybackStats)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onPlaybackSuppressionReasonChanged(AnalyticsListener.EventTime, int)","url":"onPlaybackSuppressionReasonChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onPlaybackSuppressionReasonChanged(AnalyticsListener.EventTime, int)","url":"onPlaybackSuppressionReasonChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onPlaybackSuppressionReasonChanged(int)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onPlaybackSuppressionReasonChanged(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onPlaybackSuppressionReasonChanged(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onPlayerError(AnalyticsListener.EventTime, PlaybackException)","url":"onPlayerError(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.PlaybackException)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onPlayerError(AnalyticsListener.EventTime, PlaybackException)","url":"onPlayerError(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.PlaybackException)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onPlayerError(PlaybackException)","url":"onPlayerError(com.google.android.exoplayer2.PlaybackException)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onPlayerError(PlaybackException)","url":"onPlayerError(com.google.android.exoplayer2.PlaybackException)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onPlayerError(PlaybackException)","url":"onPlayerError(com.google.android.exoplayer2.PlaybackException)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"onPlayerError(PlaybackException)","url":"onPlayerError(com.google.android.exoplayer2.PlaybackException)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onPlayerErrorChanged(PlaybackException)","url":"onPlayerErrorChanged(com.google.android.exoplayer2.PlaybackException)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onPlayerErrorChanged(PlaybackException)","url":"onPlayerErrorChanged(com.google.android.exoplayer2.PlaybackException)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"onPlayerErrorInternal(ExoPlaybackException)","url":"onPlayerErrorInternal(com.google.android.exoplayer2.ExoPlaybackException)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onPlayerReleased(AnalyticsListener.EventTime)","url":"onPlayerReleased(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onPlayerStateChanged(AnalyticsListener.EventTime, boolean, int)","url":"onPlayerStateChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,boolean,int)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onPlayerStateChanged(boolean, int)","url":"onPlayerStateChanged(boolean,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onPlayerStateChanged(boolean, int)","url":"onPlayerStateChanged(boolean,int)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"onPlaylistChanged()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker.PlaylistEventListener","l":"onPlaylistChanged()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"onPlaylistError(Uri, LoadErrorHandlingPolicy.LoadErrorInfo, boolean)","url":"onPlaylistError(android.net.Uri,com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.LoadErrorInfo,boolean)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker.PlaylistEventListener","l":"onPlaylistError(Uri, LoadErrorHandlingPolicy.LoadErrorInfo, boolean)","url":"onPlaylistError(android.net.Uri,com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.LoadErrorInfo,boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onPlaylistMetadataChanged(AnalyticsListener.EventTime, MediaMetadata)","url":"onPlaylistMetadataChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.MediaMetadata)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onPlaylistMetadataChanged(MediaMetadata)","url":"onPlaylistMetadataChanged(com.google.android.exoplayer2.MediaMetadata)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onPlaylistMetadataChanged(MediaMetadata)","url":"onPlaylistMetadataChanged(com.google.android.exoplayer2.MediaMetadata)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onPlaylistMetadataChanged(MediaMetadata)","url":"onPlaylistMetadataChanged(com.google.android.exoplayer2.MediaMetadata)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"onPlaylistRefreshRequired(Uri)","url":"onPlaylistRefreshRequired(android.net.Uri)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onPlayWhenReadyChanged(AnalyticsListener.EventTime, boolean, int)","url":"onPlayWhenReadyChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,boolean,int)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onPlayWhenReadyChanged(AnalyticsListener.EventTime, boolean, int)","url":"onPlayWhenReadyChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,boolean,int)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onPlayWhenReadyChanged(boolean, int)","url":"onPlayWhenReadyChanged(boolean,int)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onPlayWhenReadyChanged(boolean, int)","url":"onPlayWhenReadyChanged(boolean,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onPlayWhenReadyChanged(boolean, int)","url":"onPlayWhenReadyChanged(boolean,int)"},{"p":"com.google.android.exoplayer2.util","c":"DebugTextViewHelper","l":"onPlayWhenReadyChanged(boolean, int)","url":"onPlayWhenReadyChanged(boolean,int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"onPlayWhenReadyChanged(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.Listener","l":"onPositionAdvancing(long)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.Listener","l":"onPositionDiscontinuity()"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"onPositionDiscontinuity()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onPositionDiscontinuity()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onPositionDiscontinuity(AnalyticsListener.EventTime, int)","url":"onPositionDiscontinuity(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onPositionDiscontinuity(AnalyticsListener.EventTime, Player.PositionInfo, Player.PositionInfo, int)","url":"onPositionDiscontinuity(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.Player.PositionInfo,com.google.android.exoplayer2.Player.PositionInfo,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"onPositionDiscontinuity(AnalyticsListener.EventTime, Player.PositionInfo, Player.PositionInfo, int)","url":"onPositionDiscontinuity(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.Player.PositionInfo,com.google.android.exoplayer2.Player.PositionInfo,int)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onPositionDiscontinuity(AnalyticsListener.EventTime, Player.PositionInfo, Player.PositionInfo, int)","url":"onPositionDiscontinuity(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.Player.PositionInfo,com.google.android.exoplayer2.Player.PositionInfo,int)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onPositionDiscontinuity(int)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onPositionDiscontinuity(Player.PositionInfo, Player.PositionInfo, int)","url":"onPositionDiscontinuity(com.google.android.exoplayer2.Player.PositionInfo,com.google.android.exoplayer2.Player.PositionInfo,int)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onPositionDiscontinuity(Player.PositionInfo, Player.PositionInfo, int)","url":"onPositionDiscontinuity(com.google.android.exoplayer2.Player.PositionInfo,com.google.android.exoplayer2.Player.PositionInfo,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onPositionDiscontinuity(Player.PositionInfo, Player.PositionInfo, int)","url":"onPositionDiscontinuity(com.google.android.exoplayer2.Player.PositionInfo,com.google.android.exoplayer2.Player.PositionInfo,int)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"onPositionDiscontinuity(Player.PositionInfo, Player.PositionInfo, int)","url":"onPositionDiscontinuity(com.google.android.exoplayer2.Player.PositionInfo,com.google.android.exoplayer2.Player.PositionInfo,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"onPositionDiscontinuity(Player.PositionInfo, Player.PositionInfo, int)","url":"onPositionDiscontinuity(com.google.android.exoplayer2.Player.PositionInfo,com.google.android.exoplayer2.Player.PositionInfo,int)"},{"p":"com.google.android.exoplayer2.util","c":"DebugTextViewHelper","l":"onPositionDiscontinuity(Player.PositionInfo, Player.PositionInfo, int)","url":"onPositionDiscontinuity(com.google.android.exoplayer2.Player.PositionInfo,com.google.android.exoplayer2.Player.PositionInfo,int)"},{"p":"com.google.android.exoplayer2.video","c":"VideoFrameReleaseHelper","l":"onPositionReset()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"onPositionReset(long, boolean)","url":"onPositionReset(long,boolean)"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"onPositionReset(long, boolean)","url":"onPositionReset(long,boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"onPositionReset(long, boolean)","url":"onPositionReset(long,boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onPositionReset(long, boolean)","url":"onPositionReset(long,boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onPositionReset(long, boolean)","url":"onPositionReset(long,boolean)"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataRenderer","l":"onPositionReset(long, boolean)","url":"onPositionReset(long,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"onPositionReset(long, boolean)","url":"onPositionReset(long,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeVideoRenderer","l":"onPositionReset(long, boolean)","url":"onPositionReset(long,boolean)"},{"p":"com.google.android.exoplayer2.text","c":"TextRenderer","l":"onPositionReset(long, boolean)","url":"onPositionReset(long,boolean)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"onPositionReset(long, boolean)","url":"onPositionReset(long,boolean)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onPositionReset(long, boolean)","url":"onPositionReset(long,boolean)"},{"p":"com.google.android.exoplayer2.video.spherical","c":"CameraMotionRenderer","l":"onPositionReset(long, boolean)","url":"onPositionReset(long,boolean)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.PostConnectCallback","l":"onPostConnect(MediaSession, MediaSession.ControllerInfo)","url":"onPostConnect(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.PlaybackPreparer","l":"onPrepare(boolean)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod.PrepareListener","l":"onPrepareComplete(MediaSource.MediaPeriodId)","url":"onPrepareComplete(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"onPrepared()"},{"p":"com.google.android.exoplayer2","c":"LoadControl","l":"onPrepared()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"onPrepared()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper.Callback","l":"onPrepared(DownloadHelper)","url":"onPrepared(com.google.android.exoplayer2.offline.DownloadHelper)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"onPrepared(MediaPeriod)","url":"onPrepared(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"onPrepared(MediaPeriod)","url":"onPrepared(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod.Callback","l":"onPrepared(MediaPeriod)","url":"onPrepared(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper.Callback","l":"onPrepareError(DownloadHelper, IOException)","url":"onPrepareError(com.google.android.exoplayer2.offline.DownloadHelper,java.io.IOException)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod.PrepareListener","l":"onPrepareError(MediaSource.MediaPeriodId, IOException)","url":"onPrepareError(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,java.io.IOException)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.PlaybackPreparer","l":"onPrepareFromMediaId(String, boolean, Bundle)","url":"onPrepareFromMediaId(java.lang.String,boolean,android.os.Bundle)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.PlaybackPreparer","l":"onPrepareFromSearch(String, boolean, Bundle)","url":"onPrepareFromSearch(java.lang.String,boolean,android.os.Bundle)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.PlaybackPreparer","l":"onPrepareFromUri(Uri, boolean, Bundle)","url":"onPrepareFromUri(android.net.Uri,boolean,android.os.Bundle)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource","l":"onPrimaryPlaylistRefreshed(HlsMediaPlaylist)","url":"onPrimaryPlaylistRefreshed(com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker.PrimaryPlaylistListener","l":"onPrimaryPlaylistRefreshed(HlsMediaPlaylist)","url":"onPrimaryPlaylistRefreshed(com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onProcessedOutputBuffer(long)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"onProcessedOutputBuffer(long)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onProcessedOutputBuffer(long)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onProcessedStreamChange()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onProcessedStreamChange()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onProcessedStreamChange()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onProcessedTunneledBuffer(long)"},{"p":"com.google.android.exoplayer2.offline","c":"Downloader.ProgressListener","l":"onProgress(long, long, float)","url":"onProgress(long,long,float)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheWriter.ProgressListener","l":"onProgress(long, long, long)","url":"onProgress(long,long,long)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView.ProgressUpdateListener","l":"onProgressUpdate(long, long)","url":"onProgressUpdate(long,long)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView.ProgressUpdateListener","l":"onProgressUpdate(long, long)","url":"onProgressUpdate(long,long)"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"onQueueEndOfStream()"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"onQueueEndOfStream()"},{"p":"com.google.android.exoplayer2.audio","c":"TeeAudioProcessor","l":"onQueueEndOfStream()"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"onQueueInputBuffer(DecoderInputBuffer)","url":"onQueueInputBuffer(com.google.android.exoplayer2.decoder.DecoderInputBuffer)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onQueueInputBuffer(DecoderInputBuffer)","url":"onQueueInputBuffer(com.google.android.exoplayer2.decoder.DecoderInputBuffer)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onQueueInputBuffer(DecoderInputBuffer)","url":"onQueueInputBuffer(com.google.android.exoplayer2.decoder.DecoderInputBuffer)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onQueueInputBuffer(DecoderInputBuffer)","url":"onQueueInputBuffer(com.google.android.exoplayer2.decoder.DecoderInputBuffer)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"onQueueInputBuffer(VideoDecoderInputBuffer)","url":"onQueueInputBuffer(com.google.android.exoplayer2.video.VideoDecoderInputBuffer)"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"onRebuffer()"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","c":"RtpAc3Reader","l":"onReceivingFirstPacket(long, int)","url":"onReceivingFirstPacket(long,int)"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","c":"RtpPayloadReader","l":"onReceivingFirstPacket(long, int)","url":"onReceivingFirstPacket(long,int)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"onReleased()"},{"p":"com.google.android.exoplayer2","c":"LoadControl","l":"onReleased()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.QueueEditor","l":"onRemoveQueueItem(Player, MediaDescriptionCompat)","url":"onRemoveQueueItem(com.google.android.exoplayer2.Player,android.support.v4.media.MediaDescriptionCompat)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor","l":"onRemoveQueueItem(Player, MediaDescriptionCompat)","url":"onRemoveQueueItem(com.google.android.exoplayer2.Player,android.support.v4.media.MediaDescriptionCompat)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onRenderedFirstFrame()"},{"p":"com.google.android.exoplayer2.video","c":"VideoListener","l":"onRenderedFirstFrame()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onRenderedFirstFrame(AnalyticsListener.EventTime, Object, long)","url":"onRenderedFirstFrame(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.Object,long)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onRenderedFirstFrame(AnalyticsListener.EventTime, Object, long)","url":"onRenderedFirstFrame(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.Object,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onRenderedFirstFrame(Object, long)","url":"onRenderedFirstFrame(java.lang.Object,long)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener","l":"onRenderedFirstFrame(Object, long)","url":"onRenderedFirstFrame(java.lang.Object,long)"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"onRendererOffsetChanged(long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onRepeatModeChanged(AnalyticsListener.EventTime, int)","url":"onRepeatModeChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onRepeatModeChanged(AnalyticsListener.EventTime, int)","url":"onRepeatModeChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onRepeatModeChanged(int)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onRepeatModeChanged(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onRepeatModeChanged(int)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"onRepeatModeChanged(int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager.Listener","l":"onRequirementsStateChanged(DownloadManager, Requirements, int)","url":"onRequirementsStateChanged(com.google.android.exoplayer2.offline.DownloadManager,com.google.android.exoplayer2.scheduler.Requirements,int)"},{"p":"com.google.android.exoplayer2.scheduler","c":"RequirementsWatcher.Listener","l":"onRequirementsStateChanged(RequirementsWatcher, int)","url":"onRequirementsStateChanged(com.google.android.exoplayer2.scheduler.RequirementsWatcher,int)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"onReset()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"onReset()"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"onReset()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onReset()"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"onReset()"},{"p":"com.google.android.exoplayer2.audio","c":"TeeAudioProcessor","l":"onReset()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onReset()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onReset()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"onResume()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"onResume()"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView","l":"onResume()"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"onRtlPropertiesChanged(int)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"onSampleCompleted(int, long, int, int, int, MediaCodec.CryptoInfo)","url":"onSampleCompleted(int,long,int,int,int,android.media.MediaCodec.CryptoInfo)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"onSampleDataFound(int, MediaParser.InputReader)","url":"onSampleDataFound(int,android.media.MediaParser.InputReader)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream.ReleaseCallback","l":"onSampleStreamReleased(ChunkSampleStream)","url":"onSampleStreamReleased(com.google.android.exoplayer2.source.chunk.ChunkSampleStream)"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar.OnScrubListener","l":"onScrubMove(TimeBar, long)","url":"onScrubMove(com.google.android.exoplayer2.ui.TimeBar,long)"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar.OnScrubListener","l":"onScrubStart(TimeBar, long)","url":"onScrubStart(com.google.android.exoplayer2.ui.TimeBar,long)"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar.OnScrubListener","l":"onScrubStop(TimeBar, long, boolean)","url":"onScrubStop(com.google.android.exoplayer2.ui.TimeBar,long,boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onSeekBackIncrementChanged(AnalyticsListener.EventTime, long)","url":"onSeekBackIncrementChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,long)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onSeekBackIncrementChanged(long)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onSeekBackIncrementChanged(long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onSeekBackIncrementChanged(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.TimestampSeeker","l":"onSeekFinished()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onSeekForwardIncrementChanged(AnalyticsListener.EventTime, long)","url":"onSeekForwardIncrementChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,long)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onSeekForwardIncrementChanged(long)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onSeekForwardIncrementChanged(long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onSeekForwardIncrementChanged(long)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"onSeekMapFound(MediaParser.SeekMap)","url":"onSeekMapFound(android.media.MediaParser.SeekMap)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"onSeekOperationFinished(boolean, long)","url":"onSeekOperationFinished(boolean,long)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onSeekProcessed()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onSeekProcessed()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onSeekProcessed(AnalyticsListener.EventTime)","url":"onSeekProcessed(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onSeekStarted(AnalyticsListener.EventTime)","url":"onSeekStarted(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector","l":"onSelectionActivated(Object)","url":"onSelectionActivated(java.lang.Object)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelector","l":"onSelectionActivated(Object)","url":"onSelectionActivated(java.lang.Object)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackSessionManager.Listener","l":"onSessionActive(AnalyticsListener.EventTime, String)","url":"onSessionActive(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"onSessionActive(AnalyticsListener.EventTime, String)","url":"onSessionActive(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackSessionManager.Listener","l":"onSessionCreated(AnalyticsListener.EventTime, String)","url":"onSessionCreated(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"onSessionCreated(AnalyticsListener.EventTime, String)","url":"onSessionCreated(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackSessionManager.Listener","l":"onSessionFinished(AnalyticsListener.EventTime, String, boolean)","url":"onSessionFinished(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"onSessionFinished(AnalyticsListener.EventTime, String, boolean)","url":"onSessionFinished(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.CaptionCallback","l":"onSetCaptioningEnabled(Player, boolean)","url":"onSetCaptioningEnabled(com.google.android.exoplayer2.Player,boolean)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.RatingCallback","l":"onSetRating(MediaSession, MediaSession.ControllerInfo, String, Rating)","url":"onSetRating(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo,java.lang.String,androidx.media2.common.Rating)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.RatingCallback","l":"onSetRating(Player, RatingCompat, Bundle)","url":"onSetRating(com.google.android.exoplayer2.Player,android.support.v4.media.RatingCompat,android.os.Bundle)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.RatingCallback","l":"onSetRating(Player, RatingCompat)","url":"onSetRating(com.google.android.exoplayer2.Player,android.support.v4.media.RatingCompat)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onShuffleModeChanged(AnalyticsListener.EventTime, boolean)","url":"onShuffleModeChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onShuffleModeChanged(AnalyticsListener.EventTime, boolean)","url":"onShuffleModeChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,boolean)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onShuffleModeEnabledChanged(boolean)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onShuffleModeEnabledChanged(boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onShuffleModeEnabledChanged(boolean)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"onShuffleModeEnabledChanged(boolean)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.SkipCallback","l":"onSkipBackward(MediaSession, MediaSession.ControllerInfo)","url":"onSkipBackward(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.SkipCallback","l":"onSkipForward(MediaSession, MediaSession.ControllerInfo)","url":"onSkipForward(androidx.media2.session.MediaSession,androidx.media2.session.MediaSession.ControllerInfo)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onSkipSilenceEnabledChanged(AnalyticsListener.EventTime, boolean)","url":"onSkipSilenceEnabledChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onSkipSilenceEnabledChanged(AnalyticsListener.EventTime, boolean)","url":"onSkipSilenceEnabledChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,boolean)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onSkipSilenceEnabledChanged(boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onSkipSilenceEnabledChanged(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioListener","l":"onSkipSilenceEnabledChanged(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener","l":"onSkipSilenceEnabledChanged(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.Listener","l":"onSkipSilenceEnabledChanged(boolean)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.QueueNavigator","l":"onSkipToNext(Player, ControlDispatcher)","url":"onSkipToNext(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ControlDispatcher)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueNavigator","l":"onSkipToNext(Player, ControlDispatcher)","url":"onSkipToNext(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ControlDispatcher)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.QueueNavigator","l":"onSkipToPrevious(Player, ControlDispatcher)","url":"onSkipToPrevious(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ControlDispatcher)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueNavigator","l":"onSkipToPrevious(Player, ControlDispatcher)","url":"onSkipToPrevious(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ControlDispatcher)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.QueueNavigator","l":"onSkipToQueueItem(Player, ControlDispatcher, long)","url":"onSkipToQueueItem(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ControlDispatcher,long)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueNavigator","l":"onSkipToQueueItem(Player, ControlDispatcher, long)","url":"onSkipToQueueItem(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ControlDispatcher,long)"},{"p":"com.google.android.exoplayer2","c":"Renderer.WakeupListener","l":"onSleep(long)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource","l":"onSourceInfoRefreshed(long, boolean, boolean)","url":"onSourceInfoRefreshed(long,boolean,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource.MediaSourceCaller","l":"onSourceInfoRefreshed(MediaSource, Timeline)","url":"onSourceInfoRefreshed(com.google.android.exoplayer2.source.MediaSource,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsMediaSource","l":"onSourceInfoRefreshed(MediaSource, Timeline)","url":"onSourceInfoRefreshed(com.google.android.exoplayer2.source.MediaSource,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache.Listener","l":"onSpanAdded(Cache, CacheSpan)","url":"onSpanAdded(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CachedRegionTracker","l":"onSpanAdded(Cache, CacheSpan)","url":"onSpanAdded(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"LeastRecentlyUsedCacheEvictor","l":"onSpanAdded(Cache, CacheSpan)","url":"onSpanAdded(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"NoOpCacheEvictor","l":"onSpanAdded(Cache, CacheSpan)","url":"onSpanAdded(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache.Listener","l":"onSpanRemoved(Cache, CacheSpan)","url":"onSpanRemoved(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CachedRegionTracker","l":"onSpanRemoved(Cache, CacheSpan)","url":"onSpanRemoved(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"LeastRecentlyUsedCacheEvictor","l":"onSpanRemoved(Cache, CacheSpan)","url":"onSpanRemoved(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"NoOpCacheEvictor","l":"onSpanRemoved(Cache, CacheSpan)","url":"onSpanRemoved(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache.Listener","l":"onSpanTouched(Cache, CacheSpan, CacheSpan)","url":"onSpanTouched(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.cache.CacheSpan,com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CachedRegionTracker","l":"onSpanTouched(Cache, CacheSpan, CacheSpan)","url":"onSpanTouched(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.cache.CacheSpan,com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"LeastRecentlyUsedCacheEvictor","l":"onSpanTouched(Cache, CacheSpan, CacheSpan)","url":"onSpanTouched(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.cache.CacheSpan,com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"NoOpCacheEvictor","l":"onSpanTouched(Cache, CacheSpan, CacheSpan)","url":"onSpanTouched(com.google.android.exoplayer2.upstream.cache.Cache,com.google.android.exoplayer2.upstream.cache.CacheSpan,com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity","l":"onStart()"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"onStart(HostActivity, Surface, FrameLayout)","url":"onStart(com.google.android.exoplayer2.testutil.HostActivity,android.view.Surface,android.widget.FrameLayout)"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity.HostedTest","l":"onStart(HostActivity, Surface, FrameLayout)","url":"onStart(com.google.android.exoplayer2.testutil.HostActivity,android.view.Surface,android.widget.FrameLayout)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"onStartCommand(Intent, int, int)","url":"onStartCommand(android.content.Intent,int,int)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"onStarted()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"onStarted()"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"onStarted()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onStarted()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onStarted()"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"onStarted()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onStarted()"},{"p":"com.google.android.exoplayer2.video","c":"VideoFrameReleaseHelper","l":"onStarted()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheEvictor","l":"onStartFile(Cache, String, long, long)","url":"onStartFile(com.google.android.exoplayer2.upstream.cache.Cache,java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"LeastRecentlyUsedCacheEvictor","l":"onStartFile(Cache, String, long, long)","url":"onStartFile(com.google.android.exoplayer2.upstream.cache.Cache,java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"NoOpCacheEvictor","l":"onStartFile(Cache, String, long, long)","url":"onStartFile(com.google.android.exoplayer2.upstream.cache.Cache,java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.scheduler","c":"PlatformScheduler.PlatformSchedulerService","l":"onStartJob(JobParameters)","url":"onStartJob(android.app.job.JobParameters)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onStaticMetadataChanged(AnalyticsListener.EventTime, List)","url":"onStaticMetadataChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.util.List)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onStaticMetadataChanged(List)","url":"onStaticMetadataChanged(java.util.List)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onStaticMetadataChanged(List)","url":"onStaticMetadataChanged(java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity","l":"onStop()"},{"p":"com.google.android.exoplayer2.scheduler","c":"PlatformScheduler.PlatformSchedulerService","l":"onStopJob(JobParameters)","url":"onStopJob(android.app.job.JobParameters)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"onStopped()"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"onStopped()"},{"p":"com.google.android.exoplayer2","c":"LoadControl","l":"onStopped()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"onStopped()"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"onStopped()"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"onStopped()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onStopped()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeVideoRenderer","l":"onStopped()"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"onStopped()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"onStopped()"},{"p":"com.google.android.exoplayer2.video","c":"VideoFrameReleaseHelper","l":"onStopped()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"onStreamChanged(Format[], long, long)","url":"onStreamChanged(com.google.android.exoplayer2.Format[],long,long)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"onStreamChanged(Format[], long, long)","url":"onStreamChanged(com.google.android.exoplayer2.Format[],long,long)"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataRenderer","l":"onStreamChanged(Format[], long, long)","url":"onStreamChanged(com.google.android.exoplayer2.Format[],long,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeVideoRenderer","l":"onStreamChanged(Format[], long, long)","url":"onStreamChanged(com.google.android.exoplayer2.Format[],long,long)"},{"p":"com.google.android.exoplayer2.text","c":"TextRenderer","l":"onStreamChanged(Format[], long, long)","url":"onStreamChanged(com.google.android.exoplayer2.Format[],long,long)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"onStreamChanged(Format[], long, long)","url":"onStreamChanged(com.google.android.exoplayer2.Format[],long,long)"},{"p":"com.google.android.exoplayer2.video.spherical","c":"CameraMotionRenderer","l":"onStreamChanged(Format[], long, long)","url":"onStreamChanged(com.google.android.exoplayer2.Format[],long,long)"},{"p":"com.google.android.exoplayer2.video","c":"VideoFrameReleaseHelper","l":"onSurfaceChanged(Surface)","url":"onSurfaceChanged(android.view.Surface)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onSurfaceSizeChanged(AnalyticsListener.EventTime, int, int)","url":"onSurfaceSizeChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,int)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onSurfaceSizeChanged(AnalyticsListener.EventTime, int, int)","url":"onSurfaceSizeChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,int)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onSurfaceSizeChanged(int, int)","url":"onSurfaceSizeChanged(int,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onSurfaceSizeChanged(int, int)","url":"onSurfaceSizeChanged(int,int)"},{"p":"com.google.android.exoplayer2.video","c":"VideoListener","l":"onSurfaceSizeChanged(int, int)","url":"onSurfaceSizeChanged(int,int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"onTaskRemoved(Intent)","url":"onTaskRemoved(android.content.Intent)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock","l":"onThreadBlocked()"},{"p":"com.google.android.exoplayer2.util","c":"Clock","l":"onThreadBlocked()"},{"p":"com.google.android.exoplayer2.util","c":"SystemClock","l":"onThreadBlocked()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onTimelineChanged(AnalyticsListener.EventTime, int)","url":"onTimelineChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onTimelineChanged(AnalyticsListener.EventTime, int)","url":"onTimelineChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.QueueNavigator","l":"onTimelineChanged(Player)","url":"onTimelineChanged(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueNavigator","l":"onTimelineChanged(Player)","url":"onTimelineChanged(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onTimelineChanged(Timeline, int)","url":"onTimelineChanged(com.google.android.exoplayer2.Timeline,int)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onTimelineChanged(Timeline, int)","url":"onTimelineChanged(com.google.android.exoplayer2.Timeline,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onTimelineChanged(Timeline, int)","url":"onTimelineChanged(com.google.android.exoplayer2.Timeline,int)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"onTimelineChanged(Timeline, int)","url":"onTimelineChanged(com.google.android.exoplayer2.Timeline,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"onTimelineChanged(Timeline, int)","url":"onTimelineChanged(com.google.android.exoplayer2.Timeline,int)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"onTouchEvent(MotionEvent)","url":"onTouchEvent(android.view.MotionEvent)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"onTouchEvent(MotionEvent)","url":"onTouchEvent(android.view.MotionEvent)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"onTouchEvent(MotionEvent)","url":"onTouchEvent(android.view.MotionEvent)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"onTrackballEvent(MotionEvent)","url":"onTrackballEvent(android.view.MotionEvent)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"onTrackballEvent(MotionEvent)","url":"onTrackballEvent(android.view.MotionEvent)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"onTrackCountFound(int)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"onTrackDataFound(int, MediaParser.TrackData)","url":"onTrackDataFound(int,android.media.MediaParser.TrackData)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onTracksChanged(AnalyticsListener.EventTime, TrackGroupArray, TrackSelectionArray)","url":"onTracksChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.trackselection.TrackSelectionArray)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onTracksChanged(AnalyticsListener.EventTime, TrackGroupArray, TrackSelectionArray)","url":"onTracksChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.trackselection.TrackSelectionArray)"},{"p":"com.google.android.exoplayer2","c":"Player.EventListener","l":"onTracksChanged(TrackGroupArray, TrackSelectionArray)","url":"onTracksChanged(com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.trackselection.TrackSelectionArray)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onTracksChanged(TrackGroupArray, TrackSelectionArray)","url":"onTracksChanged(com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.trackselection.TrackSelectionArray)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onTracksChanged(TrackGroupArray, TrackSelectionArray)","url":"onTracksChanged(com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.trackselection.TrackSelectionArray)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"onTracksChanged(TrackGroupArray, TrackSelectionArray)","url":"onTracksChanged(com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.trackselection.TrackSelectionArray)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionView.TrackSelectionListener","l":"onTrackSelectionChanged(boolean, List)","url":"onTrackSelectionChanged(boolean,java.util.List)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelector.InvalidationListener","l":"onTrackSelectionsInvalidated()"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder.DialogCallback","l":"onTracksSelected(boolean, List)","url":"onTracksSelected(boolean,java.util.List)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"onTracksSelected(Renderer[], TrackGroupArray, ExoTrackSelection[])","url":"onTracksSelected(com.google.android.exoplayer2.Renderer[],com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.trackselection.ExoTrackSelection[])"},{"p":"com.google.android.exoplayer2","c":"LoadControl","l":"onTracksSelected(Renderer[], TrackGroupArray, ExoTrackSelection[])","url":"onTracksSelected(com.google.android.exoplayer2.Renderer[],com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.trackselection.ExoTrackSelection[])"},{"p":"com.google.android.exoplayer2","c":"BundleListRetriever","l":"onTransact(int, Parcel, Parcel, int)","url":"onTransact(int,android.os.Parcel,android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.FakeTransferListener","l":"onTransferEnd(DataSource, DataSpec, boolean)","url":"onTransferEnd(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"onTransferEnd(DataSource, DataSpec, boolean)","url":"onTransferEnd(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"TransferListener","l":"onTransferEnd(DataSource, DataSpec, boolean)","url":"onTransferEnd(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.FakeTransferListener","l":"onTransferInitializing(DataSource, DataSpec, boolean)","url":"onTransferInitializing(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"onTransferInitializing(DataSource, DataSpec, boolean)","url":"onTransferInitializing(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"TransferListener","l":"onTransferInitializing(DataSource, DataSpec, boolean)","url":"onTransferInitializing(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"TimeToFirstByteEstimator","l":"onTransferInitializing(DataSpec)","url":"onTransferInitializing(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.FakeTransferListener","l":"onTransferStart(DataSource, DataSpec, boolean)","url":"onTransferStart(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"onTransferStart(DataSource, DataSpec, boolean)","url":"onTransferStart(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"TransferListener","l":"onTransferStart(DataSource, DataSpec, boolean)","url":"onTransferStart(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"TimeToFirstByteEstimator","l":"onTransferStart(DataSpec)","url":"onTransferStart(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer.Listener","l":"onTransformationCompleted(MediaItem)","url":"onTransformationCompleted(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer.Listener","l":"onTransformationError(MediaItem, Exception)","url":"onTransformationError(com.google.android.exoplayer2.MediaItem,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.source.hls","c":"BundledHlsMediaChunkExtractor","l":"onTruncatedSegmentParsed()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaChunkExtractor","l":"onTruncatedSegmentParsed()"},{"p":"com.google.android.exoplayer2.source.hls","c":"MediaParserHlsMediaChunkExtractor","l":"onTruncatedSegmentParsed()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.Listener","l":"onUnderrun(int, long, long)","url":"onUnderrun(int,long,long)"},{"p":"com.google.android.exoplayer2.database","c":"ExoDatabaseProvider","l":"onUpgrade(SQLiteDatabase, int, int)","url":"onUpgrade(android.database.sqlite.SQLiteDatabase,int,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onUpstreamDiscarded(AnalyticsListener.EventTime, MediaLoadData)","url":"onUpstreamDiscarded(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onUpstreamDiscarded(AnalyticsListener.EventTime, MediaLoadData)","url":"onUpstreamDiscarded(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onUpstreamDiscarded(int, MediaSource.MediaPeriodId, MediaLoadData)","url":"onUpstreamDiscarded(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener","l":"onUpstreamDiscarded(int, MediaSource.MediaPeriodId, MediaLoadData)","url":"onUpstreamDiscarded(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsMediaSource","l":"onUpstreamDiscarded(int, MediaSource.MediaPeriodId, MediaLoadData)","url":"onUpstreamDiscarded(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue.UpstreamFormatChangedListener","l":"onUpstreamFormatChanged(Format)","url":"onUpstreamFormatChanged(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onVideoCodecError(AnalyticsListener.EventTime, Exception)","url":"onVideoCodecError(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onVideoCodecError(Exception)","url":"onVideoCodecError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener","l":"onVideoCodecError(Exception)","url":"onVideoCodecError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onVideoDecoderInitialized(AnalyticsListener.EventTime, String, long, long)","url":"onVideoDecoderInitialized(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onVideoDecoderInitialized(AnalyticsListener.EventTime, String, long)","url":"onVideoDecoderInitialized(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String,long)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onVideoDecoderInitialized(AnalyticsListener.EventTime, String, long)","url":"onVideoDecoderInitialized(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onVideoDecoderInitialized(String, long, long)","url":"onVideoDecoderInitialized(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener","l":"onVideoDecoderInitialized(String, long, long)","url":"onVideoDecoderInitialized(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onVideoDecoderReleased(AnalyticsListener.EventTime, String)","url":"onVideoDecoderReleased(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onVideoDecoderReleased(AnalyticsListener.EventTime, String)","url":"onVideoDecoderReleased(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,java.lang.String)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onVideoDecoderReleased(String)","url":"onVideoDecoderReleased(java.lang.String)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener","l":"onVideoDecoderReleased(String)","url":"onVideoDecoderReleased(java.lang.String)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onVideoDisabled(AnalyticsListener.EventTime, DecoderCounters)","url":"onVideoDisabled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"onVideoDisabled(AnalyticsListener.EventTime, DecoderCounters)","url":"onVideoDisabled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onVideoDisabled(AnalyticsListener.EventTime, DecoderCounters)","url":"onVideoDisabled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onVideoDisabled(DecoderCounters)","url":"onVideoDisabled(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener","l":"onVideoDisabled(DecoderCounters)","url":"onVideoDisabled(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onVideoEnabled(AnalyticsListener.EventTime, DecoderCounters)","url":"onVideoEnabled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onVideoEnabled(AnalyticsListener.EventTime, DecoderCounters)","url":"onVideoEnabled(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onVideoEnabled(DecoderCounters)","url":"onVideoEnabled(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener","l":"onVideoEnabled(DecoderCounters)","url":"onVideoEnabled(com.google.android.exoplayer2.decoder.DecoderCounters)"},{"p":"com.google.android.exoplayer2.video","c":"VideoFrameMetadataListener","l":"onVideoFrameAboutToBeRendered(long, long, Format, MediaFormat)","url":"onVideoFrameAboutToBeRendered(long,long,com.google.android.exoplayer2.Format,android.media.MediaFormat)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onVideoFrameProcessingOffset(AnalyticsListener.EventTime, long, int)","url":"onVideoFrameProcessingOffset(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,long,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onVideoFrameProcessingOffset(long, int)","url":"onVideoFrameProcessingOffset(long,int)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener","l":"onVideoFrameProcessingOffset(long, int)","url":"onVideoFrameProcessingOffset(long,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onVideoInputFormatChanged(AnalyticsListener.EventTime, Format, DecoderReuseEvaluation)","url":"onVideoInputFormatChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.decoder.DecoderReuseEvaluation)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onVideoInputFormatChanged(AnalyticsListener.EventTime, Format, DecoderReuseEvaluation)","url":"onVideoInputFormatChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.Format,com.google.android.exoplayer2.decoder.DecoderReuseEvaluation)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onVideoInputFormatChanged(AnalyticsListener.EventTime, Format)","url":"onVideoInputFormatChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onVideoInputFormatChanged(Format, DecoderReuseEvaluation)","url":"onVideoInputFormatChanged(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.decoder.DecoderReuseEvaluation)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener","l":"onVideoInputFormatChanged(Format, DecoderReuseEvaluation)","url":"onVideoInputFormatChanged(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.decoder.DecoderReuseEvaluation)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener","l":"onVideoInputFormatChanged(Format)","url":"onVideoInputFormatChanged(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onVideoSizeChanged(AnalyticsListener.EventTime, int, int, int, float)","url":"onVideoSizeChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,int,int,float)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onVideoSizeChanged(AnalyticsListener.EventTime, VideoSize)","url":"onVideoSizeChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.video.VideoSize)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"onVideoSizeChanged(AnalyticsListener.EventTime, VideoSize)","url":"onVideoSizeChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.video.VideoSize)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onVideoSizeChanged(AnalyticsListener.EventTime, VideoSize)","url":"onVideoSizeChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,com.google.android.exoplayer2.video.VideoSize)"},{"p":"com.google.android.exoplayer2.video","c":"VideoListener","l":"onVideoSizeChanged(int, int, int, float)","url":"onVideoSizeChanged(int,int,int,float)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onVideoSizeChanged(VideoSize)","url":"onVideoSizeChanged(com.google.android.exoplayer2.video.VideoSize)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onVideoSizeChanged(VideoSize)","url":"onVideoSizeChanged(com.google.android.exoplayer2.video.VideoSize)"},{"p":"com.google.android.exoplayer2.video","c":"VideoListener","l":"onVideoSizeChanged(VideoSize)","url":"onVideoSizeChanged(com.google.android.exoplayer2.video.VideoSize)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener","l":"onVideoSizeChanged(VideoSize)","url":"onVideoSizeChanged(com.google.android.exoplayer2.video.VideoSize)"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView.VideoSurfaceListener","l":"onVideoSurfaceCreated(Surface)","url":"onVideoSurfaceCreated(android.view.Surface)"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView.VideoSurfaceListener","l":"onVideoSurfaceDestroyed(Surface)","url":"onVideoSurfaceDestroyed(android.view.Surface)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView.VisibilityListener","l":"onVisibilityChange(int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView.VisibilityListener","l":"onVisibilityChange(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener","l":"onVolumeChanged(AnalyticsListener.EventTime, float)","url":"onVolumeChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,float)"},{"p":"com.google.android.exoplayer2.util","c":"EventLogger","l":"onVolumeChanged(AnalyticsListener.EventTime, float)","url":"onVolumeChanged(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,float)"},{"p":"com.google.android.exoplayer2","c":"Player.Listener","l":"onVolumeChanged(float)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"onVolumeChanged(float)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioListener","l":"onVolumeChanged(float)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager.Listener","l":"onWaitingForRequirementsChanged(DownloadManager, boolean)","url":"onWaitingForRequirementsChanged(com.google.android.exoplayer2.offline.DownloadManager,boolean)"},{"p":"com.google.android.exoplayer2","c":"Renderer.WakeupListener","l":"onWakeup()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceInputStream","l":"open()"},{"p":"com.google.android.exoplayer2.util","c":"ConditionVariable","l":"open()"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.ext.rtmp","c":"RtmpDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.testutil","c":"FailOnCloseDataSink","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"AssetDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"ByteArrayDataSink","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"ByteArrayDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"ContentDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSchemeDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSink","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"DummyDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"PriorityDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"RawResourceDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"ResolvingDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"StatsDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"TeeDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"UdpDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesCipherDataSink","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesCipherDataSource","l":"open(DataSpec)","url":"open(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.OpenException","l":"OpenException(DataSpec, int, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSpec,int,int)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.OpenException","l":"OpenException(IOException, DataSpec, int, int)","url":"%3Cinit%3E(java.io.IOException,com.google.android.exoplayer2.upstream.DataSpec,int,int)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.OpenException","l":"OpenException(IOException, DataSpec, int)","url":"%3Cinit%3E(java.io.IOException,com.google.android.exoplayer2.upstream.DataSpec,int)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.OpenException","l":"OpenException(String, DataSpec, int, int)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.upstream.DataSpec,int,int)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.OpenException","l":"OpenException(String, DataSpec, int)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.upstream.DataSpec,int)"},{"p":"com.google.android.exoplayer2.util","c":"AtomicFile","l":"openRead()"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"openSession()"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"openSession()"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"openSession()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"openSession()"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusDecoder","l":"OpusDecoder(int, int, int, List, ExoMediaCrypto, boolean)","url":"%3Cinit%3E(int,int,int,java.util.List,com.google.android.exoplayer2.drm.ExoMediaCrypto,boolean)"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusLibrary","l":"opusGetVersion()"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusLibrary","l":"opusIsSecureDecodeSupported()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.OtherTrackScore","l":"OtherTrackScore(Format, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format,int)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"outOfNetworkIndicator"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.Event","l":"outOfNetworkIndicator"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"outputAudioFormat"},{"p":"com.google.android.exoplayer2.decoder","c":"OutputBuffer","l":"OutputBuffer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"OutputConsumerAdapterV30()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"OutputConsumerAdapterV30(Format, int, boolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format,int,boolean)"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusDecoder","l":"outputFloat"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"overallRating"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.TimestampSearchResult","l":"overestimatedResult(long, long)","url":"overestimatedResult(long,long)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"overridePreparePositionUs(long)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"PrivFrame","l":"owner"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Reader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Reader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsReader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DtsReader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DvbSubtitleReader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"ElementaryStreamReader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H262Reader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H263Reader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H264Reader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H265Reader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Id3Reader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"LatmReader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"MpegAudioReader","l":"packetFinished()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Reader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Reader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsReader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DtsReader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DvbSubtitleReader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"ElementaryStreamReader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H262Reader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H263Reader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H264Reader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H265Reader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Id3Reader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"LatmReader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"MpegAudioReader","l":"packetStarted(long, int)","url":"packetStarted(long,int)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"padding"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"MediaParserUtil","l":"PARAMETER_EAGERLY_EXPOSE_TRACK_TYPE"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"MediaParserUtil","l":"PARAMETER_EXPOSE_CAPTION_FORMATS"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"MediaParserUtil","l":"PARAMETER_EXPOSE_CHUNK_INDEX_AS_MEDIA_FORMAT"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"MediaParserUtil","l":"PARAMETER_EXPOSE_DUMMY_SEEK_MAP"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"MediaParserUtil","l":"PARAMETER_IGNORE_TIMESTAMP_OFFSET"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"MediaParserUtil","l":"PARAMETER_IN_BAND_CRYPTO_INFO"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"MediaParserUtil","l":"PARAMETER_INCLUDE_SUPPLEMENTAL_DATA"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"MediaParserUtil","l":"PARAMETER_OVERRIDE_IN_BAND_CAPTION_DECLARATIONS"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"ParametersBuilder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"ParametersBuilder(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream.EmbeddedSampleStream","l":"parent"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"ParsableBitArray()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"ParsableBitArray(byte[], int)","url":"%3Cinit%3E(byte[],int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"ParsableBitArray(byte[])","url":"%3Cinit%3E(byte[])"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"ParsableByteArray()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"ParsableByteArray(byte[], int)","url":"%3Cinit%3E(byte[],int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"ParsableByteArray(byte[])","url":"%3Cinit%3E(byte[])"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"ParsableByteArray(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableNalUnitBitArray","l":"ParsableNalUnitBitArray(byte[], int, int)","url":"%3Cinit%3E(byte[],int,int)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"parse(byte[], int)","url":"parse(byte[],int)"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"parse(Map>)","url":"parse(java.util.Map)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"parse(ParsableByteArray)","url":"parse(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.video","c":"AvcConfig","l":"parse(ParsableByteArray)","url":"parse(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.video","c":"DolbyVisionConfig","l":"parse(ParsableByteArray)","url":"parse(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.video","c":"HevcConfig","l":"parse(ParsableByteArray)","url":"parse(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.offline","c":"FilteringManifestParser","l":"parse(Uri, InputStream)","url":"parse(android.net.Uri,java.io.InputStream)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parse(Uri, InputStream)","url":"parse(android.net.Uri,java.io.InputStream)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistParser","l":"parse(Uri, InputStream)","url":"parse(android.net.Uri,java.io.InputStream)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifestParser","l":"parse(Uri, InputStream)","url":"parse(android.net.Uri,java.io.InputStream)"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable.Parser","l":"parse(Uri, InputStream)","url":"parse(android.net.Uri,java.io.InputStream)"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"parseAc3AnnexFFormat(ParsableByteArray, String, String, DrmInitData)","url":"parseAc3AnnexFFormat(com.google.android.exoplayer2.util.ParsableByteArray,java.lang.String,java.lang.String,com.google.android.exoplayer2.drm.DrmInitData)"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"parseAc3SyncframeAudioSampleCount(ByteBuffer)","url":"parseAc3SyncframeAudioSampleCount(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"parseAc3SyncframeInfo(ParsableBitArray)","url":"parseAc3SyncframeInfo(com.google.android.exoplayer2.util.ParsableBitArray)"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"parseAc3SyncframeSize(byte[])"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util","l":"parseAc4AnnexEFormat(ParsableByteArray, String, String, DrmInitData)","url":"parseAc4AnnexEFormat(com.google.android.exoplayer2.util.ParsableByteArray,java.lang.String,java.lang.String,com.google.android.exoplayer2.drm.DrmInitData)"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util","l":"parseAc4SyncframeAudioSampleCount(ByteBuffer)","url":"parseAc4SyncframeAudioSampleCount(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util","l":"parseAc4SyncframeInfo(ParsableBitArray)","url":"parseAc4SyncframeInfo(com.google.android.exoplayer2.util.ParsableBitArray)"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util","l":"parseAc4SyncframeSize(byte[], int)","url":"parseAc4SyncframeSize(byte[],int)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseAdaptationSet(XmlPullParser, List, SegmentBase, long, long, long, long, long)","url":"parseAdaptationSet(org.xmlpull.v1.XmlPullParser,java.util.List,com.google.android.exoplayer2.source.dash.manifest.SegmentBase,long,long,long,long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseAdaptationSetChild(XmlPullParser)","url":"parseAdaptationSetChild(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.util","c":"CodecSpecificDataUtil","l":"parseAlacAudioSpecificConfig(byte[])"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseAudioChannelConfiguration(XmlPullParser)","url":"parseAudioChannelConfiguration(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"parseAudioSpecificConfig(byte[])"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil","l":"parseAudioSpecificConfig(ParsableBitArray, boolean)","url":"parseAudioSpecificConfig(com.google.android.exoplayer2.util.ParsableBitArray,boolean)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseAvailabilityTimeOffsetUs(XmlPullParser, long)","url":"parseAvailabilityTimeOffsetUs(org.xmlpull.v1.XmlPullParser,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseBaseUrl(XmlPullParser, List)","url":"parseBaseUrl(org.xmlpull.v1.XmlPullParser,java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseCea608AccessibilityChannel(List)","url":"parseCea608AccessibilityChannel(java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseCea708AccessibilityChannel(List)","url":"parseCea708AccessibilityChannel(java.util.List)"},{"p":"com.google.android.exoplayer2.util","c":"CodecSpecificDataUtil","l":"parseCea708InitializationData(List)","url":"parseCea708InitializationData(java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseContentProtection(XmlPullParser)","url":"parseContentProtection(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseContentType(XmlPullParser)","url":"parseContentType(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.util","c":"ColorParser","l":"parseCssColor(String)","url":"parseCssColor(java.lang.String)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCueParser","l":"parseCue(ParsableByteArray, List)","url":"parseCue(com.google.android.exoplayer2.util.ParsableByteArray,java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseDateTime(XmlPullParser, String, long)","url":"parseDateTime(org.xmlpull.v1.XmlPullParser,java.lang.String,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseDescriptor(XmlPullParser, String)","url":"parseDescriptor(org.xmlpull.v1.XmlPullParser,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseDolbyChannelConfiguration(XmlPullParser)","url":"parseDolbyChannelConfiguration(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.audio","c":"DtsUtil","l":"parseDtsAudioSampleCount(byte[])"},{"p":"com.google.android.exoplayer2.audio","c":"DtsUtil","l":"parseDtsAudioSampleCount(ByteBuffer)","url":"parseDtsAudioSampleCount(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.audio","c":"DtsUtil","l":"parseDtsFormat(byte[], String, String, DrmInitData)","url":"parseDtsFormat(byte[],java.lang.String,java.lang.String,com.google.android.exoplayer2.drm.DrmInitData)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseDuration(XmlPullParser, String, long)","url":"parseDuration(org.xmlpull.v1.XmlPullParser,java.lang.String,long)"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"parseEAc3AnnexFFormat(ParsableByteArray, String, String, DrmInitData)","url":"parseEAc3AnnexFFormat(com.google.android.exoplayer2.util.ParsableByteArray,java.lang.String,java.lang.String,com.google.android.exoplayer2.drm.DrmInitData)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseEac3SupplementalProperties(List)","url":"parseEac3SupplementalProperties(java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseEvent(XmlPullParser, String, String, long, ByteArrayOutputStream)","url":"parseEvent(org.xmlpull.v1.XmlPullParser,java.lang.String,java.lang.String,long,java.io.ByteArrayOutputStream)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseEventObject(XmlPullParser, ByteArrayOutputStream)","url":"parseEventObject(org.xmlpull.v1.XmlPullParser,java.io.ByteArrayOutputStream)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseEventStream(XmlPullParser)","url":"parseEventStream(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseFloat(XmlPullParser, String, float)","url":"parseFloat(org.xmlpull.v1.XmlPullParser,java.lang.String,float)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseFrameRate(XmlPullParser, float)","url":"parseFrameRate(org.xmlpull.v1.XmlPullParser,float)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseInitialization(XmlPullParser)","url":"parseInitialization(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseInt(XmlPullParser, String, int)","url":"parseInt(org.xmlpull.v1.XmlPullParser,java.lang.String,int)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseLabel(XmlPullParser)","url":"parseLabel(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseLastSegmentNumberSupplementalProperty(List)","url":"parseLastSegmentNumberSupplementalProperty(java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseLong(XmlPullParser, String, long)","url":"parseLong(org.xmlpull.v1.XmlPullParser,java.lang.String,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseMediaPresentationDescription(XmlPullParser, BaseUrl)","url":"parseMediaPresentationDescription(org.xmlpull.v1.XmlPullParser,com.google.android.exoplayer2.source.dash.manifest.BaseUrl)"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil","l":"parseMpegAudioFrameSampleCount(int)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseMpegChannelConfiguration(XmlPullParser)","url":"parseMpegChannelConfiguration(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttParserUtil","l":"parsePercentage(String)","url":"parsePercentage(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parsePeriod(XmlPullParser, List, long, long, long, long)","url":"parsePeriod(org.xmlpull.v1.XmlPullParser,java.util.List,long,long,long,long)"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil","l":"parsePpsNalUnit(byte[], int, int)","url":"parsePpsNalUnit(byte[],int,int)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseProgramInformation(XmlPullParser)","url":"parseProgramInformation(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseRangedUrl(XmlPullParser, String, String)","url":"parseRangedUrl(org.xmlpull.v1.XmlPullParser,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseRepresentation(XmlPullParser, List, String, String, int, int, float, int, int, String, List, List, List, List, SegmentBase, long, long, long, long, long)","url":"parseRepresentation(org.xmlpull.v1.XmlPullParser,java.util.List,java.lang.String,java.lang.String,int,int,float,int,int,java.lang.String,java.util.List,java.util.List,java.util.List,java.util.List,com.google.android.exoplayer2.source.dash.manifest.SegmentBase,long,long,long,long,long)"},{"p":"com.google.android.exoplayer2","c":"ParserException","l":"ParserException(String, Throwable, boolean, int)","url":"%3Cinit%3E(java.lang.String,java.lang.Throwable,boolean,int)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseRoleFlagsFromAccessibilityDescriptors(List)","url":"parseRoleFlagsFromAccessibilityDescriptors(java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseRoleFlagsFromDashRoleScheme(String)","url":"parseRoleFlagsFromDashRoleScheme(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseRoleFlagsFromProperties(List)","url":"parseRoleFlagsFromProperties(java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseRoleFlagsFromRoleDescriptors(List)","url":"parseRoleFlagsFromRoleDescriptors(java.util.List)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"PsshAtomUtil","l":"parseSchemeSpecificData(byte[], UUID)","url":"parseSchemeSpecificData(byte[],java.util.UUID)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseSegmentBase(XmlPullParser, SegmentBase.SingleSegmentBase)","url":"parseSegmentBase(org.xmlpull.v1.XmlPullParser,com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseSegmentList(XmlPullParser, SegmentBase.SegmentList, long, long, long, long, long)","url":"parseSegmentList(org.xmlpull.v1.XmlPullParser,com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SegmentList,long,long,long,long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseSegmentTemplate(XmlPullParser, SegmentBase.SegmentTemplate, List, long, long, long, long, long)","url":"parseSegmentTemplate(org.xmlpull.v1.XmlPullParser,com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SegmentTemplate,java.util.List,long,long,long,long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseSegmentTimeline(XmlPullParser, long, long)","url":"parseSegmentTimeline(org.xmlpull.v1.XmlPullParser,long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseSegmentUrl(XmlPullParser)","url":"parseSegmentUrl(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseSelectionFlagsFromDashRoleScheme(String)","url":"parseSelectionFlagsFromDashRoleScheme(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseSelectionFlagsFromRoleDescriptors(List)","url":"parseSelectionFlagsFromRoleDescriptors(java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseServiceDescription(XmlPullParser)","url":"parseServiceDescription(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil","l":"parseSpsNalUnit(byte[], int, int)","url":"parseSpsNalUnit(byte[],int,int)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseString(XmlPullParser, String, String)","url":"parseString(org.xmlpull.v1.XmlPullParser,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseText(XmlPullParser, String)","url":"parseText(org.xmlpull.v1.XmlPullParser,java.lang.String)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttParserUtil","l":"parseTimestampUs(String)","url":"parseTimestampUs(java.lang.String)"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"parseTrueHdSyncframeAudioSampleCount(byte[])"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"parseTrueHdSyncframeAudioSampleCount(ByteBuffer, int)","url":"parseTrueHdSyncframeAudioSampleCount(java.nio.ByteBuffer,int)"},{"p":"com.google.android.exoplayer2.util","c":"ColorParser","l":"parseTtmlColor(String)","url":"parseTtmlColor(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseTvaAudioPurposeCsValue(String)","url":"parseTvaAudioPurposeCsValue(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseUrlTemplate(XmlPullParser, String, UrlTemplate)","url":"parseUrlTemplate(org.xmlpull.v1.XmlPullParser,java.lang.String,com.google.android.exoplayer2.source.dash.manifest.UrlTemplate)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser","l":"parseUtcTiming(XmlPullParser)","url":"parseUtcTiming(org.xmlpull.v1.XmlPullParser)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"PsshAtomUtil","l":"parseUuid(byte[])"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"PsshAtomUtil","l":"parseVersion(byte[])"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"parseXsDateTime(String)","url":"parseXsDateTime(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"parseXsDuration(String)","url":"parseXsDuration(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"ParsingLoadable(DataSource, DataSpec, int, ParsingLoadable.Parser)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,int,com.google.android.exoplayer2.upstream.ParsingLoadable.Parser)"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"ParsingLoadable(DataSource, Uri, int, ParsingLoadable.Parser)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,android.net.Uri,int,com.google.android.exoplayer2.upstream.ParsingLoadable.Parser)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.Part","l":"Part(String, HlsMediaPlaylist.Segment, long, int, long, DrmInitData, String, String, long, long, boolean, boolean, boolean)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.Segment,long,int,long,com.google.android.exoplayer2.drm.DrmInitData,java.lang.String,java.lang.String,long,long,boolean,boolean,boolean)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.ServerControl","l":"partHoldBackUs"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.Segment","l":"parts"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"partTargetDurationUs"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PassthroughSectionPayloadReader","l":"PassthroughSectionPayloadReader(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"pause()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"pause()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"pause()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"pause()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"pause()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"pause()"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"pause()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"pause()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"pause()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"pauseDownloads()"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"payloadData"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"payloadType"},{"p":"com.google.android.exoplayer2","c":"Format","l":"pcmEncoding"},{"p":"com.google.android.exoplayer2","c":"Format","l":"peakBitrate"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry.VariantInfo","l":"peakBitrate"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"peek(byte[], int, int)","url":"peek(byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"peek(byte[], int, int)","url":"peek(byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"peek(byte[], int, int)","url":"peek(byte[],int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"peek(byte[], int, int)","url":"peek(byte[],int,int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"peekChar()"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"peekFully(byte[], int, int, boolean)","url":"peekFully(byte[],int,int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"peekFully(byte[], int, int, boolean)","url":"peekFully(byte[],int,int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"peekFully(byte[], int, int, boolean)","url":"peekFully(byte[],int,int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"peekFully(byte[], int, int, boolean)","url":"peekFully(byte[],int,int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"peekFully(byte[], int, int)","url":"peekFully(byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"peekFully(byte[], int, int)","url":"peekFully(byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"peekFully(byte[], int, int)","url":"peekFully(byte[],int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"peekFully(byte[], int, int)","url":"peekFully(byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorUtil","l":"peekFullyQuietly(ExtractorInput, byte[], int, int, boolean)","url":"peekFullyQuietly(com.google.android.exoplayer2.extractor.ExtractorInput,byte[],int,int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"Id3Peeker","l":"peekId3Data(ExtractorInput, Id3Decoder.FramePredicate)","url":"peekId3Data(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.metadata.id3.Id3Decoder.FramePredicate)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacMetadataReader","l":"peekId3Metadata(ExtractorInput, boolean)","url":"peekId3Metadata(com.google.android.exoplayer2.extractor.ExtractorInput,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"peekSourceId()"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorUtil","l":"peekToLength(ExtractorInput, byte[], int, int)","url":"peekToLength(com.google.android.exoplayer2.extractor.ExtractorInput,byte[],int,int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"peekUnsignedByte()"},{"p":"com.google.android.exoplayer2","c":"C","l":"PERCENTAGE_UNSET"},{"p":"com.google.android.exoplayer2","c":"PercentageRating","l":"PercentageRating()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"PercentageRating","l":"PercentageRating(float)","url":"%3Cinit%3E(float)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadProgress","l":"percentDownloaded"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"performAccessibilityAction(int, Bundle)","url":"performAccessibilityAction(int,android.os.Bundle)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"performClick()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"performClick()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"Period()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Period","l":"Period(String, long, List, List, Descriptor)","url":"%3Cinit%3E(java.lang.String,long,java.util.List,java.util.List,com.google.android.exoplayer2.source.dash.manifest.Descriptor)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Period","l":"Period(String, long, List, List)","url":"%3Cinit%3E(java.lang.String,long,java.util.List,java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Period","l":"Period(String, long, List)","url":"%3Cinit%3E(java.lang.String,long,java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"periodCount"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"periodIndex"},{"p":"com.google.android.exoplayer2.offline","c":"StreamKey","l":"periodIndex"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"periodUid"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"periodUid"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"TrackEncryptionBox","l":"perSampleIvSize"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PesReader","l":"PesReader(ElementaryStreamReader)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.ts.ElementaryStreamReader)"},{"p":"com.google.android.exoplayer2.text.pgs","c":"PgsDecoder","l":"PgsDecoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MotionPhotoMetadata","l":"photoPresentationTimestampUs"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MotionPhotoMetadata","l":"photoSize"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MotionPhotoMetadata","l":"photoStartPosition"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"picOrderCntLsbLength"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"picOrderCountType"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.PpsData","l":"picParameterSetId"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"PICTURE_TYPE_A_BRIGHT_COLORED_FISH"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"PICTURE_TYPE_ARTIST_PERFORMER"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"PICTURE_TYPE_BACK_COVER"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"PICTURE_TYPE_BAND_ARTIST_LOGO"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"PICTURE_TYPE_BAND_ORCHESTRA"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"PICTURE_TYPE_COMPOSER"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"PICTURE_TYPE_CONDUCTOR"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"PICTURE_TYPE_DURING_PERFORMANCE"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"PICTURE_TYPE_DURING_RECORDING"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"PICTURE_TYPE_FILE_ICON"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"PICTURE_TYPE_FILE_ICON_OTHER"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"PICTURE_TYPE_FRONT_COVER"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"PICTURE_TYPE_ILLUSTRATION"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"PICTURE_TYPE_LEAD_ARTIST_PERFORMER"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"PICTURE_TYPE_LEAFLET_PAGE"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"PICTURE_TYPE_LYRICIST"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"PICTURE_TYPE_MEDIA"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"PICTURE_TYPE_MOVIE_VIDEO_SCREEN_CAPTURE"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"PICTURE_TYPE_OTHER"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"PICTURE_TYPE_PUBLISHER_STUDIO_LOGO"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"PICTURE_TYPE_RECORDING_LOCATION"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"pictureData"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ApicFrame","l":"pictureData"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"PictureFrame(int, String, String, int, int, int, int, byte[])","url":"%3Cinit%3E(int,java.lang.String,java.lang.String,int,int,int,int,byte[])"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"pictureType"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ApicFrame","l":"pictureType"},{"p":"com.google.android.exoplayer2","c":"PlaybackParameters","l":"pitch"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"pixelWidthAspectRatio"},{"p":"com.google.android.exoplayer2.video","c":"AvcConfig","l":"pixelWidthAspectRatio"},{"p":"com.google.android.exoplayer2","c":"Format","l":"pixelWidthHeightRatio"},{"p":"com.google.android.exoplayer2.video","c":"VideoSize","l":"pixelWidthHeightRatio"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorOutput","l":"PLACEHOLDER"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource.PlaceholderTimeline","l":"PlaceholderTimeline(MediaItem)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.scheduler","c":"PlatformScheduler","l":"PlatformScheduler(Context, int)","url":"%3Cinit%3E(android.content.Context,int)"},{"p":"com.google.android.exoplayer2.scheduler","c":"PlatformScheduler.PlatformSchedulerService","l":"PlatformSchedulerService()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"PLAY_WHEN_READY_CHANGE_REASON_AUDIO_BECOMING_NOISY"},{"p":"com.google.android.exoplayer2","c":"Player","l":"PLAY_WHEN_READY_CHANGE_REASON_AUDIO_FOCUS_LOSS"},{"p":"com.google.android.exoplayer2","c":"Player","l":"PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM"},{"p":"com.google.android.exoplayer2","c":"Player","l":"PLAY_WHEN_READY_CHANGE_REASON_REMOTE"},{"p":"com.google.android.exoplayer2","c":"Player","l":"PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"play()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"play()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"play()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"play()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"play()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"play()"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"play()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"play()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"play()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_ABANDONED"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_BUFFERING"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_ENDED"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_FAILED"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_INTERRUPTED_BY_AD"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_JOINING_BACKGROUND"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_JOINING_FOREGROUND"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_NOT_STARTED"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_PAUSED"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_PAUSED_BUFFERING"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_PLAYING"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_SEEKING"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_STOPPED"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_SUPPRESSED"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"PLAYBACK_STATE_SUPPRESSED_BUFFERING"},{"p":"com.google.android.exoplayer2","c":"Player","l":"PLAYBACK_SUPPRESSION_REASON_NONE"},{"p":"com.google.android.exoplayer2","c":"Player","l":"PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS"},{"p":"com.google.android.exoplayer2.device","c":"DeviceInfo","l":"PLAYBACK_TYPE_LOCAL"},{"p":"com.google.android.exoplayer2.device","c":"DeviceInfo","l":"PLAYBACK_TYPE_REMOTE"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"playbackCount"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"PlaybackException(Bundle)","url":"%3Cinit%3E(android.os.Bundle)"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"PlaybackException(String, Throwable, int, long)","url":"%3Cinit%3E(java.lang.String,java.lang.Throwable,int,long)"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"PlaybackException(String, Throwable, int)","url":"%3Cinit%3E(java.lang.String,java.lang.Throwable,int)"},{"p":"com.google.android.exoplayer2","c":"PlaybackParameters","l":"PlaybackParameters(float, float)","url":"%3Cinit%3E(float,float)"},{"p":"com.google.android.exoplayer2","c":"PlaybackParameters","l":"PlaybackParameters(float)","url":"%3Cinit%3E(float)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"TimeSignalCommand","l":"playbackPositionUs"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"playbackProperties"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats.EventTimeAndPlaybackState","l":"playbackState"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"playbackStateHistory"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStatsListener","l":"PlaybackStatsListener(boolean, PlaybackStatsListener.Callback)","url":"%3Cinit%3E(boolean,com.google.android.exoplayer2.analytics.PlaybackStatsListener.Callback)"},{"p":"com.google.android.exoplayer2.device","c":"DeviceInfo","l":"playbackType"},{"p":"com.google.android.exoplayer2","c":"MediaItem.DrmConfiguration","l":"playClearContentWithoutKey"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"playClearSamplesWithoutKeys()"},{"p":"com.google.android.exoplayer2.drm","c":"ErrorStateDrmSession","l":"playClearSamplesWithoutKeys()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"PlayerControlView(Context, AttributeSet, int, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet,int,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"PlayerControlView(Context, AttributeSet, int)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet,int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"PlayerControlView(Context, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"PlayerControlView(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler","l":"PlayerEmsgHandler(DashManifest, PlayerEmsgHandler.PlayerEmsgCallback, Allocator)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.dash.manifest.DashManifest,com.google.android.exoplayer2.source.dash.PlayerEmsgHandler.PlayerEmsgCallback,com.google.android.exoplayer2.upstream.Allocator)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"PlayerMessage(PlayerMessage.Sender, PlayerMessage.Target, Timeline, int, Clock, Looper)","url":"%3Cinit%3E(com.google.android.exoplayer2.PlayerMessage.Sender,com.google.android.exoplayer2.PlayerMessage.Target,com.google.android.exoplayer2.Timeline,int,com.google.android.exoplayer2.util.Clock,android.os.Looper)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.PlayerRunnable","l":"PlayerRunnable()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.PlayerTarget","l":"PlayerTarget()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"PlayerView(Context, AttributeSet, int)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet,int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"PlayerView(Context, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"PlayerView(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"PLAYLIST_TYPE_EVENT"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"PLAYLIST_TYPE_UNKNOWN"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"PLAYLIST_TYPE_VOD"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker.PlaylistResetException","l":"PlaylistResetException(Uri)","url":"%3Cinit%3E(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker.PlaylistStuckException","l":"PlaylistStuckException(Uri)","url":"%3Cinit%3E(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"playlistType"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.RenditionReport","l":"playlistUri"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"PLAYREADY_CUSTOM_DATA_KEY"},{"p":"com.google.android.exoplayer2","c":"C","l":"PLAYREADY_UUID"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"playToEndOfStream()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"playToEndOfStream()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"playToEndOfStream()"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestPlayerRunHelper","l":"playUntilPosition(ExoPlayer, int, long)","url":"playUntilPosition(com.google.android.exoplayer2.ExoPlayer,int,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"playUntilPosition(int, long)","url":"playUntilPosition(int,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.PlayUntilPosition","l":"PlayUntilPosition(String, int, long)","url":"%3Cinit%3E(java.lang.String,int,long)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestPlayerRunHelper","l":"playUntilStartOfWindow(ExoPlayer, int)","url":"playUntilStartOfWindow(com.google.android.exoplayer2.ExoPlayer,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"playUntilStartOfWindow(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata.SeekTable","l":"pointOffsets"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata.SeekTable","l":"pointSampleNumbers"},{"p":"com.google.android.exoplayer2.util","c":"TimedValueQueue","l":"poll(long)"},{"p":"com.google.android.exoplayer2.util","c":"TimedValueQueue","l":"pollFirst()"},{"p":"com.google.android.exoplayer2.util","c":"TimedValueQueue","l":"pollFloor(long)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"populateFromMetadata(List)","url":"populateFromMetadata(java.util.List)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"populateFromMetadata(Metadata)","url":"populateFromMetadata(com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata.Entry","l":"populateMediaMetadata(MediaMetadata.Builder)","url":"populateMediaMetadata(com.google.android.exoplayer2.MediaMetadata.Builder)"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"populateMediaMetadata(MediaMetadata.Builder)","url":"populateMediaMetadata(com.google.android.exoplayer2.MediaMetadata.Builder)"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"VorbisComment","l":"populateMediaMetadata(MediaMetadata.Builder)","url":"populateMediaMetadata(com.google.android.exoplayer2.MediaMetadata.Builder)"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyInfo","l":"populateMediaMetadata(MediaMetadata.Builder)","url":"populateMediaMetadata(com.google.android.exoplayer2.MediaMetadata.Builder)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ApicFrame","l":"populateMediaMetadata(MediaMetadata.Builder)","url":"populateMediaMetadata(com.google.android.exoplayer2.MediaMetadata.Builder)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"TextInformationFrame","l":"populateMediaMetadata(MediaMetadata.Builder)","url":"populateMediaMetadata(com.google.android.exoplayer2.MediaMetadata.Builder)"},{"p":"com.google.android.exoplayer2.extractor","c":"PositionHolder","l":"position"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekPoint","l":"position"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"position"},{"p":"com.google.android.exoplayer2.text.span","c":"RubySpan","l":"position"},{"p":"com.google.android.exoplayer2.text.span","c":"TextEmphasisSpan","l":"position"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"position"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheSpan","l":"position"},{"p":"com.google.android.exoplayer2.text.span","c":"TextAnnotation","l":"POSITION_AFTER"},{"p":"com.google.android.exoplayer2.text.span","c":"TextAnnotation","l":"POSITION_BEFORE"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceException","l":"POSITION_OUT_OF_RANGE"},{"p":"com.google.android.exoplayer2.text.span","c":"TextAnnotation","l":"POSITION_UNKNOWN"},{"p":"com.google.android.exoplayer2","c":"C","l":"POSITION_UNSET"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener.EventDispatcher","l":"positionAdvancing(long)"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"positionAnchor"},{"p":"com.google.android.exoplayer2.extractor","c":"PositionHolder","l":"PositionHolder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"positionInFirstPeriodUs"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"PositionInfo(Object, int, Object, int, long, long, int, int)","url":"%3Cinit%3E(java.lang.Object,int,java.lang.Object,int,long,long,int,int)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"positionInWindowUs"},{"p":"com.google.android.exoplayer2","c":"IllegalSeekPositionException","l":"positionMs"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"positionMs"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"positionResetCount"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"post(Runnable)","url":"post(java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"postAtFrontOfQueue(Runnable)","url":"postAtFrontOfQueue(java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"postDelayed(Runnable, long)","url":"postDelayed(java.lang.Runnable,long)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"postOrRun(Handler, Runnable)","url":"postOrRun(android.os.Handler,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.PpsData","l":"PpsData(int, int, boolean)","url":"%3Cinit%3E(int,int,boolean)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"preacquireSession(Looper, DrmSessionEventListener.EventDispatcher, Format)","url":"preacquireSession(android.os.Looper,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionManager","l":"preacquireSession(Looper, DrmSessionEventListener.EventDispatcher, Format)","url":"preacquireSession(android.os.Looper,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"preciseStart"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"preferredAudioLanguages"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"preferredAudioMimeTypes"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"preferredAudioRoleFlags"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"preferredTextLanguages"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"preferredTextRoleFlags"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"preferredVideoMimeTypes"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"prepare()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"prepare()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"prepare()"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"prepare()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionManager","l":"prepare()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"prepare()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"prepare()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"prepare()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"prepare()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"prepare(DownloadHelper.Callback)","url":"prepare(com.google.android.exoplayer2.offline.DownloadHelper.Callback)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"prepare(MediaPeriod.Callback, long)","url":"prepare(com.google.android.exoplayer2.source.MediaPeriod.Callback,long)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"prepare(MediaPeriod.Callback, long)","url":"prepare(com.google.android.exoplayer2.source.MediaPeriod.Callback,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"prepare(MediaPeriod.Callback, long)","url":"prepare(com.google.android.exoplayer2.source.MediaPeriod.Callback,long)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"prepare(MediaPeriod.Callback, long)","url":"prepare(com.google.android.exoplayer2.source.MediaPeriod.Callback,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"prepare(MediaPeriod.Callback, long)","url":"prepare(com.google.android.exoplayer2.source.MediaPeriod.Callback,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"prepare(MediaPeriod.Callback, long)","url":"prepare(com.google.android.exoplayer2.source.MediaPeriod.Callback,long)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"prepare(MediaSource, boolean, boolean)","url":"prepare(com.google.android.exoplayer2.source.MediaSource,boolean,boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"prepare(MediaSource, boolean, boolean)","url":"prepare(com.google.android.exoplayer2.source.MediaSource,boolean,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"prepare(MediaSource, boolean, boolean)","url":"prepare(com.google.android.exoplayer2.source.MediaSource,boolean,boolean)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"prepare(MediaSource)","url":"prepare(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"prepare(MediaSource)","url":"prepare(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"prepare(MediaSource)","url":"prepare(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.Prepare","l":"Prepare(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"prepareChildSource(T, MediaSource)","url":"prepareChildSource(T,com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"preparePeriod(MediaPeriod, long)","url":"preparePeriod(com.google.android.exoplayer2.source.MediaPeriod,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"prepareSource()"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"prepareSource(MediaSource.MediaSourceCaller, TransferListener)","url":"prepareSource(com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"prepareSource(MediaSource.MediaSourceCaller, TransferListener)","url":"prepareSource(com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller,com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"LoopingMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"prepareSourceInternal(TransferListener)","url":"prepareSourceInternal(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"preRelease()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"presentationStartTimeMs"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"presentationTimeOffsetUs"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"EventStream","l":"presentationTimesUs"},{"p":"com.google.android.exoplayer2","c":"SeekParameters","l":"PREVIOUS_SYNC"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"previous()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"previous()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"previous()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"primaryTrackType"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"BaseUrl","l":"priority"},{"p":"com.google.android.exoplayer2","c":"C","l":"PRIORITY_DOWNLOAD"},{"p":"com.google.android.exoplayer2","c":"C","l":"PRIORITY_PLAYBACK"},{"p":"com.google.android.exoplayer2.upstream","c":"PriorityDataSource","l":"PriorityDataSource(DataSource, PriorityTaskManager, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.util.PriorityTaskManager,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"PriorityDataSourceFactory","l":"PriorityDataSourceFactory(DataSource.Factory, PriorityTaskManager, int)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource.Factory,com.google.android.exoplayer2.util.PriorityTaskManager,int)"},{"p":"com.google.android.exoplayer2.util","c":"PriorityTaskManager","l":"PriorityTaskManager()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.util","c":"PriorityTaskManager.PriorityTooLowException","l":"PriorityTooLowException(int, int)","url":"%3Cinit%3E(int,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"PRIVATE_STREAM_1"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"PrivFrame","l":"privateData"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"PrivFrame","l":"PrivFrame(String, byte[])","url":"%3Cinit%3E(java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.util","c":"PriorityTaskManager","l":"proceed(int)"},{"p":"com.google.android.exoplayer2.util","c":"PriorityTaskManager","l":"proceedNonBlocking(int)"},{"p":"com.google.android.exoplayer2.util","c":"PriorityTaskManager","l":"proceedOrThrow(int)"},{"p":"com.google.android.exoplayer2.robolectric","c":"RandomizedMp3Decoder","l":"process(ByteBuffer, ByteBuffer)","url":"process(java.nio.ByteBuffer,java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"processOutputBuffer(long, long, MediaCodecAdapter, ByteBuffer, int, int, int, long, boolean, boolean, Format)","url":"processOutputBuffer(long,long,com.google.android.exoplayer2.mediacodec.MediaCodecAdapter,java.nio.ByteBuffer,int,int,int,long,boolean,boolean,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"processOutputBuffer(long, long, MediaCodecAdapter, ByteBuffer, int, int, int, long, boolean, boolean, Format)","url":"processOutputBuffer(long,long,com.google.android.exoplayer2.mediacodec.MediaCodecAdapter,java.nio.ByteBuffer,int,int,int,long,boolean,boolean,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"processOutputBuffer(long, long, MediaCodecAdapter, ByteBuffer, int, int, int, long, boolean, boolean, Format)","url":"processOutputBuffer(long,long,com.google.android.exoplayer2.mediacodec.MediaCodecAdapter,java.nio.ByteBuffer,int,int,int,long,boolean,boolean,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.video","c":"DolbyVisionConfig","l":"profile"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"profileIdc"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"programInformation"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ProgramInformation","l":"ProgramInformation(String, String, String, String, String)","url":"%3Cinit%3E(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"programSpliceFlag"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.Event","l":"programSpliceFlag"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"programSplicePlaybackPositionUs"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"programSplicePts"},{"p":"com.google.android.exoplayer2.transformer","c":"ProgressHolder","l":"progress"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer","l":"PROGRESS_STATE_AVAILABLE"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer","l":"PROGRESS_STATE_NO_TRANSFORMATION"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer","l":"PROGRESS_STATE_UNAVAILABLE"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer","l":"PROGRESS_STATE_WAITING_FOR_AVAILABILITY"},{"p":"com.google.android.exoplayer2.transformer","c":"ProgressHolder","l":"ProgressHolder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.offline","c":"ProgressiveDownloader","l":"ProgressiveDownloader(MediaItem, CacheDataSource.Factory, Executor)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.offline","c":"ProgressiveDownloader","l":"ProgressiveDownloader(MediaItem, CacheDataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory)"},{"p":"com.google.android.exoplayer2","c":"C","l":"PROJECTION_CUBEMAP"},{"p":"com.google.android.exoplayer2","c":"C","l":"PROJECTION_EQUIRECTANGULAR"},{"p":"com.google.android.exoplayer2","c":"C","l":"PROJECTION_MESH"},{"p":"com.google.android.exoplayer2","c":"C","l":"PROJECTION_RECTANGULAR"},{"p":"com.google.android.exoplayer2","c":"Format","l":"projectionData"},{"p":"com.google.android.exoplayer2.drm","c":"WidevineUtil","l":"PROPERTY_LICENSE_DURATION_REMAINING"},{"p":"com.google.android.exoplayer2.drm","c":"WidevineUtil","l":"PROPERTY_PLAYBACK_DURATION_REMAINING"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest","l":"protectionElement"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.ProtectionElement","l":"ProtectionElement(UUID, byte[], TrackEncryptionBox[])","url":"%3Cinit%3E(java.util.UUID,byte[],com.google.android.exoplayer2.extractor.mp4.TrackEncryptionBox[])"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"protectionSchemes"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"provideKeyResponse(byte[], byte[])","url":"provideKeyResponse(byte[],byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"provideKeyResponse(byte[], byte[])","url":"provideKeyResponse(byte[],byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"provideKeyResponse(byte[], byte[])","url":"provideKeyResponse(byte[],byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"provideKeyResponse(byte[], byte[])","url":"provideKeyResponse(byte[],byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"provideProvisionResponse(byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"provideProvisionResponse(byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"provideProvisionResponse(byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"provideProvisionResponse(byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.ProvisionRequest","l":"ProvisionRequest(byte[], String)","url":"%3Cinit%3E(byte[],java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"PS"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"PsExtractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"PsExtractor(TimestampAdjuster)","url":"%3Cinit%3E(com.google.android.exoplayer2.util.TimestampAdjuster)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"PrivateCommand","l":"ptsAdjustment"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"TimeSignalCommand","l":"ptsTime"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"ptsToUs(long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"publishTimeMs"},{"p":"com.google.android.exoplayer2.ui","c":"AdOverlayInfo","l":"purpose"},{"p":"com.google.android.exoplayer2.ui","c":"AdOverlayInfo","l":"PURPOSE_CLOSE_AD"},{"p":"com.google.android.exoplayer2.ui","c":"AdOverlayInfo","l":"PURPOSE_CONTROLS"},{"p":"com.google.android.exoplayer2.ui","c":"AdOverlayInfo","l":"PURPOSE_NOT_VISIBLE"},{"p":"com.google.android.exoplayer2.ui","c":"AdOverlayInfo","l":"PURPOSE_OTHER"},{"p":"com.google.android.exoplayer2.util","c":"BundleUtil","l":"putBinder(Bundle, String, IBinder)","url":"putBinder(android.os.Bundle,java.lang.String,android.os.IBinder)"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloadIndex","l":"putDownload(Download)","url":"putDownload(com.google.android.exoplayer2.offline.Download)"},{"p":"com.google.android.exoplayer2.offline","c":"WritableDownloadIndex","l":"putDownload(Download)","url":"putDownload(com.google.android.exoplayer2.offline.Download)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"putInt(int, int)","url":"putInt(int,int)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"queryKeyStatus()"},{"p":"com.google.android.exoplayer2.drm","c":"ErrorStateDrmSession","l":"queryKeyStatus()"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"queryKeyStatus(byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"queryKeyStatus(byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"queryKeyStatus(byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"queryKeyStatus(byte[])"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor","l":"queueEndOfStream()"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"queueEndOfStream()"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"queueEndOfStream()"},{"p":"com.google.android.exoplayer2.ext.gvr","c":"GvrAudioProcessor","l":"queueEndOfStream()"},{"p":"com.google.android.exoplayer2.util","c":"ListenerSet","l":"queueEvent(int, ListenerSet.Event)","url":"queueEvent(int,com.google.android.exoplayer2.util.ListenerSet.Event)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor","l":"queueInput(ByteBuffer)","url":"queueInput(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"queueInput(ByteBuffer)","url":"queueInput(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"queueInput(ByteBuffer)","url":"queueInput(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.audio","c":"TeeAudioProcessor","l":"queueInput(ByteBuffer)","url":"queueInput(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.ext.gvr","c":"GvrAudioProcessor","l":"queueInput(ByteBuffer)","url":"queueInput(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.decoder","c":"Decoder","l":"queueInputBuffer(I)"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleDecoder","l":"queueInputBuffer(I)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"queueInputBuffer(int, int, int, long, int)","url":"queueInputBuffer(int,int,int,long,int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"queueInputBuffer(int, int, int, long, int)","url":"queueInputBuffer(int,int,int,long,int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"queueSecureInputBuffer(int, int, CryptoInfo, long, int)","url":"queueSecureInputBuffer(int,int,com.google.android.exoplayer2.decoder.CryptoInfo,long,int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"queueSecureInputBuffer(int, int, CryptoInfo, long, int)","url":"queueSecureInputBuffer(int,int,com.google.android.exoplayer2.decoder.CryptoInfo,long,int)"},{"p":"com.google.android.exoplayer2.robolectric","c":"RandomizedMp3Decoder","l":"RandomizedMp3Decoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.trackselection","c":"RandomTrackSelection","l":"RandomTrackSelection(TrackGroup, int[], int, Random)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroup,int[],int,java.util.Random)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"RangedUri","l":"RangedUri(String, long, long)","url":"%3Cinit%3E(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2","c":"C","l":"RATE_UNSET"},{"p":"com.google.android.exoplayer2","c":"Rating","l":"RATING_UNSET"},{"p":"com.google.android.exoplayer2.upstream","c":"RawResourceDataSource","l":"RAW_RESOURCE_SCHEME"},{"p":"com.google.android.exoplayer2.extractor.rawcc","c":"RawCcExtractor","l":"RawCcExtractor(Format)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyInfo","l":"rawMetadata"},{"p":"com.google.android.exoplayer2.upstream","c":"RawResourceDataSource","l":"RawResourceDataSource(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.upstream","c":"RawResourceDataSource.RawResourceDataSourceException","l":"RawResourceDataSourceException(String, Throwable, int)","url":"%3Cinit%3E(java.lang.String,java.lang.Throwable,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"RawResourceDataSource.RawResourceDataSourceException","l":"RawResourceDataSourceException(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"RawResourceDataSource.RawResourceDataSourceException","l":"RawResourceDataSourceException(Throwable)","url":"%3Cinit%3E(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceInputStream","l":"read()"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.ext.rtmp","c":"RtmpDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"InputReaderAdapterV30","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"AssetDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"ByteArrayDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"ContentDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataReader","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSchemeDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceInputStream","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DummyDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"PriorityDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"RawResourceDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"ResolvingDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"StatsDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"TeeDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"UdpDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesCipherDataSource","l":"read(byte[], int, int)","url":"read(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceInputStream","l":"read(byte[])"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"read(ByteBuffer)","url":"read(java.nio.ByteBuffer)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor","c":"Extractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.amr","c":"AmrExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.flac","c":"FlacExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.flv","c":"FlvExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.jpeg","c":"JpegExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.ogg","c":"OggExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.rawcc","c":"RawCcExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Extractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Extractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor.wav","c":"WavExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.source.hls","c":"WebvttExtractor","l":"read(ExtractorInput, PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BundledChunkExtractor","l":"read(ExtractorInput)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkExtractor","l":"read(ExtractorInput)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaParserChunkExtractor","l":"read(ExtractorInput)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.source.hls","c":"BundledHlsMediaChunkExtractor","l":"read(ExtractorInput)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaChunkExtractor","l":"read(ExtractorInput)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.source.hls","c":"MediaParserHlsMediaChunkExtractor","l":"read(ExtractorInput)","url":"read(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"read(FormatHolder, DecoderInputBuffer, int, boolean)","url":"read(com.google.android.exoplayer2.FormatHolder,com.google.android.exoplayer2.decoder.DecoderInputBuffer,int,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"BundledExtractorsAdapter","l":"read(PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.source","c":"MediaParserExtractorAdapter","l":"read(PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaExtractor","l":"read(PositionHolder)","url":"read(com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisBitArray","l":"readBit()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"readBit()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableNalUnitBitArray","l":"readBit()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"readBits(byte[], int, int)","url":"readBits(byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisBitArray","l":"readBits(int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"readBits(int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableNalUnitBitArray","l":"readBits(int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"readBitsToLong(int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"readBoolean(Parcel)","url":"readBoolean(android.os.Parcel)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"readBytes(byte[], int, int)","url":"readBytes(byte[],int,int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readBytes(byte[], int, int)","url":"readBytes(byte[],int,int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readBytes(ByteBuffer, int)","url":"readBytes(java.nio.ByteBuffer,int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readBytes(ParsableBitArray, int)","url":"readBytes(com.google.android.exoplayer2.util.ParsableBitArray,int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"readBytesAsString(int, Charset)","url":"readBytesAsString(int,java.nio.charset.Charset)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"readBytesAsString(int)"},{"p":"com.google.android.exoplayer2.source","c":"EmptySampleStream","l":"readData(FormatHolder, DecoderInputBuffer, int)","url":"readData(com.google.android.exoplayer2.FormatHolder,com.google.android.exoplayer2.decoder.DecoderInputBuffer,int)"},{"p":"com.google.android.exoplayer2.source","c":"SampleStream","l":"readData(FormatHolder, DecoderInputBuffer, int)","url":"readData(com.google.android.exoplayer2.FormatHolder,com.google.android.exoplayer2.decoder.DecoderInputBuffer,int)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"readData(FormatHolder, DecoderInputBuffer, int)","url":"readData(com.google.android.exoplayer2.FormatHolder,com.google.android.exoplayer2.decoder.DecoderInputBuffer,int)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream.EmbeddedSampleStream","l":"readData(FormatHolder, DecoderInputBuffer, int)","url":"readData(com.google.android.exoplayer2.FormatHolder,com.google.android.exoplayer2.decoder.DecoderInputBuffer,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"readData(FormatHolder, DecoderInputBuffer, int)","url":"readData(com.google.android.exoplayer2.FormatHolder,com.google.android.exoplayer2.decoder.DecoderInputBuffer,int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readDelimiterTerminatedString(char)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"readDiscontinuity()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"readDiscontinuity()"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"readDiscontinuity()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"readDiscontinuity()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"readDiscontinuity()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"readDiscontinuity()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readDouble()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"readExactly(DataSource, int)","url":"readExactly(com.google.android.exoplayer2.upstream.DataSource,int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readFloat()"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacFrameReader","l":"readFrameBlockSizeSamplesFromKey(ParsableByteArray, int)","url":"readFrameBlockSizeSamplesFromKey(com.google.android.exoplayer2.util.ParsableByteArray,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"readFully(byte[], int, int, boolean)","url":"readFully(byte[],int,int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"readFully(byte[], int, int, boolean)","url":"readFully(byte[],int,int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"readFully(byte[], int, int, boolean)","url":"readFully(byte[],int,int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"readFully(byte[], int, int, boolean)","url":"readFully(byte[],int,int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"readFully(byte[], int, int)","url":"readFully(byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"readFully(byte[], int, int)","url":"readFully(byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"readFully(byte[], int, int)","url":"readFully(byte[],int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"readFully(byte[], int, int)","url":"readFully(byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorUtil","l":"readFullyQuietly(ExtractorInput, byte[], int, int)","url":"readFullyQuietly(com.google.android.exoplayer2.extractor.ExtractorInput,byte[],int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacMetadataReader","l":"readId3Metadata(ExtractorInput, boolean)","url":"readId3Metadata(com.google.android.exoplayer2.extractor.ExtractorInput,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readInt()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readInt24()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readLine()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readLittleEndianInt()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readLittleEndianInt24()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readLittleEndianLong()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readLittleEndianShort()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readLittleEndianUnsignedInt()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readLittleEndianUnsignedInt24()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readLittleEndianUnsignedIntToInt()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readLittleEndianUnsignedShort()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readLong()"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacMetadataReader","l":"readMetadataBlock(ExtractorInput, FlacMetadataReader.FlacStreamMetadataHolder)","url":"readMetadataBlock(com.google.android.exoplayer2.extractor.ExtractorInput,com.google.android.exoplayer2.extractor.FlacMetadataReader.FlacStreamMetadataHolder)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readNullTerminatedString()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readNullTerminatedString(int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsUtil","l":"readPcrFromPacket(ParsableByteArray, int, int)","url":"readPcrFromPacket(com.google.android.exoplayer2.util.ParsableByteArray,int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacMetadataReader","l":"readSeekTableMetadataBlock(ParsableByteArray)","url":"readSeekTableMetadataBlock(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readShort()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableNalUnitBitArray","l":"readSignedExpGolombCodedInt()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"readSource(FormatHolder, DecoderInputBuffer, int)","url":"readSource(com.google.android.exoplayer2.FormatHolder,com.google.android.exoplayer2.decoder.DecoderInputBuffer,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacMetadataReader","l":"readStreamMarker(ExtractorInput)","url":"readStreamMarker(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readString(int, Charset)","url":"readString(int,java.nio.charset.Charset)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readString(int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readSynchSafeInt()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"readToEnd(DataSource)","url":"readToEnd(com.google.android.exoplayer2.upstream.DataSource)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readUnsignedByte()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableNalUnitBitArray","l":"readUnsignedExpGolombCodedInt()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readUnsignedFixedPoint1616()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readUnsignedInt()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readUnsignedInt24()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readUnsignedIntToInt()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readUnsignedLongToLong()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readUnsignedShort()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"readUtf8EncodedLong()"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil","l":"readVorbisCommentHeader(ParsableByteArray, boolean, boolean)","url":"readVorbisCommentHeader(com.google.android.exoplayer2.util.ParsableByteArray,boolean,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil","l":"readVorbisCommentHeader(ParsableByteArray)","url":"readVorbisCommentHeader(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil","l":"readVorbisIdentificationHeader(ParsableByteArray)","url":"readVorbisIdentificationHeader(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil","l":"readVorbisModes(ParsableByteArray, int)","url":"readVorbisModes(com.google.android.exoplayer2.util.ParsableByteArray,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"realtimeMs"},{"p":"com.google.android.exoplayer2.drm","c":"UnsupportedDrmException","l":"reason"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource.IllegalClippingException","l":"reason"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource.IllegalMergeException","l":"reason"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSourceException","l":"reason"},{"p":"com.google.android.exoplayer2.drm","c":"UnsupportedDrmException","l":"REASON_INSTANTIATION_ERROR"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource.IllegalClippingException","l":"REASON_INVALID_PERIOD_COUNT"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource.IllegalClippingException","l":"REASON_NOT_SEEKABLE_TO_START"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource.IllegalMergeException","l":"REASON_PERIOD_COUNT_MISMATCH"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource.IllegalClippingException","l":"REASON_START_EXCEEDS_END"},{"p":"com.google.android.exoplayer2.drm","c":"UnsupportedDrmException","l":"REASON_UNSUPPORTED_SCHEME"},{"p":"com.google.android.exoplayer2.ui","c":"AdOverlayInfo","l":"reasonDetail"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"recordingDay"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"recordingMonth"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"recordingYear"},{"p":"com.google.android.exoplayer2.source.hls","c":"BundledHlsMediaChunkExtractor","l":"recreate()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaChunkExtractor","l":"recreate()"},{"p":"com.google.android.exoplayer2.source.hls","c":"MediaParserHlsMediaChunkExtractor","l":"recreate()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"recursiveDelete(File)","url":"recursiveDelete(java.io.File)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"reevaluateBuffer(long)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeSequenceableLoader","l":"reevaluateBuffer(long)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"reevaluateBuffer(long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"reevaluateBuffer(long)"},{"p":"com.google.android.exoplayer2.source","c":"SequenceableLoader","l":"reevaluateBuffer(long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"reevaluateBuffer(long)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"reevaluateBuffer(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"reevaluateBuffer(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"reevaluateBuffer(long)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"refreshPlaylist(Uri)","url":"refreshPlaylist(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"refreshPlaylist(Uri)","url":"refreshPlaylist(android.net.Uri)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"refreshSourceInfo(Timeline)","url":"refreshSourceInfo(com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioCapabilitiesReceiver","l":"register()"},{"p":"com.google.android.exoplayer2.util","c":"NetworkTypeObserver","l":"register(NetworkTypeObserver.Listener)","url":"register(com.google.android.exoplayer2.util.NetworkTypeObserver.Listener)"},{"p":"com.google.android.exoplayer2.robolectric","c":"PlaybackOutput","l":"register(SimpleExoPlayer, CapturingRenderersFactory)","url":"register(com.google.android.exoplayer2.SimpleExoPlayer,com.google.android.exoplayer2.testutil.CapturingRenderersFactory)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"registerCustomCommandReceiver(MediaSessionConnector.CommandReceiver)","url":"registerCustomCommandReceiver(com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.CommandReceiver)"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"registerCustomMimeType(String, String, int)","url":"registerCustomMimeType(java.lang.String,java.lang.String,int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayerLibraryInfo","l":"registeredModules()"},{"p":"com.google.android.exoplayer2","c":"ExoPlayerLibraryInfo","l":"registerModule(String)","url":"registerModule(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource","l":"REJECT_PAYWALL_TYPES"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.SegmentBase","l":"relativeDiscontinuitySequence"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.SegmentBase","l":"relativeStartTimeUs"},{"p":"com.google.android.exoplayer2","c":"MediaItem.ClippingProperties","l":"relativeToDefaultPosition"},{"p":"com.google.android.exoplayer2","c":"MediaItem.ClippingProperties","l":"relativeToLiveWindow"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"release()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"release()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"release()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"release()"},{"p":"com.google.android.exoplayer2.decoder","c":"Decoder","l":"release()"},{"p":"com.google.android.exoplayer2.decoder","c":"OutputBuffer","l":"release()"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleDecoder","l":"release()"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleOutputBuffer","l":"release()"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"release()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionManager","l":"release()"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionManager.DrmSessionReference","l":"release()"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"release()"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"release()"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"release()"},{"p":"com.google.android.exoplayer2.drm","c":"OfflineLicenseHelper","l":"release()"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Gav1Decoder","l":"release()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"release()"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacDecoder","l":"release()"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"release()"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusDecoder","l":"release()"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxDecoder","l":"release()"},{"p":"com.google.android.exoplayer2.extractor","c":"Extractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.amr","c":"AmrExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.flac","c":"FlacExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.flv","c":"FlvExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.jpeg","c":"JpegExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.ogg","c":"OggExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.rawcc","c":"RawCcExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Extractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Extractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.extractor.wav","c":"WavExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"release()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"release()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"release()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"release()"},{"p":"com.google.android.exoplayer2.source","c":"BundledExtractorsAdapter","l":"release()"},{"p":"com.google.android.exoplayer2.source","c":"MediaParserExtractorAdapter","l":"release()"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"release()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsLoader","l":"release()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BundledChunkExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"release()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream.EmbeddedSampleStream","l":"release()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSource","l":"release()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaParserChunkExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"release()"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler","l":"release()"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler.PlayerTrackEmsgHandler","l":"release()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"release()"},{"p":"com.google.android.exoplayer2.source.hls","c":"WebvttExtractor","l":"release()"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource","l":"release()"},{"p":"com.google.android.exoplayer2.testutil","c":"DummyMainThread","l":"release()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"release()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource","l":"release()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"release()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"release()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"release()"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"release()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"release()"},{"p":"com.google.android.exoplayer2.text.cea","c":"Cea608Decoder","l":"release()"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"release()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"release()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CachedRegionTracker","l":"release()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"release()"},{"p":"com.google.android.exoplayer2.util","c":"EGLSurfaceTexture","l":"release()"},{"p":"com.google.android.exoplayer2.util","c":"ListenerSet","l":"release()"},{"p":"com.google.android.exoplayer2.video","c":"DummySurface","l":"release()"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"release()"},{"p":"com.google.android.exoplayer2.upstream","c":"Allocator","l":"release(Allocation)","url":"release(com.google.android.exoplayer2.upstream.Allocation)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultAllocator","l":"release(Allocation)","url":"release(com.google.android.exoplayer2.upstream.Allocation)"},{"p":"com.google.android.exoplayer2.upstream","c":"Allocator","l":"release(Allocation[])","url":"release(com.google.android.exoplayer2.upstream.Allocation[])"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultAllocator","l":"release(Allocation[])","url":"release(com.google.android.exoplayer2.upstream.Allocation[])"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"release(ChunkSampleStream.ReleaseCallback)","url":"release(com.google.android.exoplayer2.source.chunk.ChunkSampleStream.ReleaseCallback)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"release(DrmSessionEventListener.EventDispatcher)","url":"release(com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2.drm","c":"ErrorStateDrmSession","l":"release(DrmSessionEventListener.EventDispatcher)","url":"release(com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"release(Loader.ReleaseCallback)","url":"release(com.google.android.exoplayer2.upstream.Loader.ReleaseCallback)"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"releaseChildSource(T)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"releaseCodec()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"releaseCount"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"releaseDay"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"releaseDecoder()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"releaseHoleSpan(CacheSpan)","url":"releaseHoleSpan(com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"releaseHoleSpan(CacheSpan)","url":"releaseHoleSpan(com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.drm","c":"OfflineLicenseHelper","l":"releaseLicense(byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaSource","l":"releaseMediaPeriod(MediaPeriod)","url":"releaseMediaPeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"releaseMediaPeriod(MediaPeriod)","url":"releaseMediaPeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"releaseMonth"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"releaseOutputBuffer(int, boolean)","url":"releaseOutputBuffer(int,boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"releaseOutputBuffer(int, boolean)","url":"releaseOutputBuffer(int,boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"releaseOutputBuffer(int, long)","url":"releaseOutputBuffer(int,long)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"releaseOutputBuffer(int, long)","url":"releaseOutputBuffer(int,long)"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleDecoder","l":"releaseOutputBuffer(O)"},{"p":"com.google.android.exoplayer2.decoder","c":"OutputBuffer.Owner","l":"releaseOutputBuffer(S)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Gav1Decoder","l":"releaseOutputBuffer(VideoDecoderOutputBuffer)","url":"releaseOutputBuffer(com.google.android.exoplayer2.video.VideoDecoderOutputBuffer)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxDecoder","l":"releaseOutputBuffer(VideoDecoderOutputBuffer)","url":"releaseOutputBuffer(com.google.android.exoplayer2.video.VideoDecoderOutputBuffer)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"releasePeriod()"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source","c":"LoopingMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"releasePeriod(MediaPeriod)","url":"releasePeriod(com.google.android.exoplayer2.source.MediaPeriod)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"releaseSource()"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"releaseSource(MediaSource.MediaSourceCaller)","url":"releaseSource(com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"releaseSource(MediaSource.MediaSourceCaller)","url":"releaseSource(com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source","c":"CompositeMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source","c":"MergingMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"releaseSourceInternal()"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"releaseYear"},{"p":"com.google.android.exoplayer2","c":"Timeline.RemotableTimeline","l":"RemotableTimeline(ImmutableList, ImmutableList, int[])","url":"%3Cinit%3E(com.google.common.collect.ImmutableList,com.google.common.collect.ImmutableList,int[])"},{"p":"com.google.android.exoplayer2.offline","c":"Downloader","l":"remove()"},{"p":"com.google.android.exoplayer2.offline","c":"ProgressiveDownloader","l":"remove()"},{"p":"com.google.android.exoplayer2.offline","c":"SegmentDownloader","l":"remove()"},{"p":"com.google.android.exoplayer2.util","c":"IntArrayQueue","l":"remove()"},{"p":"com.google.android.exoplayer2.util","c":"CopyOnWriteMultiset","l":"remove(E)"},{"p":"com.google.android.exoplayer2","c":"Player.Commands.Builder","l":"remove(int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor.QueueDataAdapter","l":"remove(int)"},{"p":"com.google.android.exoplayer2.util","c":"FlagSet.Builder","l":"remove(int)"},{"p":"com.google.android.exoplayer2.util","c":"PriorityTaskManager","l":"remove(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.RequestProperties","l":"remove(String)","url":"remove(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadataMutations","l":"remove(String)","url":"remove(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"ListenerSet","l":"remove(T)"},{"p":"com.google.android.exoplayer2","c":"Player.Commands.Builder","l":"removeAll(int...)"},{"p":"com.google.android.exoplayer2.util","c":"FlagSet.Builder","l":"removeAll(int...)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"removeAllDownloads()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"removeAnalyticsListener(AnalyticsListener)","url":"removeAnalyticsListener(com.google.android.exoplayer2.analytics.AnalyticsListener)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioComponent","l":"removeAudioListener(AudioListener)","url":"removeAudioListener(com.google.android.exoplayer2.audio.AudioListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"removeAudioListener(AudioListener)","url":"removeAudioListener(com.google.android.exoplayer2.audio.AudioListener)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"removeAudioOffloadListener(ExoPlayer.AudioOffloadListener)","url":"removeAudioOffloadListener(com.google.android.exoplayer2.ExoPlayer.AudioOffloadListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"removeAudioOffloadListener(ExoPlayer.AudioOffloadListener)","url":"removeAudioOffloadListener(com.google.android.exoplayer2.ExoPlayer.AudioOffloadListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"removeAudioOffloadListener(ExoPlayer.AudioOffloadListener)","url":"removeAudioOffloadListener(com.google.android.exoplayer2.ExoPlayer.AudioOffloadListener)"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"removeCallbacksAndMessages(Object)","url":"removeCallbacksAndMessages(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"removedAdGroupCount"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.DeviceComponent","l":"removeDeviceListener(DeviceListener)","url":"removeDeviceListener(com.google.android.exoplayer2.device.DeviceListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"removeDeviceListener(DeviceListener)","url":"removeDeviceListener(com.google.android.exoplayer2.device.DeviceListener)"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloadIndex","l":"removeDownload(String)","url":"removeDownload(java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"removeDownload(String)","url":"removeDownload(java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"WritableDownloadIndex","l":"removeDownload(String)","url":"removeDownload(java.lang.String)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"removeDrmEventListener(DrmSessionEventListener)","url":"removeDrmEventListener(com.google.android.exoplayer2.drm.DrmSessionEventListener)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"removeDrmEventListener(DrmSessionEventListener)","url":"removeDrmEventListener(com.google.android.exoplayer2.drm.DrmSessionEventListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"BandwidthMeter","l":"removeEventListener(BandwidthMeter.EventListener)","url":"removeEventListener(com.google.android.exoplayer2.upstream.BandwidthMeter.EventListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"removeEventListener(BandwidthMeter.EventListener)","url":"removeEventListener(com.google.android.exoplayer2.upstream.BandwidthMeter.EventListener)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener.EventDispatcher","l":"removeEventListener(DrmSessionEventListener)","url":"removeEventListener(com.google.android.exoplayer2.drm.DrmSessionEventListener)"},{"p":"com.google.android.exoplayer2.source","c":"BaseMediaSource","l":"removeEventListener(MediaSourceEventListener)","url":"removeEventListener(com.google.android.exoplayer2.source.MediaSourceEventListener)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSource","l":"removeEventListener(MediaSourceEventListener)","url":"removeEventListener(com.google.android.exoplayer2.source.MediaSourceEventListener)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"removeEventListener(MediaSourceEventListener)","url":"removeEventListener(com.google.android.exoplayer2.source.MediaSourceEventListener)"},{"p":"com.google.android.exoplayer2","c":"Player.Commands.Builder","l":"removeIf(int, boolean)","url":"removeIf(int,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"FlagSet.Builder","l":"removeIf(int, boolean)","url":"removeIf(int,boolean)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"removeListener(AnalyticsListener)","url":"removeListener(com.google.android.exoplayer2.analytics.AnalyticsListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"BandwidthMeter.EventListener.EventDispatcher","l":"removeListener(BandwidthMeter.EventListener)","url":"removeListener(com.google.android.exoplayer2.upstream.BandwidthMeter.EventListener)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"removeListener(DownloadManager.Listener)","url":"removeListener(com.google.android.exoplayer2.offline.DownloadManager.Listener)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"removeListener(HlsPlaylistTracker.PlaylistEventListener)","url":"removeListener(com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker.PlaylistEventListener)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"removeListener(HlsPlaylistTracker.PlaylistEventListener)","url":"removeListener(com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker.PlaylistEventListener)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"removeListener(Player.EventListener)","url":"removeListener(com.google.android.exoplayer2.Player.EventListener)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"removeListener(Player.EventListener)","url":"removeListener(com.google.android.exoplayer2.Player.EventListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"removeListener(Player.EventListener)","url":"removeListener(com.google.android.exoplayer2.Player.EventListener)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"removeListener(Player.EventListener)","url":"removeListener(com.google.android.exoplayer2.Player.EventListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"removeListener(Player.EventListener)","url":"removeListener(com.google.android.exoplayer2.Player.EventListener)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"removeListener(Player.Listener)","url":"removeListener(com.google.android.exoplayer2.Player.Listener)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"removeListener(Player.Listener)","url":"removeListener(com.google.android.exoplayer2.Player.Listener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"removeListener(Player.Listener)","url":"removeListener(com.google.android.exoplayer2.Player.Listener)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"removeListener(Player.Listener)","url":"removeListener(com.google.android.exoplayer2.Player.Listener)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"removeListener(Player.Listener)","url":"removeListener(com.google.android.exoplayer2.Player.Listener)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"removeListener(String, Cache.Listener)","url":"removeListener(java.lang.String,com.google.android.exoplayer2.upstream.cache.Cache.Listener)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"removeListener(String, Cache.Listener)","url":"removeListener(java.lang.String,com.google.android.exoplayer2.upstream.cache.Cache.Listener)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"removeListener(TimeBar.OnScrubListener)","url":"removeListener(com.google.android.exoplayer2.ui.TimeBar.OnScrubListener)"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar","l":"removeListener(TimeBar.OnScrubListener)","url":"removeListener(com.google.android.exoplayer2.ui.TimeBar.OnScrubListener)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"removeMediaItem(int)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"removeMediaItem(int)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"removeMediaItem(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"removeMediaItem(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.RemoveMediaItem","l":"RemoveMediaItem(String, int)","url":"%3Cinit%3E(java.lang.String,int)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"removeMediaItems(int, int)","url":"removeMediaItems(int,int)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"removeMediaItems(int, int)","url":"removeMediaItems(int,int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"removeMediaItems(int, int)","url":"removeMediaItems(int,int)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"removeMediaItems(int, int)","url":"removeMediaItems(int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"removeMediaItems(int, int)","url":"removeMediaItems(int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"removeMediaItems(int, int)","url":"removeMediaItems(int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.RemoveMediaItems","l":"RemoveMediaItems(String, int, int)","url":"%3Cinit%3E(java.lang.String,int,int)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"removeMediaSource(int, Handler, Runnable)","url":"removeMediaSource(int,android.os.Handler,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"removeMediaSource(int)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"removeMediaSourceRange(int, int, Handler, Runnable)","url":"removeMediaSourceRange(int,int,android.os.Handler,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"removeMediaSourceRange(int, int)","url":"removeMediaSourceRange(int,int)"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"removeMessages(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.MetadataComponent","l":"removeMetadataOutput(MetadataOutput)","url":"removeMetadataOutput(com.google.android.exoplayer2.metadata.MetadataOutput)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"removeMetadataOutput(MetadataOutput)","url":"removeMetadataOutput(com.google.android.exoplayer2.metadata.MetadataOutput)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"removePlaylistItem(int)"},{"p":"com.google.android.exoplayer2.util","c":"UriUtil","l":"removeQueryParameter(Uri, String)","url":"removeQueryParameter(android.net.Uri,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"removeRange(List, int, int)","url":"removeRange(java.util.List,int,int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"removeResource(String)","url":"removeResource(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"removeResource(String)","url":"removeResource(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"removeSpan(CacheSpan)","url":"removeSpan(com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"removeSpan(CacheSpan)","url":"removeSpan(com.google.android.exoplayer2.upstream.cache.CacheSpan)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.TextComponent","l":"removeTextOutput(TextOutput)","url":"removeTextOutput(com.google.android.exoplayer2.text.TextOutput)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"removeTextOutput(TextOutput)","url":"removeTextOutput(com.google.android.exoplayer2.text.TextOutput)"},{"p":"com.google.android.exoplayer2.database","c":"VersionTable","l":"removeVersion(SQLiteDatabase, int, String)","url":"removeVersion(android.database.sqlite.SQLiteDatabase,int,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"removeVideoListener(VideoListener)","url":"removeVideoListener(com.google.android.exoplayer2.video.VideoListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"removeVideoListener(VideoListener)","url":"removeVideoListener(com.google.android.exoplayer2.video.VideoListener)"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView","l":"removeVideoSurfaceListener(SphericalGLSurfaceView.VideoSurfaceListener)","url":"removeVideoSurfaceListener(com.google.android.exoplayer2.video.spherical.SphericalGLSurfaceView.VideoSurfaceListener)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"removeVisibilityListener(PlayerControlView.VisibilityListener)","url":"removeVisibilityListener(com.google.android.exoplayer2.ui.PlayerControlView.VisibilityListener)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"removeVisibilityListener(StyledPlayerControlView.VisibilityListener)","url":"removeVisibilityListener(com.google.android.exoplayer2.ui.StyledPlayerControlView.VisibilityListener)"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"render(long, long)","url":"render(long,long)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"render(long, long)","url":"render(long,long)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"render(long, long)","url":"render(long,long)"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataRenderer","l":"render(long, long)","url":"render(long,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"render(long, long)","url":"render(long,long)"},{"p":"com.google.android.exoplayer2.text","c":"TextRenderer","l":"render(long, long)","url":"render(long,long)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"render(long, long)","url":"render(long,long)"},{"p":"com.google.android.exoplayer2.video.spherical","c":"CameraMotionRenderer","l":"render(long, long)","url":"render(long,long)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener.EventDispatcher","l":"renderedFirstFrame(Object)","url":"renderedFirstFrame(java.lang.Object)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"renderedOutputBufferCount"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"RENDERER_SUPPORT_EXCEEDS_CAPABILITIES_TRACKS"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"RENDERER_SUPPORT_NO_TRACKS"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"RENDERER_SUPPORT_PLAYABLE_TRACKS"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector.MappedTrackInfo","l":"RENDERER_SUPPORT_UNSUPPORTED_TRACKS"},{"p":"com.google.android.exoplayer2","c":"RendererConfiguration","l":"RendererConfiguration(boolean)","url":"%3Cinit%3E(boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectorResult","l":"rendererConfigurations"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"rendererFormat"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"rendererFormatSupport"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"rendererIndex"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"rendererName"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"renderers"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"renderOutputBuffer(MediaCodecAdapter, int, long)","url":"renderOutputBuffer(com.google.android.exoplayer2.mediacodec.MediaCodecAdapter,int,long)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"renderOutputBuffer(VideoDecoderOutputBuffer, long, Format)","url":"renderOutputBuffer(com.google.android.exoplayer2.video.VideoDecoderOutputBuffer,long,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Libgav1VideoRenderer","l":"renderOutputBufferToSurface(VideoDecoderOutputBuffer, Surface)","url":"renderOutputBufferToSurface(com.google.android.exoplayer2.video.VideoDecoderOutputBuffer,android.view.Surface)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"LibvpxVideoRenderer","l":"renderOutputBufferToSurface(VideoDecoderOutputBuffer, Surface)","url":"renderOutputBufferToSurface(com.google.android.exoplayer2.video.VideoDecoderOutputBuffer,android.view.Surface)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"renderOutputBufferToSurface(VideoDecoderOutputBuffer, Surface)","url":"renderOutputBufferToSurface(com.google.android.exoplayer2.video.VideoDecoderOutputBuffer,android.view.Surface)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"renderOutputBufferV21(MediaCodecAdapter, int, long, long)","url":"renderOutputBufferV21(com.google.android.exoplayer2.mediacodec.MediaCodecAdapter,int,long,long)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"renderToEndOfStream()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"renderToEndOfStream()"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Gav1Decoder","l":"renderToSurface(VideoDecoderOutputBuffer, Surface)","url":"renderToSurface(com.google.android.exoplayer2.video.VideoDecoderOutputBuffer,android.view.Surface)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxDecoder","l":"renderToSurface(VideoDecoderOutputBuffer, Surface)","url":"renderToSurface(com.google.android.exoplayer2.video.VideoDecoderOutputBuffer,android.view.Surface)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Rendition","l":"Rendition(Uri, Format, String, String)","url":"%3Cinit%3E(android.net.Uri,com.google.android.exoplayer2.Format,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.RenditionReport","l":"RenditionReport(Uri, long, int)","url":"%3Cinit%3E(android.net.Uri,long,int)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"renditionReports"},{"p":"com.google.android.exoplayer2.drm","c":"OfflineLicenseHelper","l":"renewLicense(byte[])"},{"p":"com.google.android.exoplayer2","c":"Player","l":"REPEAT_MODE_ALL"},{"p":"com.google.android.exoplayer2","c":"Player","l":"REPEAT_MODE_OFF"},{"p":"com.google.android.exoplayer2","c":"Player","l":"REPEAT_MODE_ONE"},{"p":"com.google.android.exoplayer2.util","c":"RepeatModeUtil","l":"REPEAT_TOGGLE_MODE_ALL"},{"p":"com.google.android.exoplayer2.util","c":"RepeatModeUtil","l":"REPEAT_TOGGLE_MODE_NONE"},{"p":"com.google.android.exoplayer2.util","c":"RepeatModeUtil","l":"REPEAT_TOGGLE_MODE_ONE"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"repeat(Action, long)","url":"repeat(com.google.android.exoplayer2.testutil.Action,long)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"RepeatModeActionProvider","l":"RepeatModeActionProvider(Context, int)","url":"%3Cinit%3E(android.content.Context,int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"RepeatModeActionProvider","l":"RepeatModeActionProvider(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource","l":"replaceManifestUri(Uri)","url":"replaceManifestUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"replaceOutputBuffer(int)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"replacePlaylistItem(int, MediaItem)","url":"replacePlaylistItem(int,androidx.media2.common.MediaItem)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"replaceSession(DrmSession, DrmSession)","url":"replaceSession(com.google.android.exoplayer2.drm.DrmSession,com.google.android.exoplayer2.drm.DrmSession)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"replaceStream(Format[], SampleStream, long, long)","url":"replaceStream(com.google.android.exoplayer2.Format[],com.google.android.exoplayer2.source.SampleStream,long,long)"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"replaceStream(Format[], SampleStream, long, long)","url":"replaceStream(com.google.android.exoplayer2.Format[],com.google.android.exoplayer2.source.SampleStream,long,long)"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"replaceStream(Format[], SampleStream, long, long)","url":"replaceStream(com.google.android.exoplayer2.Format[],com.google.android.exoplayer2.source.SampleStream,long,long)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadHelper","l":"replaceTrackSelections(int, DefaultTrackSelector.Parameters)","url":"replaceTrackSelections(int,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener.EventDispatcher","l":"reportVideoFrameProcessingOffset(long, int)","url":"reportVideoFrameProcessingOffset(long,int)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationHolder","l":"representation"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"representationHolders"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser.RepresentationInfo","l":"RepresentationInfo(Format, List, SegmentBase, String, ArrayList, ArrayList, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format,java.util.List,com.google.android.exoplayer2.source.dash.manifest.SegmentBase,java.lang.String,java.util.ArrayList,java.util.ArrayList,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"AdaptationSet","l":"representations"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationSegmentIterator","l":"RepresentationSegmentIterator(DefaultDashChunkSource.RepresentationHolder, long, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.dash.DefaultDashChunkSource.RepresentationHolder,long,long,long)"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"request"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"REQUEST_HEADER_ENABLE_METADATA_NAME"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"REQUEST_HEADER_ENABLE_METADATA_VALUE"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyRequest","l":"REQUEST_TYPE_INITIAL"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyRequest","l":"REQUEST_TYPE_NONE"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyRequest","l":"REQUEST_TYPE_RELEASE"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyRequest","l":"REQUEST_TYPE_RENEWAL"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyRequest","l":"REQUEST_TYPE_UNKNOWN"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm.KeyRequest","l":"REQUEST_TYPE_UPDATE"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"requestAds(DataSpec, Object, ViewGroup)","url":"requestAds(com.google.android.exoplayer2.upstream.DataSpec,java.lang.Object,android.view.ViewGroup)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.DrmConfiguration","l":"requestHeaders"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.RequestProperties","l":"RequestProperties()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts.RequestSet","l":"RequestSet(FakeDataSet)","url":"%3Cinit%3E(com.google.android.exoplayer2.testutil.FakeDataSet)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer.InsufficientCapacityException","l":"requiredCapacity"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"Requirements(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.scheduler","c":"RequirementsWatcher","l":"RequirementsWatcher(Context, RequirementsWatcher.Listener, Requirements)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.scheduler.RequirementsWatcher.Listener,com.google.android.exoplayer2.scheduler.Requirements)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheEvictor","l":"requiresCacheSpanTouches()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"LeastRecentlyUsedCacheEvictor","l":"requiresCacheSpanTouches()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"NoOpCacheEvictor","l":"requiresCacheSpanTouches()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"reset()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"reset()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"reset()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor","l":"reset()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"reset()"},{"p":"com.google.android.exoplayer2.audio","c":"BaseAudioProcessor","l":"reset()"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"reset()"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"reset()"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"reset()"},{"p":"com.google.android.exoplayer2.ext.gvr","c":"GvrAudioProcessor","l":"reset()"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisBitArray","l":"reset()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"reset()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunkIterator","l":"reset()"},{"p":"com.google.android.exoplayer2.source.chunk","c":"MediaChunkIterator","l":"reset()"},{"p":"com.google.android.exoplayer2.source.dash","c":"BaseUrlExclusionList","l":"reset()"},{"p":"com.google.android.exoplayer2.source.hls","c":"TimestampAdjusterProvider","l":"reset()"},{"p":"com.google.android.exoplayer2.testutil","c":"CapturingAudioSink","l":"reset()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"reset()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"reset()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultAllocator","l":"reset()"},{"p":"com.google.android.exoplayer2.upstream","c":"TimeToFirstByteEstimator","l":"reset()"},{"p":"com.google.android.exoplayer2.util","c":"SlidingPercentile","l":"reset()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"reset(boolean)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableNalUnitBitArray","l":"reset(byte[], int, int)","url":"reset(byte[],int,int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"reset(byte[], int)","url":"reset(byte[],int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"reset(byte[], int)","url":"reset(byte[],int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"reset(byte[])"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"reset(byte[])"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"reset(int)"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"reset(long)"},{"p":"com.google.android.exoplayer2.util","c":"ReusableBufferedOutputStream","l":"reset(OutputStream)","url":"reset(java.io.OutputStream)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"reset(ParsableByteArray)","url":"reset(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.upstream","c":"StatsDataSource","l":"resetBytesRead()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"resetCodecStateForFlush()"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"resetCodecStateForFlush()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"resetCodecStateForRelease()"},{"p":"com.google.android.exoplayer2.util","c":"NetworkTypeObserver","l":"resetForTests()"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"resetPeekPosition()"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"resetPeekPosition()"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"resetPeekPosition()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"resetPeekPosition()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"resetPosition(long)"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"resetPosition(long)"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"resetPosition(long)"},{"p":"com.google.android.exoplayer2.util","c":"StandaloneMediaClock","l":"resetPosition(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"resetProvisioning()"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"resetSupplementalData(int)"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout","l":"RESIZE_MODE_FILL"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout","l":"RESIZE_MODE_FIT"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout","l":"RESIZE_MODE_FIXED_HEIGHT"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout","l":"RESIZE_MODE_FIXED_WIDTH"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout","l":"RESIZE_MODE_ZOOM"},{"p":"com.google.android.exoplayer2.util","c":"UriUtil","l":"resolve(String, String)","url":"resolve(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"ResolvingDataSource.Resolver","l":"resolveDataSpec(DataSpec)","url":"resolveDataSpec(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.upstream","c":"ResolvingDataSource.Resolver","l":"resolveReportedUri(Uri)","url":"resolveReportedUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2","c":"SeekParameters","l":"resolveSeekPositionUs(long, long, long)","url":"resolveSeekPositionUs(long,long,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource","l":"resolvesToUnknownLength()"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource.Builder","l":"resolvesToUnknownLength(boolean)"},{"p":"com.google.android.exoplayer2.util","c":"UriUtil","l":"resolveToUri(String, String)","url":"resolveToUri(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"RangedUri","l":"resolveUri(String)","url":"resolveUri(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"RangedUri","l":"resolveUriString(String)","url":"resolveUriString(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"ResolvingDataSource","l":"ResolvingDataSource(DataSource, ResolvingDataSource.Resolver)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.ResolvingDataSource.Resolver)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"resourceNotFound_transferListenerCallbacks()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"resourceNotFound()"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.InvalidResponseCodeException","l":"responseBody"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.InvalidResponseCodeException","l":"responseCode"},{"p":"com.google.android.exoplayer2.drm","c":"MediaDrmCallbackException","l":"responseHeaders"},{"p":"com.google.android.exoplayer2.source","c":"LoadEventInfo","l":"responseHeaders"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.InvalidResponseCodeException","l":"responseMessage"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"restoreKeys(byte[], byte[])","url":"restoreKeys(byte[],byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"restoreKeys(byte[], byte[])","url":"restoreKeys(byte[],byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"restoreKeys(byte[], byte[])","url":"restoreKeys(byte[],byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"restoreKeys(byte[], byte[])","url":"restoreKeys(byte[],byte[])"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"result"},{"p":"com.google.android.exoplayer2","c":"C","l":"RESULT_BUFFER_READ"},{"p":"com.google.android.exoplayer2.extractor","c":"Extractor","l":"RESULT_CONTINUE"},{"p":"com.google.android.exoplayer2","c":"C","l":"RESULT_END_OF_INPUT"},{"p":"com.google.android.exoplayer2.extractor","c":"Extractor","l":"RESULT_END_OF_INPUT"},{"p":"com.google.android.exoplayer2","c":"C","l":"RESULT_FORMAT_READ"},{"p":"com.google.android.exoplayer2","c":"C","l":"RESULT_MAX_LENGTH_EXCEEDED"},{"p":"com.google.android.exoplayer2","c":"C","l":"RESULT_NOTHING_READ"},{"p":"com.google.android.exoplayer2.extractor","c":"Extractor","l":"RESULT_SEEK"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"resumeDownloads()"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"retainBackBufferFromKeyframe()"},{"p":"com.google.android.exoplayer2","c":"LoadControl","l":"retainBackBufferFromKeyframe()"},{"p":"com.google.android.exoplayer2","c":"MetadataRetriever","l":"retrieveMetadata(Context, MediaItem)","url":"retrieveMetadata(android.content.Context,com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2","c":"MetadataRetriever","l":"retrieveMetadata(MediaSourceFactory, MediaItem)","url":"retrieveMetadata(com.google.android.exoplayer2.source.MediaSourceFactory,com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"RETRY"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"RETRY_RESET_ERROR_COUNT"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"retry()"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"retry()"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"retry()"},{"p":"com.google.android.exoplayer2.util","c":"ReusableBufferedOutputStream","l":"ReusableBufferedOutputStream(OutputStream, int)","url":"%3Cinit%3E(java.io.OutputStream,int)"},{"p":"com.google.android.exoplayer2.util","c":"ReusableBufferedOutputStream","l":"ReusableBufferedOutputStream(OutputStream)","url":"%3Cinit%3E(java.io.OutputStream)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"REUSE_RESULT_NO"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"REUSE_RESULT_YES_WITH_FLUSH"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"REUSE_RESULT_YES_WITH_RECONFIGURATION"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderReuseEvaluation","l":"REUSE_RESULT_YES_WITHOUT_RECONFIGURATION"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"REVISION_ID_DEFAULT"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser.RepresentationInfo","l":"revisionId"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation","l":"revisionId"},{"p":"com.google.android.exoplayer2.audio","c":"WavUtil","l":"RIFF_FOURCC"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_ALTERNATE"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_CAPTION"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_COMMENTARY"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_DESCRIBES_VIDEO"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_DUB"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_EASY_TO_READ"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_EMERGENCY"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_ENHANCED_DIALOG_INTELLIGIBILITY"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_MAIN"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_SIGN"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_SUBTITLE"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_SUPPLEMENTARY"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_TRANSCRIBES_DIALOG"},{"p":"com.google.android.exoplayer2","c":"C","l":"ROLE_FLAG_TRICK_PLAY"},{"p":"com.google.android.exoplayer2","c":"Format","l":"roleFlags"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Subtitle","l":"roleFlags"},{"p":"com.google.android.exoplayer2","c":"Format","l":"rotationDegrees"},{"p":"com.google.android.exoplayer2.ext.rtmp","c":"RtmpDataSource","l":"RtmpDataSource()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.rtmp","c":"RtmpDataSourceFactory","l":"RtmpDataSourceFactory()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.rtmp","c":"RtmpDataSourceFactory","l":"RtmpDataSourceFactory(TransferListener)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"RTP_VERSION"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","c":"RtpAc3Reader","l":"RtpAc3Reader(RtpPayloadFormat)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.rtsp.RtpPayloadFormat)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPayloadFormat","l":"RtpPayloadFormat(Format, int, int, Map)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format,int,int,java.util.Map)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPayloadFormat","l":"rtpPayloadType"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.RtspPlaybackException","l":"RtspPlaybackException(String, Throwable)","url":"%3Cinit%3E(java.lang.String,java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.RtspPlaybackException","l":"RtspPlaybackException(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.RtspPlaybackException","l":"RtspPlaybackException(Throwable)","url":"%3Cinit%3E(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.text.span","c":"RubySpan","l":"RubySpan(String, int)","url":"%3Cinit%3E(java.lang.String,int)"},{"p":"com.google.android.exoplayer2.text.span","c":"RubySpan","l":"rubyText"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"run()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.PlayerRunnable","l":"run()"},{"p":"com.google.android.exoplayer2.testutil","c":"DummyMainThread.TestRunnable","l":"run()"},{"p":"com.google.android.exoplayer2.util","c":"DebugTextViewHelper","l":"run()"},{"p":"com.google.android.exoplayer2.util","c":"EGLSurfaceTexture","l":"run()"},{"p":"com.google.android.exoplayer2.util","c":"RunnableFutureTask","l":"run()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.PlayerRunnable","l":"run(SimpleExoPlayer)","url":"run(com.google.android.exoplayer2.SimpleExoPlayer)"},{"p":"com.google.android.exoplayer2.robolectric","c":"RobolectricUtil","l":"runLooperUntil(Looper, Supplier, long, Clock)","url":"runLooperUntil(android.os.Looper,com.google.common.base.Supplier,long,com.google.android.exoplayer2.util.Clock)"},{"p":"com.google.android.exoplayer2.robolectric","c":"RobolectricUtil","l":"runLooperUntil(Looper, Supplier)","url":"runLooperUntil(android.os.Looper,com.google.common.base.Supplier)"},{"p":"com.google.android.exoplayer2.robolectric","c":"RobolectricUtil","l":"runMainLooperUntil(Supplier, long, Clock)","url":"runMainLooperUntil(com.google.common.base.Supplier,long,com.google.android.exoplayer2.util.Clock)"},{"p":"com.google.android.exoplayer2.robolectric","c":"RobolectricUtil","l":"runMainLooperUntil(Supplier)","url":"runMainLooperUntil(com.google.common.base.Supplier)"},{"p":"com.google.android.exoplayer2.util","c":"RunnableFutureTask","l":"RunnableFutureTask()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.testutil","c":"DummyMainThread","l":"runOnMainThread(int, Runnable)","url":"runOnMainThread(int,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.testutil","c":"DummyMainThread","l":"runOnMainThread(Runnable)","url":"runOnMainThread(java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"runOnPlaybackThread(Runnable)","url":"runOnPlaybackThread(java.lang.Runnable)"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity","l":"runTest(HostActivity.HostedTest, long, boolean)","url":"runTest(com.google.android.exoplayer2.testutil.HostActivity.HostedTest,long,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity","l":"runTest(HostActivity.HostedTest, long)","url":"runTest(com.google.android.exoplayer2.testutil.HostActivity.HostedTest,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"DummyMainThread","l":"runTestOnMainThread(DummyMainThread.TestRunnable)","url":"runTestOnMainThread(com.google.android.exoplayer2.testutil.DummyMainThread.TestRunnable)"},{"p":"com.google.android.exoplayer2.testutil","c":"DummyMainThread","l":"runTestOnMainThread(int, DummyMainThread.TestRunnable)","url":"runTestOnMainThread(int,com.google.android.exoplayer2.testutil.DummyMainThread.TestRunnable)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestPlayerRunHelper","l":"runUntilError(ExoPlayer)","url":"runUntilError(com.google.android.exoplayer2.ExoPlayer)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestPlayerRunHelper","l":"runUntilPendingCommandsAreFullyHandled(ExoPlayer)","url":"runUntilPendingCommandsAreFullyHandled(com.google.android.exoplayer2.ExoPlayer)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestPlayerRunHelper","l":"runUntilPlaybackState(Player, int)","url":"runUntilPlaybackState(com.google.android.exoplayer2.Player,int)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestPlayerRunHelper","l":"runUntilPlayWhenReady(Player, boolean)","url":"runUntilPlayWhenReady(com.google.android.exoplayer2.Player,boolean)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestPlayerRunHelper","l":"runUntilPositionDiscontinuity(Player, int)","url":"runUntilPositionDiscontinuity(com.google.android.exoplayer2.Player,int)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestPlayerRunHelper","l":"runUntilReceiveOffloadSchedulingEnabledNewState(ExoPlayer)","url":"runUntilReceiveOffloadSchedulingEnabledNewState(com.google.android.exoplayer2.ExoPlayer)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestPlayerRunHelper","l":"runUntilRenderedFirstFrame(SimpleExoPlayer)","url":"runUntilRenderedFirstFrame(com.google.android.exoplayer2.SimpleExoPlayer)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestPlayerRunHelper","l":"runUntilSleepingForOffload(ExoPlayer, boolean)","url":"runUntilSleepingForOffload(com.google.android.exoplayer2.ExoPlayer,boolean)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestPlayerRunHelper","l":"runUntilTimelineChanged(Player, Timeline)","url":"runUntilTimelineChanged(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestPlayerRunHelper","l":"runUntilTimelineChanged(Player)","url":"runUntilTimelineChanged(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector.MediaMetadataProvider","l":"sameAs(MediaMetadataCompat, MediaMetadataCompat)","url":"sameAs(android.support.v4.media.MediaMetadataCompat,android.support.v4.media.MediaMetadataCompat)"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput","l":"SAMPLE_DATA_PART_ENCRYPTION"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput","l":"SAMPLE_DATA_PART_MAIN"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput","l":"SAMPLE_DATA_PART_SUPPLEMENTAL"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util","l":"SAMPLE_HEADER_SIZE"},{"p":"com.google.android.exoplayer2.audio","c":"OpusUtil","l":"SAMPLE_RATE"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"SAMPLE_RATE_NO_CHANGE"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream.FakeSampleStreamItem","l":"sample(long, int, byte[])","url":"sample(long,int,byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"sampleBufferReadCount"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util.SyncFrameInfo","l":"sampleCount"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util.SyncFrameInfo","l":"sampleCount"},{"p":"com.google.android.exoplayer2.extractor","c":"DummyTrackOutput","l":"sampleData(DataReader, int, boolean, int)","url":"sampleData(com.google.android.exoplayer2.upstream.DataReader,int,boolean,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput","l":"sampleData(DataReader, int, boolean, int)","url":"sampleData(com.google.android.exoplayer2.upstream.DataReader,int,boolean,int)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"sampleData(DataReader, int, boolean, int)","url":"sampleData(com.google.android.exoplayer2.upstream.DataReader,int,boolean,int)"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler.PlayerTrackEmsgHandler","l":"sampleData(DataReader, int, boolean, int)","url":"sampleData(com.google.android.exoplayer2.upstream.DataReader,int,boolean,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"sampleData(DataReader, int, boolean, int)","url":"sampleData(com.google.android.exoplayer2.upstream.DataReader,int,boolean,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput","l":"sampleData(DataReader, int, boolean)","url":"sampleData(com.google.android.exoplayer2.upstream.DataReader,int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"DummyTrackOutput","l":"sampleData(ParsableByteArray, int, int)","url":"sampleData(com.google.android.exoplayer2.util.ParsableByteArray,int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput","l":"sampleData(ParsableByteArray, int, int)","url":"sampleData(com.google.android.exoplayer2.util.ParsableByteArray,int,int)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"sampleData(ParsableByteArray, int, int)","url":"sampleData(com.google.android.exoplayer2.util.ParsableByteArray,int,int)"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler.PlayerTrackEmsgHandler","l":"sampleData(ParsableByteArray, int, int)","url":"sampleData(com.google.android.exoplayer2.util.ParsableByteArray,int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"sampleData(ParsableByteArray, int, int)","url":"sampleData(com.google.android.exoplayer2.util.ParsableByteArray,int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput","l":"sampleData(ParsableByteArray, int)","url":"sampleData(com.google.android.exoplayer2.util.ParsableByteArray,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"DummyTrackOutput","l":"sampleMetadata(long, int, int, int, TrackOutput.CryptoData)","url":"sampleMetadata(long,int,int,int,com.google.android.exoplayer2.extractor.TrackOutput.CryptoData)"},{"p":"com.google.android.exoplayer2.extractor","c":"TrackOutput","l":"sampleMetadata(long, int, int, int, TrackOutput.CryptoData)","url":"sampleMetadata(long,int,int,int,com.google.android.exoplayer2.extractor.TrackOutput.CryptoData)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"sampleMetadata(long, int, int, int, TrackOutput.CryptoData)","url":"sampleMetadata(long,int,int,int,com.google.android.exoplayer2.extractor.TrackOutput.CryptoData)"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler.PlayerTrackEmsgHandler","l":"sampleMetadata(long, int, int, int, TrackOutput.CryptoData)","url":"sampleMetadata(long,int,int,int,com.google.android.exoplayer2.extractor.TrackOutput.CryptoData)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackOutput","l":"sampleMetadata(long, int, int, int, TrackOutput.CryptoData)","url":"sampleMetadata(long,int,int,int,com.google.android.exoplayer2.extractor.TrackOutput.CryptoData)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"sampleMimeType"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacFrameReader.SampleNumberHolder","l":"sampleNumber"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacFrameReader.SampleNumberHolder","l":"SampleNumberHolder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"SampleQueue(Allocator, Looper, DrmSessionManager, DrmSessionEventListener.EventDispatcher)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.Allocator,android.os.Looper,com.google.android.exoplayer2.drm.DrmSessionManager,com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher)"},{"p":"com.google.android.exoplayer2.source.hls","c":"SampleQueueMappingException","l":"SampleQueueMappingException(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"sampleRate"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util.SyncFrameInfo","l":"sampleRate"},{"p":"com.google.android.exoplayer2.audio","c":"Ac4Util.SyncFrameInfo","l":"sampleRate"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor.AudioFormat","l":"sampleRate"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil.Header","l":"sampleRate"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"sampleRate"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.VorbisIdHeader","l":"sampleRate"},{"p":"com.google.android.exoplayer2.audio","c":"AacUtil.Config","l":"sampleRateHz"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"sampleRateLookupKey"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil.Header","l":"samplesPerFrame"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"sampleTransformation"},{"p":"com.google.android.exoplayer2","c":"C","l":"SANS_SERIF_NAME"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"scaleLargeTimestamp(long, long, long)","url":"scaleLargeTimestamp(long,long,long)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"scaleLargeTimestamps(List, long, long)","url":"scaleLargeTimestamps(java.util.List,long,long)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"scaleLargeTimestampsInPlace(long[], long, long)","url":"scaleLargeTimestampsInPlace(long[],long,long)"},{"p":"com.google.android.exoplayer2.ext.workmanager","c":"WorkManagerScheduler","l":"schedule(Requirements, String, String)","url":"schedule(com.google.android.exoplayer2.scheduler.Requirements,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.scheduler","c":"PlatformScheduler","l":"schedule(Requirements, String, String)","url":"schedule(com.google.android.exoplayer2.scheduler.Requirements,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.scheduler","c":"Scheduler","l":"schedule(Requirements, String, String)","url":"schedule(com.google.android.exoplayer2.scheduler.Requirements,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.workmanager","c":"WorkManagerScheduler.SchedulerWorker","l":"SchedulerWorker(Context, WorkerParameters)","url":"%3Cinit%3E(android.content.Context,androidx.work.WorkerParameters)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSchemeDataSource","l":"SCHEME_DATA"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"SchemeData(UUID, String, byte[])","url":"%3Cinit%3E(java.util.UUID,java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"SchemeData(UUID, String, String, byte[])","url":"%3Cinit%3E(java.util.UUID,java.lang.String,java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"schemeDataCount"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"schemeIdUri"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Descriptor","l":"schemeIdUri"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"EventStream","l":"schemeIdUri"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"UtcTimingElement","l":"schemeIdUri"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"schemeType"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"TrackEncryptionBox","l":"schemeType"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"SCTE35_SCHEME_ID"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"SDK_INT"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.TimestampSeeker","l":"searchForTimestamp(ExtractorInput, long)","url":"searchForTimestamp(com.google.android.exoplayer2.extractor.ExtractorInput,long)"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap.SeekPoints","l":"second"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"SectionReader","l":"SectionReader(SectionPayloadReader)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.ts.SectionPayloadReader)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"secure"},{"p":"com.google.android.exoplayer2.video","c":"DummySurface","l":"secure"},{"p":"com.google.android.exoplayer2.util","c":"EGLSurfaceTexture","l":"SECURE_MODE_NONE"},{"p":"com.google.android.exoplayer2.util","c":"EGLSurfaceTexture","l":"SECURE_MODE_PROTECTED_PBUFFER"},{"p":"com.google.android.exoplayer2.util","c":"EGLSurfaceTexture","l":"SECURE_MODE_SURFACELESS_CONTEXT"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer.DecoderInitializationException","l":"secureDecoderRequired"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Reader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Reader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsReader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DtsReader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"DvbSubtitleReader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"ElementaryStreamReader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H262Reader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H263Reader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H264Reader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"H265Reader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Id3Reader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"LatmReader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"MpegAudioReader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PesReader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"SectionReader","l":"seek()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader","l":"seek()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"seek(int, long, boolean)","url":"seek(int,long,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"seek(int, long)","url":"seek(int,long)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor","c":"Extractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.amr","c":"AmrExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.flac","c":"FlacExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.flv","c":"FlvExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.jpeg","c":"JpegExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.ogg","c":"OggExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.rawcc","c":"RawCcExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Extractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Extractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.extractor.wav","c":"WavExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.source","c":"BundledExtractorsAdapter","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaParserExtractorAdapter","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.source.hls","c":"WebvttExtractor","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","c":"RtpAc3Reader","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","c":"RtpPayloadReader","l":"seek(long, long)","url":"seek(long,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"seek(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.Seek","l":"Seek(String, int, long, boolean)","url":"%3Cinit%3E(java.lang.String,int,long,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.Seek","l":"Seek(String, long)","url":"%3Cinit%3E(java.lang.String,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"seekAndWait(long)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"seekBack()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"seekBack()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"seekBack()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"seekForward()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"seekForward()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"seekForward()"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"seekMap"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorOutput","l":"seekMap"},{"p":"com.google.android.exoplayer2.extractor","c":"DummyExtractorOutput","l":"seekMap(SeekMap)","url":"seekMap(com.google.android.exoplayer2.extractor.SeekMap)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorOutput","l":"seekMap(SeekMap)","url":"seekMap(com.google.android.exoplayer2.extractor.SeekMap)"},{"p":"com.google.android.exoplayer2.extractor.jpeg","c":"StartOffsetExtractorOutput","l":"seekMap(SeekMap)","url":"seekMap(com.google.android.exoplayer2.extractor.SeekMap)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BundledChunkExtractor","l":"seekMap(SeekMap)","url":"seekMap(com.google.android.exoplayer2.extractor.SeekMap)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorOutput","l":"seekMap(SeekMap)","url":"seekMap(com.google.android.exoplayer2.extractor.SeekMap)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"seekOperationParams"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.SeekOperationParams","l":"SeekOperationParams(long, long, long, long, long, long, long)","url":"%3Cinit%3E(long,long,long,long,long,long,long)"},{"p":"com.google.android.exoplayer2","c":"SeekParameters","l":"SeekParameters(long, long)","url":"%3Cinit%3E(long,long)"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekPoint","l":"SeekPoint(long, long)","url":"%3Cinit%3E(long,long)"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap.SeekPoints","l":"SeekPoints(SeekPoint, SeekPoint)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.SeekPoint,com.google.android.exoplayer2.extractor.SeekPoint)"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap.SeekPoints","l":"SeekPoints(SeekPoint)","url":"%3Cinit%3E(com.google.android.exoplayer2.extractor.SeekPoint)"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"seekTable"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata.SeekTable","l":"SeekTable(long[], long[])","url":"%3Cinit%3E(long[],long[])"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"seekTo(int, long)","url":"seekTo(int,long)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"seekTo(int, long)","url":"seekTo(int,long)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"seekTo(int, long)","url":"seekTo(int,long)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"seekTo(int, long)","url":"seekTo(int,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"seekTo(int, long)","url":"seekTo(int,long)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"seekTo(int)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"seekTo(long, boolean)","url":"seekTo(long,boolean)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"seekTo(long)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"seekTo(long)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"seekTo(long)"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"seekTo(long)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"seekTo(long)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"seekToDefaultPosition()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"seekToDefaultPosition()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"seekToDefaultPosition()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"seekToDefaultPosition(int)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"seekToDefaultPosition(int)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"seekToDefaultPosition(int)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"seekToNext()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"seekToNext()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"seekToNext()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"seekToNextWindow()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"seekToNextWindow()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"seekToNextWindow()"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"seekToPosition(ExtractorInput, long, PositionHolder)","url":"seekToPosition(com.google.android.exoplayer2.extractor.ExtractorInput,long,com.google.android.exoplayer2.extractor.PositionHolder)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"InputReaderAdapterV30","l":"seekToPosition(long)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"seekToPrevious()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"seekToPrevious()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"seekToPrevious()"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"seekToPreviousWindow()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"seekToPreviousWindow()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"seekToPreviousWindow()"},{"p":"com.google.android.exoplayer2.testutil","c":"TestUtil","l":"seekToTimeUs(Extractor, SeekMap, long, DataSource, FakeTrackOutput, Uri)","url":"seekToTimeUs(com.google.android.exoplayer2.extractor.Extractor,com.google.android.exoplayer2.extractor.SeekMap,long,com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.testutil.FakeTrackOutput,android.net.Uri)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"seekToUs(long)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"seekToUs(long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"seekToUs(long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"seekToUs(long)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"seekToUs(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"seekToUs(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"seekToUs(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"seekToUs(long)"},{"p":"com.google.android.exoplayer2.offline","c":"SegmentDownloader.Segment","l":"Segment(long, DataSpec)","url":"%3Cinit%3E(long,com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData.Segment","l":"Segment(long, long, int)","url":"%3Cinit%3E(long,long,int)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.Segment","l":"Segment(String, HlsMediaPlaylist.Segment, String, long, int, long, DrmInitData, String, String, long, long, boolean, List)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.Segment,java.lang.String,long,int,long,com.google.android.exoplayer2.drm.DrmInitData,java.lang.String,java.lang.String,long,long,boolean,java.util.List)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.Segment","l":"Segment(String, long, long, String, String)","url":"%3Cinit%3E(java.lang.String,long,long,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifestParser.RepresentationInfo","l":"segmentBase"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase","l":"SegmentBase(RangedUri, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.dash.manifest.RangedUri,long,long)"},{"p":"com.google.android.exoplayer2.offline","c":"SegmentDownloader","l":"SegmentDownloader(MediaItem, ParsingLoadable.Parser, CacheDataSource.Factory, Executor)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.upstream.ParsingLoadable.Parser,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationHolder","l":"segmentIndex"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SegmentList","l":"SegmentList(RangedUri, long, long, long, long, List, long, List, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.dash.manifest.RangedUri,long,long,long,long,java.util.List,long,java.util.List,long,long)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData","l":"segments"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"segments"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SegmentTemplate","l":"SegmentTemplate(RangedUri, long, long, long, long, long, List, long, UrlTemplate, UrlTemplate, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.dash.manifest.RangedUri,long,long,long,long,long,java.util.List,long,com.google.android.exoplayer2.source.dash.manifest.UrlTemplate,com.google.android.exoplayer2.source.dash.manifest.UrlTemplate,long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SegmentTimelineElement","l":"SegmentTimelineElement(long, long)","url":"%3Cinit%3E(long,long)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"SeiReader","l":"SeiReader(List)","url":"%3Cinit%3E(java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelector","l":"selectAllTracks(MappingTrackSelector.MappedTrackInfo, int[][][], int[], DefaultTrackSelector.Parameters)","url":"selectAllTracks(com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo,int[][][],int[],com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"selectAllTracks(MappingTrackSelector.MappedTrackInfo, int[][][], int[], DefaultTrackSelector.Parameters)","url":"selectAllTracks(com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo,int[][][],int[],com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"selectAudioTrack(TrackGroupArray, int[][], int, DefaultTrackSelector.Parameters, boolean)","url":"selectAudioTrack(com.google.android.exoplayer2.source.TrackGroupArray,int[][],int,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters,boolean)"},{"p":"com.google.android.exoplayer2.source.dash","c":"BaseUrlExclusionList","l":"selectBaseUrl(List)","url":"selectBaseUrl(java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource.RepresentationHolder","l":"selectedBaseUrl"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"selectEmbeddedTrack(long, int)","url":"selectEmbeddedTrack(long,int)"},{"p":"com.google.android.exoplayer2","c":"C","l":"SELECTION_FLAG_AUTOSELECT"},{"p":"com.google.android.exoplayer2","c":"C","l":"SELECTION_FLAG_DEFAULT"},{"p":"com.google.android.exoplayer2","c":"C","l":"SELECTION_FLAG_FORCED"},{"p":"com.google.android.exoplayer2","c":"C","l":"SELECTION_REASON_ADAPTIVE"},{"p":"com.google.android.exoplayer2","c":"C","l":"SELECTION_REASON_CUSTOM_BASE"},{"p":"com.google.android.exoplayer2","c":"C","l":"SELECTION_REASON_INITIAL"},{"p":"com.google.android.exoplayer2","c":"C","l":"SELECTION_REASON_MANUAL"},{"p":"com.google.android.exoplayer2","c":"C","l":"SELECTION_REASON_TRICK_PLAY"},{"p":"com.google.android.exoplayer2","c":"C","l":"SELECTION_REASON_UNKNOWN"},{"p":"com.google.android.exoplayer2","c":"Format","l":"selectionFlags"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Subtitle","l":"selectionFlags"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.SelectionOverride","l":"SelectionOverride(int, int...)","url":"%3Cinit%3E(int,int...)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.SelectionOverride","l":"SelectionOverride(int, int[], int)","url":"%3Cinit%3E(int,int[],int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectorResult","l":"selections"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"selectOtherTrack(int, TrackGroupArray, int[][], DefaultTrackSelector.Parameters)","url":"selectOtherTrack(int,com.google.android.exoplayer2.source.TrackGroupArray,int[][],com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"selectTextTrack(TrackGroupArray, int[][], DefaultTrackSelector.Parameters, String)","url":"selectTextTrack(com.google.android.exoplayer2.source.TrackGroupArray,int[][],com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters,java.lang.String)"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"selectTracks(ExoTrackSelection[], boolean[], SampleStream[], boolean[], long)","url":"selectTracks(com.google.android.exoplayer2.trackselection.ExoTrackSelection[],boolean[],com.google.android.exoplayer2.source.SampleStream[],boolean[],long)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"selectTracks(ExoTrackSelection[], boolean[], SampleStream[], boolean[], long)","url":"selectTracks(com.google.android.exoplayer2.trackselection.ExoTrackSelection[],boolean[],com.google.android.exoplayer2.source.SampleStream[],boolean[],long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriod","l":"selectTracks(ExoTrackSelection[], boolean[], SampleStream[], boolean[], long)","url":"selectTracks(com.google.android.exoplayer2.trackselection.ExoTrackSelection[],boolean[],com.google.android.exoplayer2.source.SampleStream[],boolean[],long)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaPeriod","l":"selectTracks(ExoTrackSelection[], boolean[], SampleStream[], boolean[], long)","url":"selectTracks(com.google.android.exoplayer2.trackselection.ExoTrackSelection[],boolean[],com.google.android.exoplayer2.source.SampleStream[],boolean[],long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAdaptiveMediaPeriod","l":"selectTracks(ExoTrackSelection[], boolean[], SampleStream[], boolean[], long)","url":"selectTracks(com.google.android.exoplayer2.trackselection.ExoTrackSelection[],boolean[],com.google.android.exoplayer2.source.SampleStream[],boolean[],long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"selectTracks(ExoTrackSelection[], boolean[], SampleStream[], boolean[], long)","url":"selectTracks(com.google.android.exoplayer2.trackselection.ExoTrackSelection[],boolean[],com.google.android.exoplayer2.source.SampleStream[],boolean[],long)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"selectTracks(MappingTrackSelector.MappedTrackInfo, int[][][], int[], MediaSource.MediaPeriodId, Timeline)","url":"selectTracks(com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo,int[][][],int[],com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector","l":"selectTracks(MappingTrackSelector.MappedTrackInfo, int[][][], int[], MediaSource.MediaPeriodId, Timeline)","url":"selectTracks(com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo,int[][][],int[],com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.trackselection","c":"MappingTrackSelector","l":"selectTracks(RendererCapabilities[], TrackGroupArray, MediaSource.MediaPeriodId, Timeline)","url":"selectTracks(com.google.android.exoplayer2.RendererCapabilities[],com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelector","l":"selectTracks(RendererCapabilities[], TrackGroupArray, MediaSource.MediaPeriodId, Timeline)","url":"selectTracks(com.google.android.exoplayer2.RendererCapabilities[],com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"selectUndeterminedTextLanguage"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"selectVideoTrack(TrackGroupArray, int[][], int, DefaultTrackSelector.Parameters, boolean)","url":"selectVideoTrack(com.google.android.exoplayer2.source.TrackGroupArray,int[][],int,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters,boolean)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"send()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"sendAddDownload(Context, Class, DownloadRequest, boolean)","url":"sendAddDownload(android.content.Context,java.lang.Class,com.google.android.exoplayer2.offline.DownloadRequest,boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"sendAddDownload(Context, Class, DownloadRequest, int, boolean)","url":"sendAddDownload(android.content.Context,java.lang.Class,com.google.android.exoplayer2.offline.DownloadRequest,int,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"sendEmptyMessage(int)"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"sendEmptyMessageAtTime(int, long)","url":"sendEmptyMessageAtTime(int,long)"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"sendEmptyMessageDelayed(int, int)","url":"sendEmptyMessageDelayed(int,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"sendEvent(AnalyticsListener.EventTime, int, ListenerSet.Event)","url":"sendEvent(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int,com.google.android.exoplayer2.util.ListenerSet.Event)"},{"p":"com.google.android.exoplayer2.util","c":"ListenerSet","l":"sendEvent(int, ListenerSet.Event)","url":"sendEvent(int,com.google.android.exoplayer2.util.ListenerSet.Event)"},{"p":"com.google.android.exoplayer2.audio","c":"AuxEffectInfo","l":"sendLevel"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"sendMessage(PlayerMessage.Target, int, long, boolean)","url":"sendMessage(com.google.android.exoplayer2.PlayerMessage.Target,int,long,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"sendMessage(PlayerMessage.Target, int, long)","url":"sendMessage(com.google.android.exoplayer2.PlayerMessage.Target,int,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"sendMessage(PlayerMessage.Target, long)","url":"sendMessage(com.google.android.exoplayer2.PlayerMessage.Target,long)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage.Sender","l":"sendMessage(PlayerMessage)","url":"sendMessage(com.google.android.exoplayer2.PlayerMessage)"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper","l":"sendMessageAtFrontOfQueue(HandlerWrapper.Message)","url":"sendMessageAtFrontOfQueue(com.google.android.exoplayer2.util.HandlerWrapper.Message)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SendMessages","l":"SendMessages(String, PlayerMessage.Target, int, long, boolean)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.PlayerMessage.Target,int,long,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SendMessages","l":"SendMessages(String, PlayerMessage.Target, long)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.PlayerMessage.Target,long)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"sendPauseDownloads(Context, Class, boolean)","url":"sendPauseDownloads(android.content.Context,java.lang.Class,boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"sendRemoveAllDownloads(Context, Class, boolean)","url":"sendRemoveAllDownloads(android.content.Context,java.lang.Class,boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"sendRemoveDownload(Context, Class, String, boolean)","url":"sendRemoveDownload(android.content.Context,java.lang.Class,java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"sendResumeDownloads(Context, Class, boolean)","url":"sendResumeDownloads(android.content.Context,java.lang.Class,boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"sendSetRequirements(Context, Class, Requirements, boolean)","url":"sendSetRequirements(android.content.Context,java.lang.Class,com.google.android.exoplayer2.scheduler.Requirements,boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"sendSetStopReason(Context, Class, String, int, boolean)","url":"sendSetStopReason(android.content.Context,java.lang.Class,java.lang.String,int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock.HandlerMessage","l":"sendToTarget()"},{"p":"com.google.android.exoplayer2.util","c":"HandlerWrapper.Message","l":"sendToTarget()"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"separateColorPlaneFlag"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.PpsData","l":"seqParameterSetId"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"seqParameterSetId"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"sequenceNumber"},{"p":"com.google.android.exoplayer2","c":"C","l":"SERIF_NAME"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"serverControl"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.ServerControl","l":"ServerControl(long, boolean, long, long, boolean)","url":"%3Cinit%3E(long,boolean,long,long,boolean)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsMediaSource","l":"ServerSideInsertedAdsMediaSource(MediaSource)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"serviceDescription"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ServiceDescriptionElement","l":"ServiceDescriptionElement(long, long, long, float, float)","url":"%3Cinit%3E(long,long,long,float,float)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"BaseUrl","l":"serviceLocation"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"SessionCallbackBuilder(Context, SessionPlayerConnector)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.ext.media2.SessionPlayerConnector)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.DrmConfiguration","l":"sessionForClearTypes"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaCrypto","l":"sessionId"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"sessionKeyDrmInitData"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"SessionPlayerConnector(Player, MediaItemConverter)","url":"%3Cinit%3E(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ext.media2.MediaItemConverter)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"SessionPlayerConnector(Player)","url":"%3Cinit%3E(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.decoder","c":"CryptoInfo","l":"set(int, int[], int[], byte[], byte[], int, int, int)","url":"set(int,int[],int[],byte[],byte[],int,int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.RequestProperties","l":"set(Map)","url":"set(java.util.Map)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"set(Object, MediaItem, Object, long, long, long, boolean, boolean, MediaItem.LiveConfiguration, long, long, int, int, long)","url":"set(java.lang.Object,com.google.android.exoplayer2.MediaItem,java.lang.Object,long,long,long,boolean,boolean,com.google.android.exoplayer2.MediaItem.LiveConfiguration,long,long,int,int,long)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"set(Object, Object, int, long, long, AdPlaybackState, boolean)","url":"set(java.lang.Object,java.lang.Object,int,long,long,com.google.android.exoplayer2.source.ads.AdPlaybackState,boolean)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"set(Object, Object, int, long, long)","url":"set(java.lang.Object,java.lang.Object,int,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadataMutations","l":"set(String, byte[])","url":"set(java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadataMutations","l":"set(String, long)","url":"set(java.lang.String,long)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.RequestProperties","l":"set(String, String)","url":"set(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadataMutations","l":"set(String, String)","url":"set(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setAccessibilityChannel(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setActionSchedule(ActionSchedule)","url":"setActionSchedule(com.google.android.exoplayer2.testutil.ActionSchedule)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setAdErrorListener(AdErrorEvent.AdErrorListener)","url":"setAdErrorListener(com.google.ads.interactivemedia.v3.api.AdErrorEvent.AdErrorListener)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setAdEventListener(AdEvent.AdEventListener)","url":"setAdEventListener(com.google.ads.interactivemedia.v3.api.AdEvent.AdEventListener)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setAdGroupTimesMs(long[], boolean[], int)","url":"setAdGroupTimesMs(long[],boolean[],int)"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar","l":"setAdGroupTimesMs(long[], boolean[], int)","url":"setAdGroupTimesMs(long[],boolean[],int)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setAdMarkerColor(int)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setAdMediaMimeTypes(List)","url":"setAdMediaMimeTypes(java.util.List)"},{"p":"com.google.android.exoplayer2.source.ads","c":"ServerSideInsertedAdsMediaSource","l":"setAdPlaybackState(AdPlaybackState)","url":"setAdPlaybackState(com.google.android.exoplayer2.source.ads.AdPlaybackState)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setAdPreloadTimeoutMs(long)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setAdsLoaderProvider(DefaultMediaSourceFactory.AdsLoaderProvider)","url":"setAdsLoaderProvider(com.google.android.exoplayer2.source.DefaultMediaSourceFactory.AdsLoaderProvider)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setAdTagUri(String)","url":"setAdTagUri(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setAdTagUri(Uri, Object)","url":"setAdTagUri(android.net.Uri,java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setAdTagUri(Uri)","url":"setAdTagUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"setAdtsExtractorFlags(int)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setAdUiElements(Set)","url":"setAdUiElements(java.util.Set)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setAdViewProvider(AdViewProvider)","url":"setAdViewProvider(com.google.android.exoplayer2.ui.AdViewProvider)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setAlbumArtist(CharSequence)","url":"setAlbumArtist(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setAlbumTitle(CharSequence)","url":"setAlbumTitle(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl.Builder","l":"setAllocator(DefaultAllocator)","url":"setAllocator(com.google.android.exoplayer2.upstream.DefaultAllocator)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder","l":"setAllowAdaptiveSelections(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionView","l":"setAllowAdaptiveSelections(boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setAllowAudioMixedChannelCountAdaptiveness(boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setAllowAudioMixedMimeTypeAdaptiveness(boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setAllowAudioMixedSampleRateAdaptiveness(boolean)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setAllowChunklessPreparation(boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource.Factory","l":"setAllowCrossProtocolRedirects(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes.Builder","l":"setAllowedCapturePolicy(int)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"setAllowedCommandProvider(SessionCallbackBuilder.AllowedCommandProvider)","url":"setAllowedCommandProvider(com.google.android.exoplayer2.ext.media2.SessionCallbackBuilder.AllowedCommandProvider)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"setAllowedVideoJoiningTimeMs(long)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setAllowMultipleAdaptiveSelections(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder","l":"setAllowMultipleOverrides(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionView","l":"setAllowMultipleOverrides(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"setAllowPreparation(boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setAllowVideoMixedMimeTypeAdaptiveness(boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setAllowVideoNonSeamlessAdaptiveness(boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"setAmrExtractorFlags(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"setAnalyticsCollector(AnalyticsCollector)","url":"setAnalyticsCollector(com.google.android.exoplayer2.analytics.AnalyticsCollector)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setAnalyticsCollector(AnalyticsCollector)","url":"setAnalyticsCollector(com.google.android.exoplayer2.analytics.AnalyticsCollector)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setAnalyticsListener(AnalyticsListener)","url":"setAnalyticsListener(com.google.android.exoplayer2.analytics.AnalyticsListener)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setAnimationEnabled(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"setApplyEmbeddedFontSizes(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"setApplyEmbeddedStyles(boolean)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setArtist(CharSequence)","url":"setArtist(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setArtworkData(byte[], Integer)","url":"setArtworkData(byte[],java.lang.Integer)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setArtworkData(byte[])"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setArtworkUri(Uri)","url":"setArtworkUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout","l":"setAspectRatio(float)"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout","l":"setAspectRatioListener(AspectRatioFrameLayout.AspectRatioListener)","url":"setAspectRatioListener(com.google.android.exoplayer2.ui.AspectRatioFrameLayout.AspectRatioListener)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setAspectRatioListener(AspectRatioFrameLayout.AspectRatioListener)","url":"setAspectRatioListener(com.google.android.exoplayer2.ui.AspectRatioFrameLayout.AspectRatioListener)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setAspectRatioListener(AspectRatioFrameLayout.AspectRatioListener)","url":"setAspectRatioListener(com.google.android.exoplayer2.ui.AspectRatioFrameLayout.AspectRatioListener)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioComponent","l":"setAudioAttributes(AudioAttributes, boolean)","url":"setAudioAttributes(com.google.android.exoplayer2.audio.AudioAttributes,boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setAudioAttributes(AudioAttributes, boolean)","url":"setAudioAttributes(com.google.android.exoplayer2.audio.AudioAttributes,boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setAudioAttributes(AudioAttributes, boolean)","url":"setAudioAttributes(com.google.android.exoplayer2.audio.AudioAttributes,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"setAudioAttributes(AudioAttributes, boolean)","url":"setAudioAttributes(com.google.android.exoplayer2.audio.AudioAttributes,boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"setAudioAttributes(AudioAttributes)","url":"setAudioAttributes(com.google.android.exoplayer2.audio.AudioAttributes)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"setAudioAttributes(AudioAttributes)","url":"setAudioAttributes(com.google.android.exoplayer2.audio.AudioAttributes)"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"setAudioAttributes(AudioAttributes)","url":"setAudioAttributes(com.google.android.exoplayer2.audio.AudioAttributes)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"setAudioAttributes(AudioAttributesCompat)","url":"setAudioAttributes(androidx.media.AudioAttributesCompat)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetAudioAttributes","l":"SetAudioAttributes(String, AudioAttributes, boolean)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.audio.AudioAttributes,boolean)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioComponent","l":"setAudioSessionId(int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setAudioSessionId(int)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"setAudioSessionId(int)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"setAudioSessionId(int)"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"setAudioSessionId(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioComponent","l":"setAuxEffectInfo(AuxEffectInfo)","url":"setAuxEffectInfo(com.google.android.exoplayer2.audio.AuxEffectInfo)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setAuxEffectInfo(AuxEffectInfo)","url":"setAuxEffectInfo(com.google.android.exoplayer2.audio.AuxEffectInfo)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"setAuxEffectInfo(AuxEffectInfo)","url":"setAuxEffectInfo(com.google.android.exoplayer2.audio.AuxEffectInfo)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"setAuxEffectInfo(AuxEffectInfo)","url":"setAuxEffectInfo(com.google.android.exoplayer2.audio.AuxEffectInfo)"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"setAuxEffectInfo(AuxEffectInfo)","url":"setAuxEffectInfo(com.google.android.exoplayer2.audio.AuxEffectInfo)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setAverageBitrate(int)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl.Builder","l":"setBackBuffer(int, boolean)","url":"setBackBuffer(int,boolean)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setBackgroundColor(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setBadgeIconType(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"setBandwidthMeter(BandwidthMeter)","url":"setBandwidthMeter(com.google.android.exoplayer2.upstream.BandwidthMeter)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setBandwidthMeter(BandwidthMeter)","url":"setBandwidthMeter(com.google.android.exoplayer2.upstream.BandwidthMeter)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setBandwidthMeter(BandwidthMeter)","url":"setBandwidthMeter(com.google.android.exoplayer2.upstream.BandwidthMeter)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"setBandwidthMeter(BandwidthMeter)","url":"setBandwidthMeter(com.google.android.exoplayer2.upstream.BandwidthMeter)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setBitmap(Bitmap)","url":"setBitmap(android.graphics.Bitmap)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setBitmapHeight(float)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setBold(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"setBottomPaddingFraction(float)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil.Attribute","l":"setBuffer(float[], int)","url":"setBuffer(float[],int)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl.Builder","l":"setBufferDurationsMs(int, int, int, int)","url":"setBufferDurationsMs(int,int,int,int)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setBufferedColor(int)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setBufferedPosition(long)"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar","l":"setBufferedPosition(long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink.Factory","l":"setBufferSize(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setBytesDownloaded(long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink.Factory","l":"setCache(Cache)","url":"setCache(com.google.android.exoplayer2.upstream.cache.Cache)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"setCache(Cache)","url":"setCache(com.google.android.exoplayer2.upstream.cache.Cache)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource.Factory","l":"setCacheControl(CacheControl)","url":"setCacheControl(okhttp3.CacheControl)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setCacheKey(String)","url":"setCacheKey(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"setCacheKeyFactory(CacheKeyFactory)","url":"setCacheKeyFactory(com.google.android.exoplayer2.upstream.cache.CacheKeyFactory)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"setCacheReadDataSourceFactory(DataSource.Factory)","url":"setCacheReadDataSourceFactory(com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"setCacheWriteDataSinkFactory(DataSink.Factory)","url":"setCacheWriteDataSinkFactory(com.google.android.exoplayer2.upstream.DataSink.Factory)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.PlayerTarget","l":"setCallback(ActionSchedule.PlayerTarget.Callback)","url":"setCallback(com.google.android.exoplayer2.testutil.ActionSchedule.PlayerTarget.Callback)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"setCameraMotionListener(CameraMotionListener)","url":"setCameraMotionListener(com.google.android.exoplayer2.video.spherical.CameraMotionListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setCameraMotionListener(CameraMotionListener)","url":"setCameraMotionListener(com.google.android.exoplayer2.video.spherical.CameraMotionListener)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setCaptionCallback(MediaSessionConnector.CaptionCallback)","url":"setCaptionCallback(com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.CaptionCallback)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setChannelCount(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setChannelDescriptionResourceId(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setChannelImportance(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setChannelNameResourceId(int)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setClipEndPositionMs(long)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setClipRelativeToDefaultPosition(boolean)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setClipRelativeToLiveWindow(boolean)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setClipStartPositionMs(long)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setClipStartsAtKeyFrame(boolean)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"setClock(Clock)","url":"setClock(com.google.android.exoplayer2.util.Clock)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setClock(Clock)","url":"setClock(com.google.android.exoplayer2.util.Clock)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setClock(Clock)","url":"setClock(com.google.android.exoplayer2.util.Clock)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"setClock(Clock)","url":"setClock(com.google.android.exoplayer2.util.Clock)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter.Builder","l":"setClock(Clock)","url":"setClock(com.google.android.exoplayer2.util.Clock)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setCodecs(String)","url":"setCodecs(java.lang.String)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setColor(int)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setColorInfo(ColorInfo)","url":"setColorInfo(com.google.android.exoplayer2.video.ColorInfo)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setColorized(boolean)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setCombineUpright(boolean)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setCompanionAdSlots(Collection)","url":"setCompanionAdSlots(java.util.Collection)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setCompilation(CharSequence)","url":"setCompilation(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setComposer(CharSequence)","url":"setComposer(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"setCompositeSequenceableLoaderFactory(CompositeSequenceableLoaderFactory)","url":"setCompositeSequenceableLoaderFactory(com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setCompositeSequenceableLoaderFactory(CompositeSequenceableLoaderFactory)","url":"setCompositeSequenceableLoaderFactory(com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"setCompositeSequenceableLoaderFactory(CompositeSequenceableLoaderFactory)","url":"setCompositeSequenceableLoaderFactory(com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setConductor(CharSequence)","url":"setConductor(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"setConnectionTimeoutMs(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource.Factory","l":"setConnectTimeoutMs(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"setConstantBitrateSeekingEnabled(boolean)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setContainerMimeType(String)","url":"setContainerMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleOutputBuffer","l":"setContent(long, Subtitle, long)","url":"setContent(long,com.google.android.exoplayer2.text.Subtitle,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadataMutations","l":"setContentLength(ContentMetadataMutations, long)","url":"setContentLength(com.google.android.exoplayer2.upstream.cache.ContentMetadataMutations,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setContentLength(long)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes.Builder","l":"setContentType(int)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"setContentTypePredicate(Predicate)","url":"setContentTypePredicate(com.google.common.base.Predicate)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"setContentTypePredicate(Predicate)","url":"setContentTypePredicate(com.google.common.base.Predicate)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"setContentTypePredicate(Predicate)","url":"setContentTypePredicate(com.google.common.base.Predicate)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource.Factory","l":"setContentTypePredicate(Predicate)","url":"setContentTypePredicate(com.google.common.base.Predicate)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"setContentTypePredicate(Predicate)","url":"setContentTypePredicate(com.google.common.base.Predicate)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource.Factory","l":"setContentTypePredicate(Predicate)","url":"setContentTypePredicate(com.google.common.base.Predicate)"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer.Builder","l":"setContext(Context)","url":"setContext(android.content.Context)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"setContinueLoadingCheckIntervalBytes(int)"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"setControlDispatcher(ControlDispatcher)","url":"setControlDispatcher(com.google.android.exoplayer2.ControlDispatcher)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"setControlDispatcher(ControlDispatcher)","url":"setControlDispatcher(com.google.android.exoplayer2.ControlDispatcher)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setControlDispatcher(ControlDispatcher)","url":"setControlDispatcher(com.google.android.exoplayer2.ControlDispatcher)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setControlDispatcher(ControlDispatcher)","url":"setControlDispatcher(com.google.android.exoplayer2.ControlDispatcher)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setControlDispatcher(ControlDispatcher)","url":"setControlDispatcher(com.google.android.exoplayer2.ControlDispatcher)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setControlDispatcher(ControlDispatcher)","url":"setControlDispatcher(com.google.android.exoplayer2.ControlDispatcher)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setControlDispatcher(ControlDispatcher)","url":"setControlDispatcher(com.google.android.exoplayer2.ControlDispatcher)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setControlDispatcher(ControlDispatcher)","url":"setControlDispatcher(com.google.android.exoplayer2.ControlDispatcher)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setControllerAutoShow(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setControllerAutoShow(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setControllerHideDuringAds(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setControllerHideDuringAds(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setControllerHideOnTouch(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setControllerHideOnTouch(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setControllerOnFullScreenModeChangedListener(StyledPlayerControlView.OnFullScreenModeChangedListener)","url":"setControllerOnFullScreenModeChangedListener(com.google.android.exoplayer2.ui.StyledPlayerControlView.OnFullScreenModeChangedListener)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setControllerShowTimeoutMs(int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setControllerShowTimeoutMs(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setControllerVisibilityListener(PlayerControlView.VisibilityListener)","url":"setControllerVisibilityListener(com.google.android.exoplayer2.ui.PlayerControlView.VisibilityListener)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setControllerVisibilityListener(StyledPlayerControlView.VisibilityListener)","url":"setControllerVisibilityListener(com.google.android.exoplayer2.ui.StyledPlayerControlView.VisibilityListener)"},{"p":"com.google.android.exoplayer2.util","c":"MediaFormatUtil","l":"setCsdBuffers(MediaFormat, List)","url":"setCsdBuffers(android.media.MediaFormat,java.util.List)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket.Builder","l":"setCsrc(byte[])"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"setCues(List)","url":"setCues(java.util.List)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"InputReaderAdapterV30","l":"setCurrentPosition(long)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"setCurrentStreamFinal()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"setCurrentStreamFinal()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"setCurrentStreamFinal()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setCustomActionProviders(MediaSessionConnector.CustomActionProvider...)","url":"setCustomActionProviders(com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.CustomActionProvider...)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setCustomActionReceiver(PlayerNotificationManager.CustomActionReceiver)","url":"setCustomActionReceiver(com.google.android.exoplayer2.ui.PlayerNotificationManager.CustomActionReceiver)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setCustomCacheKey(String)","url":"setCustomCacheKey(java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest.Builder","l":"setCustomCacheKey(String)","url":"setCustomCacheKey(java.lang.String)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"setCustomCacheKey(String)","url":"setCustomCacheKey(java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"setCustomCommandProvider(SessionCallbackBuilder.CustomCommandProvider)","url":"setCustomCommandProvider(com.google.android.exoplayer2.ext.media2.SessionCallbackBuilder.CustomCommandProvider)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"setCustomData(Object)","url":"setCustomData(java.lang.Object)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setCustomErrorMessage(CharSequence, int, Bundle)","url":"setCustomErrorMessage(java.lang.CharSequence,int,android.os.Bundle)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setCustomErrorMessage(CharSequence, int)","url":"setCustomErrorMessage(java.lang.CharSequence,int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setCustomErrorMessage(CharSequence)","url":"setCustomErrorMessage(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setCustomErrorMessage(CharSequence)","url":"setCustomErrorMessage(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setCustomErrorMessage(CharSequence)","url":"setCustomErrorMessage(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setCustomMetadata(byte[])"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest.Builder","l":"setData(byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput.Builder","l":"setData(byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource.Builder","l":"setData(byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet","l":"setData(String, byte[])","url":"setData(java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet","l":"setData(Uri, byte[])","url":"setData(android.net.Uri,byte[])"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"InputReaderAdapterV30","l":"setDataReader(DataReader, long)","url":"setDataReader(com.google.android.exoplayer2.upstream.DataReader,long)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setDebugModeEnabled(boolean)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Libgav1VideoRenderer","l":"setDecoderOutputMode(int)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"LibvpxVideoRenderer","l":"setDecoderOutputMode(int)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"setDecoderOutputMode(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts.AssertionConfig.Builder","l":"setDeduplicateConsecutiveFormats(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setDefaultArtwork(Drawable)","url":"setDefaultArtwork(android.graphics.drawable.Drawable)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setDefaultArtwork(Drawable)","url":"setDefaultArtwork(android.graphics.drawable.Drawable)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"setDefaultRequestProperties(Map)","url":"setDefaultRequestProperties(java.util.Map)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource.Factory","l":"setDefaultRequestProperties(Map)","url":"setDefaultRequestProperties(java.util.Map)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource.Factory","l":"setDefaultRequestProperties(Map)","url":"setDefaultRequestProperties(java.util.Map)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.BaseFactory","l":"setDefaultRequestProperties(Map)","url":"setDefaultRequestProperties(java.util.Map)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.Factory","l":"setDefaultRequestProperties(Map)","url":"setDefaultRequestProperties(java.util.Map)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setDefaults(int)"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView","l":"setDefaultStereoMode(int)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"setDeleteAfterDelivery(boolean)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setDescription(CharSequence)","url":"setDescription(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setDetachSurfaceTimeoutMs(long)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.DeviceComponent","l":"setDeviceMuted(boolean)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"setDeviceMuted(boolean)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setDeviceMuted(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setDeviceMuted(boolean)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setDeviceMuted(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setDeviceMuted(boolean)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.DeviceComponent","l":"setDeviceVolume(int)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"setDeviceVolume(int)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setDeviceVolume(int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setDeviceVolume(int)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setDeviceVolume(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setDeviceVolume(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setDisabledTextTrackSelectionFlags(int)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setDiscNumber(Integer)","url":"setDiscNumber(java.lang.Integer)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"setDisconnectedCallback(SessionCallbackBuilder.DisconnectedCallback)","url":"setDisconnectedCallback(com.google.android.exoplayer2.ext.media2.SessionCallbackBuilder.DisconnectedCallback)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"setDiscontinuityPositionUs(long)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setDispatchUnsupportedActionsEnabled(boolean)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setDisplayTitle(CharSequence)","url":"setDisplayTitle(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloadIndex","l":"setDownloadingStatesToQueued()"},{"p":"com.google.android.exoplayer2.offline","c":"WritableDownloadIndex","l":"setDownloadingStatesToQueued()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setDrmForceDefaultLicenseUri(boolean)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManagerProvider","l":"setDrmHttpDataSourceFactory(HttpDataSource.Factory)","url":"setDrmHttpDataSourceFactory(com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setDrmHttpDataSourceFactory(HttpDataSource.Factory)","url":"setDrmHttpDataSourceFactory(com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceFactory","l":"setDrmHttpDataSourceFactory(HttpDataSource.Factory)","url":"setDrmHttpDataSourceFactory(com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"setDrmHttpDataSourceFactory(HttpDataSource.Factory)","url":"setDrmHttpDataSourceFactory(com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"setDrmHttpDataSourceFactory(HttpDataSource.Factory)","url":"setDrmHttpDataSourceFactory(com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setDrmHttpDataSourceFactory(HttpDataSource.Factory)","url":"setDrmHttpDataSourceFactory(com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.Factory","l":"setDrmHttpDataSourceFactory(HttpDataSource.Factory)","url":"setDrmHttpDataSourceFactory(com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"setDrmHttpDataSourceFactory(HttpDataSource.Factory)","url":"setDrmHttpDataSourceFactory(com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setDrmInitData(DrmInitData)","url":"setDrmInitData(com.google.android.exoplayer2.drm.DrmInitData)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setDrmKeySetId(byte[])"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setDrmLicenseRequestHeaders(Map)","url":"setDrmLicenseRequestHeaders(java.util.Map)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setDrmLicenseUri(String)","url":"setDrmLicenseUri(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setDrmLicenseUri(Uri)","url":"setDrmLicenseUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setDrmMultiSession(boolean)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setDrmPlayClearContentWithoutKey(boolean)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setDrmSessionForClearPeriods(boolean)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setDrmSessionForClearTypes(List)","url":"setDrmSessionForClearTypes(java.util.List)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setDrmSessionManager(DrmSessionManager)","url":"setDrmSessionManager(com.google.android.exoplayer2.drm.DrmSessionManager)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceFactory","l":"setDrmSessionManager(DrmSessionManager)","url":"setDrmSessionManager(com.google.android.exoplayer2.drm.DrmSessionManager)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"setDrmSessionManager(DrmSessionManager)","url":"setDrmSessionManager(com.google.android.exoplayer2.drm.DrmSessionManager)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"setDrmSessionManager(DrmSessionManager)","url":"setDrmSessionManager(com.google.android.exoplayer2.drm.DrmSessionManager)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setDrmSessionManager(DrmSessionManager)","url":"setDrmSessionManager(com.google.android.exoplayer2.drm.DrmSessionManager)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.Factory","l":"setDrmSessionManager(DrmSessionManager)","url":"setDrmSessionManager(com.google.android.exoplayer2.drm.DrmSessionManager)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"setDrmSessionManager(DrmSessionManager)","url":"setDrmSessionManager(com.google.android.exoplayer2.drm.DrmSessionManager)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setDrmSessionManagerProvider(DrmSessionManagerProvider)","url":"setDrmSessionManagerProvider(com.google.android.exoplayer2.drm.DrmSessionManagerProvider)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceFactory","l":"setDrmSessionManagerProvider(DrmSessionManagerProvider)","url":"setDrmSessionManagerProvider(com.google.android.exoplayer2.drm.DrmSessionManagerProvider)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"setDrmSessionManagerProvider(DrmSessionManagerProvider)","url":"setDrmSessionManagerProvider(com.google.android.exoplayer2.drm.DrmSessionManagerProvider)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"setDrmSessionManagerProvider(DrmSessionManagerProvider)","url":"setDrmSessionManagerProvider(com.google.android.exoplayer2.drm.DrmSessionManagerProvider)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setDrmSessionManagerProvider(DrmSessionManagerProvider)","url":"setDrmSessionManagerProvider(com.google.android.exoplayer2.drm.DrmSessionManagerProvider)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.Factory","l":"setDrmSessionManagerProvider(DrmSessionManagerProvider)","url":"setDrmSessionManagerProvider(com.google.android.exoplayer2.drm.DrmSessionManagerProvider)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"setDrmSessionManagerProvider(DrmSessionManagerProvider)","url":"setDrmSessionManagerProvider(com.google.android.exoplayer2.drm.DrmSessionManagerProvider)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManagerProvider","l":"setDrmUserAgent(String)","url":"setDrmUserAgent(java.lang.String)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setDrmUserAgent(String)","url":"setDrmUserAgent(java.lang.String)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceFactory","l":"setDrmUserAgent(String)","url":"setDrmUserAgent(java.lang.String)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"setDrmUserAgent(String)","url":"setDrmUserAgent(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"setDrmUserAgent(String)","url":"setDrmUserAgent(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setDrmUserAgent(String)","url":"setDrmUserAgent(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.Factory","l":"setDrmUserAgent(String)","url":"setDrmUserAgent(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"setDrmUserAgent(String)","url":"setDrmUserAgent(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setDrmUuid(UUID)","url":"setDrmUuid(java.util.UUID)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts.AssertionConfig.Builder","l":"setDumpFilesPrefix(String)","url":"setDumpFilesPrefix(java.lang.String)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setDuration(long)"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar","l":"setDuration(long)"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource.Factory","l":"setDurationUs(long)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"setEnableAudioFloatOutput(boolean)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"setEnableAudioOffload(boolean)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"setEnableAudioTrackPlaybackParams(boolean)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setEnableContinuousPlayback(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"setEnabled(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setEnabled(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar","l":"setEnabled(boolean)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"setEnableDecoderFallback(boolean)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setEnabledPlaybackActions(long)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setEncoderDelay(int)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setEncoderPadding(int)"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"setErrorMessageProvider(ErrorMessageProvider)","url":"setErrorMessageProvider(com.google.android.exoplayer2.util.ErrorMessageProvider)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setErrorMessageProvider(ErrorMessageProvider)","url":"setErrorMessageProvider(com.google.android.exoplayer2.util.ErrorMessageProvider)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setErrorMessageProvider(ErrorMessageProvider)","url":"setErrorMessageProvider(com.google.android.exoplayer2.util.ErrorMessageProvider)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setErrorMessageProvider(ErrorMessageProvider)","url":"setErrorMessageProvider(com.google.android.exoplayer2.util.ErrorMessageProvider)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"setEventListener(CacheDataSource.EventListener)","url":"setEventListener(com.google.android.exoplayer2.upstream.cache.CacheDataSource.EventListener)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setExceedAudioConstraintsIfNecessary(boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setExceedRendererCapabilitiesIfNecessary(boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setExceedVideoConstraintsIfNecessary(boolean)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setExoMediaCryptoType(Class)","url":"setExoMediaCryptoType(java.lang.Class)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.TestResource.Builder","l":"setExpectedBytes(byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setExpectedPlayerEndedCount(int)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"setExtensionRendererMode(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setExtraAdGroupMarkers(long[], boolean[])","url":"setExtraAdGroupMarkers(long[],boolean[])"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setExtraAdGroupMarkers(long[], boolean[])","url":"setExtraAdGroupMarkers(long[],boolean[])"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setExtraAdGroupMarkers(long[], boolean[])","url":"setExtraAdGroupMarkers(long[],boolean[])"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setExtraAdGroupMarkers(long[], boolean[])","url":"setExtraAdGroupMarkers(long[],boolean[])"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setExtractorFactory(HlsExtractorFactory)","url":"setExtractorFactory(com.google.android.exoplayer2.source.hls.HlsExtractorFactory)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"setExtractorOutput(ExtractorOutput)","url":"setExtractorOutput(com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"setExtractorsFactory(ExtractorsFactory)","url":"setExtractorsFactory(com.google.android.exoplayer2.extractor.ExtractorsFactory)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setExtras(Bundle)","url":"setExtras(android.os.Bundle)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setFailureReason(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource.Factory","l":"setFakeDataSet(FakeDataSet)","url":"setFakeDataSet(com.google.android.exoplayer2.testutil.FakeDataSet)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"setFallbackFactory(HttpDataSource.Factory)","url":"setFallbackFactory(com.google.android.exoplayer2.upstream.HttpDataSource.Factory)"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl.Builder","l":"setFallbackMaxPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl.Builder","l":"setFallbackMinPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"setFallbackTargetLiveOffsetMs(long)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setFastForwardActionIconResourceId(int)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"setFastForwardIncrementMs(int)"},{"p":"com.google.android.exoplayer2.text","c":"TextRenderer","l":"setFinalStreamEndPositionUs(long)"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"setFixedTextSize(int, float)","url":"setFixedTextSize(int,float)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"setFlacExtractorFlags(int)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes.Builder","l":"setFlags(int)"},{"p":"com.google.android.exoplayer2.decoder","c":"Buffer","l":"setFlags(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"setFlags(int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"setFlags(int)"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer.Builder","l":"setFlattenForSlowMotion(boolean)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil.Uniform","l":"setFloat(float)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil.Uniform","l":"setFloats(float[])"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setFocusSkipButtonWhenAvailable(boolean)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setFolderType(Integer)","url":"setFolderType(java.lang.Integer)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setFontColor(int)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setFontFamily(String)","url":"setFontFamily(java.lang.String)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setFontSize(float)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setFontSizeUnit(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setForceHighestSupportedBitrate(boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setForceHighestSupportedBitrate(boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setForceLowestBitrate(boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setForceLowestBitrate(boolean)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.Factory","l":"setForceUseRtpTcp(boolean)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"setForegroundMode(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setForegroundMode(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setForegroundMode(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil.Header","l":"setForHeaderData(int)"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"setFractionalTextSize(float, boolean)","url":"setFractionalTextSize(float,boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"setFractionalTextSize(float)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"setFragmentedMp4ExtractorFlags(int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink.Factory","l":"setFragmentSize(long)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setFrameRate(float)"},{"p":"com.google.android.exoplayer2.extractor","c":"GaplessInfoHolder","l":"setFromMetadata(Metadata)","url":"setFromMetadata(com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2.extractor","c":"GaplessInfoHolder","l":"setFromXingHeaderValue(int)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setGenre(CharSequence)","url":"setGenre(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setGroup(String)","url":"setGroup(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource.Builder","l":"setGzipSupport(int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setHandleAudioBecomingNoisy(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setHandleAudioBecomingNoisy(boolean)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"setHandler(Handler)","url":"setHandler(android.os.Handler)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"setHandleSetCookieRequests(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setHandleWakeLock(boolean)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setHeight(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"setHttpBody(byte[])"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"setHttpMethod(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"setHttpRequestHeaders(Map)","url":"setHttpRequestHeaders(java.util.Map)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setId(int)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setId(String)","url":"setId(java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setImaSdkSettings(ImaSdkSettings)","url":"setImaSdkSettings(com.google.ads.interactivemedia.v3.api.ImaSdkSettings)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"setIndex(int)"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"setIndex(int)"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"setIndex(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"AdditionalFailureInfo","l":"setInfo(String)","url":"setInfo(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter.Builder","l":"setInitialBitrateEstimate(int, long)","url":"setInitialBitrateEstimate(int,long)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter.Builder","l":"setInitialBitrateEstimate(long)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter.Builder","l":"setInitialBitrateEstimate(String)","url":"setInitialBitrateEstimate(java.lang.String)"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleDecoder","l":"setInitialInputBufferSize(int)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setInitializationData(List)","url":"setInitializationData(java.util.List)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder","l":"setIsDisabled(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSource.Factory","l":"setIsNetwork(boolean)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setIsPlayable(Boolean)","url":"setIsPlayable(java.lang.Boolean)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setItalic(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setKeepContentOnPlayerReset(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setKeepContentOnPlayerReset(boolean)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"setKeepPostFor302Redirects(boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource.Factory","l":"setKeepPostFor302Redirects(boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"setKey(String)","url":"setKey(java.lang.String)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setKeyCountIncrement(int)"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar","l":"setKeyCountIncrement(int)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager.Builder","l":"setKeyRequestParameters(Map)","url":"setKeyRequestParameters(java.util.Map)"},{"p":"com.google.android.exoplayer2.drm","c":"HttpMediaDrmCallback","l":"setKeyRequestProperty(String, String)","url":"setKeyRequestProperty(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest.Builder","l":"setKeySetId(byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setKeySetId(byte[])"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setKeyTimeIncrement(long)"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar","l":"setKeyTimeIncrement(long)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setLabel(String)","url":"setLabel(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setLanguage(String)","url":"setLanguage(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"setLength(long)"},{"p":"com.google.android.exoplayer2.ext.opus","c":"OpusLibrary","l":"setLibraries(Class, String...)","url":"setLibraries(java.lang.Class,java.lang.String...)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxLibrary","l":"setLibraries(Class, String...)","url":"setLibraries(java.lang.Class,java.lang.String...)"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegLibrary","l":"setLibraries(String...)","url":"setLibraries(java.lang.String...)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacLibrary","l":"setLibraries(String...)","url":"setLibraries(java.lang.String...)"},{"p":"com.google.android.exoplayer2.util","c":"LibraryLoader","l":"setLibraries(String...)","url":"setLibraries(java.lang.String...)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"setLimit(int)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setLine(float, int)","url":"setLine(float,int)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setLineAnchor(int)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setLinethrough(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"setListener(AudioSink.Listener)","url":"setListener(com.google.android.exoplayer2.audio.AudioSink.Listener)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"setListener(AudioSink.Listener)","url":"setListener(com.google.android.exoplayer2.audio.AudioSink.Listener)"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"setListener(AudioSink.Listener)","url":"setListener(com.google.android.exoplayer2.audio.AudioSink.Listener)"},{"p":"com.google.android.exoplayer2.analytics","c":"DefaultPlaybackSessionManager","l":"setListener(PlaybackSessionManager.Listener)","url":"setListener(com.google.android.exoplayer2.analytics.PlaybackSessionManager.Listener)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackSessionManager","l":"setListener(PlaybackSessionManager.Listener)","url":"setListener(com.google.android.exoplayer2.analytics.PlaybackSessionManager.Listener)"},{"p":"com.google.android.exoplayer2.upstream","c":"FileDataSource.Factory","l":"setListener(TransferListener)","url":"setListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer","l":"setListener(Transformer.Listener)","url":"setListener(com.google.android.exoplayer2.transformer.Transformer.Listener)"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer.Builder","l":"setListener(Transformer.Listener)","url":"setListener(com.google.android.exoplayer2.transformer.Transformer.Listener)"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl","l":"setLiveConfiguration(MediaItem.LiveConfiguration)","url":"setLiveConfiguration(com.google.android.exoplayer2.MediaItem.LiveConfiguration)"},{"p":"com.google.android.exoplayer2","c":"LivePlaybackSpeedControl","l":"setLiveConfiguration(MediaItem.LiveConfiguration)","url":"setLiveConfiguration(com.google.android.exoplayer2.MediaItem.LiveConfiguration)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setLiveMaxOffsetMs(long)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setLiveMaxOffsetMs(long)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setLiveMaxPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setLiveMaxSpeed(float)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setLiveMinOffsetMs(long)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setLiveMinOffsetMs(long)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setLiveMinPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setLiveMinSpeed(float)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"setLivePlaybackSpeedControl(LivePlaybackSpeedControl)","url":"setLivePlaybackSpeedControl(com.google.android.exoplayer2.LivePlaybackSpeedControl)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setLivePlaybackSpeedControl(LivePlaybackSpeedControl)","url":"setLivePlaybackSpeedControl(com.google.android.exoplayer2.LivePlaybackSpeedControl)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"setLivePresentationDelayMs(long, boolean)","url":"setLivePresentationDelayMs(long,boolean)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"setLivePresentationDelayMs(long)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setLiveTargetOffsetMs(long)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setLiveTargetOffsetMs(long)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"setLoadControl(LoadControl)","url":"setLoadControl(com.google.android.exoplayer2.LoadControl)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setLoadControl(LoadControl)","url":"setLoadControl(com.google.android.exoplayer2.LoadControl)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setLoadControl(LoadControl)","url":"setLoadControl(com.google.android.exoplayer2.LoadControl)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"setLoadControl(LoadControl)","url":"setLoadControl(com.google.android.exoplayer2.LoadControl)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager.Builder","l":"setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)","url":"setLoadErrorHandlingPolicy(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)","url":"setLoadErrorHandlingPolicy(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceFactory","l":"setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)","url":"setLoadErrorHandlingPolicy(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)","url":"setLoadErrorHandlingPolicy(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy)"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource.Factory","l":"setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)","url":"setLoadErrorHandlingPolicy(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)","url":"setLoadErrorHandlingPolicy(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)","url":"setLoadErrorHandlingPolicy(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.Factory","l":"setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)","url":"setLoadErrorHandlingPolicy(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)","url":"setLoadErrorHandlingPolicy(com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy)"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"setLogLevel(int)"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"setLogStackTraces(boolean)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"setLooper(Looper)","url":"setLooper(android.os.Looper)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"setLooper(Looper)","url":"setLooper(android.os.Looper)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setLooper(Looper)","url":"setLooper(android.os.Looper)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"setLooper(Looper)","url":"setLooper(android.os.Looper)"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer.Builder","l":"setLooper(Looper)","url":"setLooper(android.os.Looper)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setManifest(Object)","url":"setManifest(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"setManifestParser(ParsingLoadable.Parser)","url":"setManifestParser(com.google.android.exoplayer2.upstream.ParsingLoadable.Parser)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"setManifestParser(ParsingLoadable.Parser)","url":"setManifestParser(com.google.android.exoplayer2.upstream.ParsingLoadable.Parser)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket.Builder","l":"setMarker(boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"setMatroskaExtractorFlags(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setMaxAudioBitrate(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setMaxAudioBitrate(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setMaxAudioChannelCount(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setMaxAudioChannelCount(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm.Builder","l":"setMaxConcurrentSessions(int)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setMaxInputSize(int)"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl.Builder","l":"setMaxLiveOffsetErrorMsForUnitSpeed(long)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setMaxMediaBitrate(int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"setMaxParallelDownloads(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setMaxVideoBitrate(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setMaxVideoBitrate(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setMaxVideoFrameRate(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setMaxVideoFrameRate(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setMaxVideoSize(int, int)","url":"setMaxVideoSize(int,int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setMaxVideoSize(int, int)","url":"setMaxVideoSize(int,int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setMaxVideoSizeSd()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setMaxVideoSizeSd()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setMediaButtonEventHandler(MediaSessionConnector.MediaButtonEventHandler)","url":"setMediaButtonEventHandler(com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.MediaButtonEventHandler)"},{"p":"com.google.android.exoplayer2","c":"DefaultRenderersFactory","l":"setMediaCodecSelector(MediaCodecSelector)","url":"setMediaCodecSelector(com.google.android.exoplayer2.mediacodec.MediaCodecSelector)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setMediaDescriptionAdapter(PlayerNotificationManager.MediaDescriptionAdapter)","url":"setMediaDescriptionAdapter(com.google.android.exoplayer2.ui.PlayerNotificationManager.MediaDescriptionAdapter)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setMediaId(String)","url":"setMediaId(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"setMediaItem(MediaItem, boolean)","url":"setMediaItem(com.google.android.exoplayer2.MediaItem,boolean)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"setMediaItem(MediaItem, boolean)","url":"setMediaItem(com.google.android.exoplayer2.MediaItem,boolean)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setMediaItem(MediaItem, boolean)","url":"setMediaItem(com.google.android.exoplayer2.MediaItem,boolean)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"setMediaItem(MediaItem, long)","url":"setMediaItem(com.google.android.exoplayer2.MediaItem,long)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"setMediaItem(MediaItem, long)","url":"setMediaItem(com.google.android.exoplayer2.MediaItem,long)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setMediaItem(MediaItem, long)","url":"setMediaItem(com.google.android.exoplayer2.MediaItem,long)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"setMediaItem(MediaItem)","url":"setMediaItem(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"setMediaItem(MediaItem)","url":"setMediaItem(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setMediaItem(MediaItem)","url":"setMediaItem(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"setMediaItem(MediaItem)","url":"setMediaItem(androidx.media2.common.MediaItem)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"setMediaItemProvider(SessionCallbackBuilder.MediaItemProvider)","url":"setMediaItemProvider(com.google.android.exoplayer2.ext.media2.SessionCallbackBuilder.MediaItemProvider)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"setMediaItems(List, boolean)","url":"setMediaItems(java.util.List,boolean)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setMediaItems(List, boolean)","url":"setMediaItems(java.util.List,boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setMediaItems(List, boolean)","url":"setMediaItems(java.util.List,boolean)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setMediaItems(List, boolean)","url":"setMediaItems(java.util.List,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setMediaItems(List, boolean)","url":"setMediaItems(java.util.List,boolean)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"setMediaItems(List, int, long)","url":"setMediaItems(java.util.List,int,long)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setMediaItems(List, int, long)","url":"setMediaItems(java.util.List,int,long)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setMediaItems(List, int, long)","url":"setMediaItems(java.util.List,int,long)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setMediaItems(List, int, long)","url":"setMediaItems(java.util.List,int,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setMediaItems(List, int, long)","url":"setMediaItems(java.util.List,int,long)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"setMediaItems(List)","url":"setMediaItems(java.util.List)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"setMediaItems(List)","url":"setMediaItems(java.util.List)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setMediaItems(List)","url":"setMediaItems(java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetMediaItems","l":"SetMediaItems(String, int, long, MediaSource...)","url":"%3Cinit%3E(java.lang.String,int,long,com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetMediaItemsResetPosition","l":"SetMediaItemsResetPosition(String, boolean, MediaSource...)","url":"%3Cinit%3E(java.lang.String,boolean,com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setMediaLoadTimeoutMs(int)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setMediaMetadata(MediaMetadata)","url":"setMediaMetadata(com.google.android.exoplayer2.MediaMetadata)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setMediaMetadataProvider(MediaSessionConnector.MediaMetadataProvider)","url":"setMediaMetadataProvider(com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.MediaMetadataProvider)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setMediaSessionToken(MediaSessionCompat.Token)","url":"setMediaSessionToken(android.support.v4.media.session.MediaSessionCompat.Token)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"setMediaSource(MediaSource, boolean)","url":"setMediaSource(com.google.android.exoplayer2.source.MediaSource,boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setMediaSource(MediaSource, boolean)","url":"setMediaSource(com.google.android.exoplayer2.source.MediaSource,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setMediaSource(MediaSource, boolean)","url":"setMediaSource(com.google.android.exoplayer2.source.MediaSource,boolean)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"setMediaSource(MediaSource, long)","url":"setMediaSource(com.google.android.exoplayer2.source.MediaSource,long)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setMediaSource(MediaSource, long)","url":"setMediaSource(com.google.android.exoplayer2.source.MediaSource,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setMediaSource(MediaSource, long)","url":"setMediaSource(com.google.android.exoplayer2.source.MediaSource,long)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"setMediaSource(MediaSource)","url":"setMediaSource(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setMediaSource(MediaSource)","url":"setMediaSource(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"setMediaSource(MediaSource)","url":"setMediaSource(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setMediaSource(MediaSource)","url":"setMediaSource(com.google.android.exoplayer2.source.MediaSource)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"setMediaSourceFactory(MediaSourceFactory)","url":"setMediaSourceFactory(com.google.android.exoplayer2.source.MediaSourceFactory)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setMediaSourceFactory(MediaSourceFactory)","url":"setMediaSourceFactory(com.google.android.exoplayer2.source.MediaSourceFactory)"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer.Builder","l":"setMediaSourceFactory(MediaSourceFactory)","url":"setMediaSourceFactory(com.google.android.exoplayer2.source.MediaSourceFactory)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"setMediaSources(boolean, MediaSource...)","url":"setMediaSources(boolean,com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"setMediaSources(int, long, MediaSource...)","url":"setMediaSources(int,long,com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"setMediaSources(List, boolean)","url":"setMediaSources(java.util.List,boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setMediaSources(List, boolean)","url":"setMediaSources(java.util.List,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setMediaSources(List, boolean)","url":"setMediaSources(java.util.List,boolean)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"setMediaSources(List, int, long)","url":"setMediaSources(java.util.List,int,long)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setMediaSources(List, int, long)","url":"setMediaSources(java.util.List,int,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setMediaSources(List, int, long)","url":"setMediaSources(java.util.List,int,long)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"setMediaSources(List)","url":"setMediaSources(java.util.List)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setMediaSources(List)","url":"setMediaSources(java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setMediaSources(List)","url":"setMediaSources(java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"setMediaSources(MediaSource...)","url":"setMediaSources(com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setMediaSources(MediaSource...)","url":"setMediaSources(com.google.android.exoplayer2.source.MediaSource...)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setMediaUri(Uri)","url":"setMediaUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setMetadata(Metadata)","url":"setMetadata(com.google.android.exoplayer2.metadata.Metadata)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setMetadataDeduplicationEnabled(boolean)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setMetadataType(int)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setMimeType(String)","url":"setMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest.Builder","l":"setMimeType(String)","url":"setMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setMimeType(String)","url":"setMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl.Builder","l":"setMinPossibleLiveOffsetSmoothingFactor(float)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"setMinRetryCount(int)"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl.Builder","l":"setMinUpdateIntervalMs(long)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setMinVideoBitrate(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setMinVideoBitrate(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setMinVideoFrameRate(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setMinVideoFrameRate(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setMinVideoSize(int, int)","url":"setMinVideoSize(int,int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setMinVideoSize(int, int)","url":"setMinVideoSize(int,int)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager","l":"setMode(int, byte[])","url":"setMode(int,byte[])"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"setMp3ExtractorFlags(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"setMp4ExtractorFlags(int)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setMultiRowAlignment(Layout.Alignment)","url":"setMultiRowAlignment(android.text.Layout.Alignment)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager.Builder","l":"setMultiSession(boolean)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"setMuxedCaptionFormats(List)","url":"setMuxedCaptionFormats(java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.TestResource.Builder","l":"setName(String)","url":"setName(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter","l":"setNetworkTypeOverride(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"setNewSourceInfo(Timeline, boolean)","url":"setNewSourceInfo(com.google.android.exoplayer2.Timeline,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaSource","l":"setNewSourceInfo(Timeline)","url":"setNewSourceInfo(com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setNextActionIconResourceId(int)"},{"p":"com.google.android.exoplayer2.util","c":"NotificationUtil","l":"setNotification(Context, int, Notification)","url":"setNotification(android.content.Context,int,android.app.Notification)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setNotificationListener(PlayerNotificationManager.NotificationListener)","url":"setNotificationListener(com.google.android.exoplayer2.ui.PlayerNotificationManager.NotificationListener)"},{"p":"com.google.android.exoplayer2.util","c":"SntpClient","l":"setNtpHost(String)","url":"setNtpHost(java.lang.String)"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"setOnEventListener(ExoMediaDrm.OnEventListener)","url":"setOnEventListener(com.google.android.exoplayer2.drm.ExoMediaDrm.OnEventListener)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"setOnEventListener(ExoMediaDrm.OnEventListener)","url":"setOnEventListener(com.google.android.exoplayer2.drm.ExoMediaDrm.OnEventListener)"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"setOnEventListener(ExoMediaDrm.OnEventListener)","url":"setOnEventListener(com.google.android.exoplayer2.drm.ExoMediaDrm.OnEventListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"setOnEventListener(ExoMediaDrm.OnEventListener)","url":"setOnEventListener(com.google.android.exoplayer2.drm.ExoMediaDrm.OnEventListener)"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"setOnExpirationUpdateListener(ExoMediaDrm.OnExpirationUpdateListener)","url":"setOnExpirationUpdateListener(com.google.android.exoplayer2.drm.ExoMediaDrm.OnExpirationUpdateListener)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"setOnExpirationUpdateListener(ExoMediaDrm.OnExpirationUpdateListener)","url":"setOnExpirationUpdateListener(com.google.android.exoplayer2.drm.ExoMediaDrm.OnExpirationUpdateListener)"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"setOnExpirationUpdateListener(ExoMediaDrm.OnExpirationUpdateListener)","url":"setOnExpirationUpdateListener(com.google.android.exoplayer2.drm.ExoMediaDrm.OnExpirationUpdateListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"setOnExpirationUpdateListener(ExoMediaDrm.OnExpirationUpdateListener)","url":"setOnExpirationUpdateListener(com.google.android.exoplayer2.drm.ExoMediaDrm.OnExpirationUpdateListener)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"setOnFrameRenderedListener(MediaCodecAdapter.OnFrameRenderedListener, Handler)","url":"setOnFrameRenderedListener(com.google.android.exoplayer2.mediacodec.MediaCodecAdapter.OnFrameRenderedListener,android.os.Handler)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"setOnFrameRenderedListener(MediaCodecAdapter.OnFrameRenderedListener, Handler)","url":"setOnFrameRenderedListener(com.google.android.exoplayer2.mediacodec.MediaCodecAdapter.OnFrameRenderedListener,android.os.Handler)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setOnFullScreenModeChangedListener(StyledPlayerControlView.OnFullScreenModeChangedListener)","url":"setOnFullScreenModeChangedListener(com.google.android.exoplayer2.ui.StyledPlayerControlView.OnFullScreenModeChangedListener)"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"setOnKeyStatusChangeListener(ExoMediaDrm.OnKeyStatusChangeListener)","url":"setOnKeyStatusChangeListener(com.google.android.exoplayer2.drm.ExoMediaDrm.OnKeyStatusChangeListener)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"setOnKeyStatusChangeListener(ExoMediaDrm.OnKeyStatusChangeListener)","url":"setOnKeyStatusChangeListener(com.google.android.exoplayer2.drm.ExoMediaDrm.OnKeyStatusChangeListener)"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"setOnKeyStatusChangeListener(ExoMediaDrm.OnKeyStatusChangeListener)","url":"setOnKeyStatusChangeListener(com.google.android.exoplayer2.drm.ExoMediaDrm.OnKeyStatusChangeListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"setOnKeyStatusChangeListener(ExoMediaDrm.OnKeyStatusChangeListener)","url":"setOnKeyStatusChangeListener(com.google.android.exoplayer2.drm.ExoMediaDrm.OnKeyStatusChangeListener)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"setOutput(Object)","url":"setOutput(java.lang.Object)"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderGLSurfaceView","l":"setOutputBuffer(VideoDecoderOutputBuffer)","url":"setOutputBuffer(com.google.android.exoplayer2.video.VideoDecoderOutputBuffer)"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBufferRenderer","l":"setOutputBuffer(VideoDecoderOutputBuffer)","url":"setOutputBuffer(com.google.android.exoplayer2.video.VideoDecoderOutputBuffer)"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer.Builder","l":"setOutputMimeType(String)","url":"setOutputMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Gav1Decoder","l":"setOutputMode(int)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxDecoder","l":"setOutputMode(int)"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"setOutputSampleRateHz(int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"setOutputSurface(Surface)","url":"setOutputSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"setOutputSurface(Surface)","url":"setOutputSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"setOutputSurfaceV23(MediaCodecAdapter, Surface)","url":"setOutputSurfaceV23(com.google.android.exoplayer2.mediacodec.MediaCodecAdapter,android.view.Surface)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setOverallRating(Rating)","url":"setOverallRating(com.google.android.exoplayer2.Rating)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder","l":"setOverride(DefaultTrackSelector.SelectionOverride)","url":"setOverride(com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder","l":"setOverrides(List)","url":"setOverrides(java.util.List)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket.Builder","l":"setPadding(boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"setParameters(Bundle)","url":"setParameters(android.os.Bundle)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"setParameters(Bundle)","url":"setParameters(android.os.Bundle)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"setParameters(DefaultTrackSelector.Parameters)","url":"setParameters(com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector","l":"setParameters(DefaultTrackSelector.ParametersBuilder)","url":"setParameters(com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder)"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource.Builder","l":"setPath(String)","url":"setPath(java.lang.String)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setPauseActionIconResourceId(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"setPauseAtEndOfMediaItems(boolean)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"setPauseAtEndOfMediaItems(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setPauseAtEndOfMediaItems(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setPauseAtEndOfMediaItems(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setPauseAtEndOfMediaItems(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setPauseAtEndOfMediaItems(boolean)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"setPayload(Object)","url":"setPayload(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket.Builder","l":"setPayloadData(byte[])"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket.Builder","l":"setPayloadType(byte)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setPcmEncoding(int)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setPeakBitrate(int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"setPendingOutputEndOfStream()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"setPendingPlaybackException(ExoPlaybackException)","url":"setPendingPlaybackException(com.google.android.exoplayer2.ExoPlaybackException)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setPercentDownloaded(float)"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"setPitch(float)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setPixelWidthHeightRatio(float)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setPlayActionIconResourceId(int)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setPlayAdBeforeStartPosition(boolean)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.util","c":"MediaClock","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.util","c":"StandaloneMediaClock","l":"setPlaybackParameters(PlaybackParameters)","url":"setPlaybackParameters(com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetPlaybackParameters","l":"SetPlaybackParameters(String, PlaybackParameters)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.PlaybackParameters)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setPlaybackPreparer(MediaSessionConnector.PlaybackPreparer)","url":"setPlaybackPreparer(com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.PlaybackPreparer)"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"setPlaybackSpeed(float, float)","url":"setPlaybackSpeed(float,float)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"setPlaybackSpeed(float, float)","url":"setPlaybackSpeed(float,float)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"setPlaybackSpeed(float, float)","url":"setPlaybackSpeed(float,float)"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"setPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"setPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"setPlaybackSpeed(float)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager.Builder","l":"setPlayClearSamplesWithoutKeys(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setPlayedAdMarkerColor(int)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setPlayedColor(int)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"setPlayer(Player, Looper)","url":"setPlayer(com.google.android.exoplayer2.Player,android.os.Looper)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"setPlayer(Player)","url":"setPlayer(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setPlayer(Player)","url":"setPlayer(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsLoader","l":"setPlayer(Player)","url":"setPlayer(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setPlayer(Player)","url":"setPlayer(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setPlayer(Player)","url":"setPlayer(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setPlayer(Player)","url":"setPlayer(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setPlayer(Player)","url":"setPlayer(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setPlayer(Player)","url":"setPlayer(com.google.android.exoplayer2.Player)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setPlayerListener(Player.Listener)","url":"setPlayerListener(com.google.android.exoplayer2.Player.Listener)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"setPlaylist(List, MediaMetadata)","url":"setPlaylist(java.util.List,androidx.media2.common.MediaMetadata)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"setPlaylistMetadata(MediaMetadata)","url":"setPlaylistMetadata(com.google.android.exoplayer2.MediaMetadata)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setPlaylistMetadata(MediaMetadata)","url":"setPlaylistMetadata(com.google.android.exoplayer2.MediaMetadata)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setPlaylistMetadata(MediaMetadata)","url":"setPlaylistMetadata(com.google.android.exoplayer2.MediaMetadata)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setPlaylistMetadata(MediaMetadata)","url":"setPlaylistMetadata(com.google.android.exoplayer2.MediaMetadata)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setPlaylistMetadata(MediaMetadata)","url":"setPlaylistMetadata(com.google.android.exoplayer2.MediaMetadata)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setPlaylistParserFactory(HlsPlaylistParserFactory)","url":"setPlaylistParserFactory(com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParserFactory)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setPlaylistTrackerFactory(HlsPlaylistTracker.Factory)","url":"setPlaylistTrackerFactory(com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker.Factory)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"setPlayWhenReady(boolean)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setPlayWhenReady(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setPlayWhenReady(boolean)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setPlayWhenReady(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setPlayWhenReady(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetPlayWhenReady","l":"SetPlayWhenReady(String, boolean)","url":"%3Cinit%3E(java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setPosition(float)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"setPosition(int, long)","url":"setPosition(int,long)"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisBitArray","l":"setPosition(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"setPosition(int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"setPosition(int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"setPosition(int)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"setPosition(long)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setPosition(long)"},{"p":"com.google.android.exoplayer2.ui","c":"TimeBar","l":"setPosition(long)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"setPosition(long)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setPositionAnchor(int)"},{"p":"com.google.android.exoplayer2.text","c":"SimpleSubtitleDecoder","l":"setPositionUs(long)"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleDecoder","l":"setPositionUs(long)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"setPostConnectCallback(SessionCallbackBuilder.PostConnectCallback)","url":"setPostConnectCallback(com.google.android.exoplayer2.ext.media2.SessionCallbackBuilder.PostConnectCallback)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setPreferredAudioLanguage(String)","url":"setPreferredAudioLanguage(java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setPreferredAudioLanguage(String)","url":"setPreferredAudioLanguage(java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setPreferredAudioLanguages(String...)","url":"setPreferredAudioLanguages(java.lang.String...)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setPreferredAudioLanguages(String...)","url":"setPreferredAudioLanguages(java.lang.String...)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setPreferredAudioMimeType(String)","url":"setPreferredAudioMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setPreferredAudioMimeType(String)","url":"setPreferredAudioMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setPreferredAudioMimeTypes(String...)","url":"setPreferredAudioMimeTypes(java.lang.String...)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setPreferredAudioMimeTypes(String...)","url":"setPreferredAudioMimeTypes(java.lang.String...)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setPreferredAudioRoleFlags(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setPreferredAudioRoleFlags(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setPreferredTextLanguage(String)","url":"setPreferredTextLanguage(java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setPreferredTextLanguage(String)","url":"setPreferredTextLanguage(java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings(Context)","url":"setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings(android.content.Context)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings(Context)","url":"setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings(android.content.Context)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setPreferredTextLanguages(String...)","url":"setPreferredTextLanguages(java.lang.String...)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setPreferredTextLanguages(String...)","url":"setPreferredTextLanguages(java.lang.String...)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setPreferredTextRoleFlags(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setPreferredTextRoleFlags(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setPreferredVideoMimeType(String)","url":"setPreferredVideoMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setPreferredVideoMimeType(String)","url":"setPreferredVideoMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setPreferredVideoMimeTypes(String...)","url":"setPreferredVideoMimeTypes(java.lang.String...)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setPreferredVideoMimeTypes(String...)","url":"setPreferredVideoMimeTypes(java.lang.String...)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"setPreparationComplete()"},{"p":"com.google.android.exoplayer2.source","c":"MaskingMediaPeriod","l":"setPrepareListener(MaskingMediaPeriod.PrepareListener)","url":"setPrepareListener(com.google.android.exoplayer2.source.MaskingMediaPeriod.PrepareListener)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setPreviousActionIconResourceId(int)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl.Builder","l":"setPrioritizeTimeOverSizeThresholds(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setPriority(int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setPriorityTaskManager(PriorityTaskManager)","url":"setPriorityTaskManager(com.google.android.exoplayer2.util.PriorityTaskManager)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setPriorityTaskManager(PriorityTaskManager)","url":"setPriorityTaskManager(com.google.android.exoplayer2.util.PriorityTaskManager)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setProgressUpdateListener(PlayerControlView.ProgressUpdateListener)","url":"setProgressUpdateListener(com.google.android.exoplayer2.ui.PlayerControlView.ProgressUpdateListener)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setProgressUpdateListener(StyledPlayerControlView.ProgressUpdateListener)","url":"setProgressUpdateListener(com.google.android.exoplayer2.ui.StyledPlayerControlView.ProgressUpdateListener)"},{"p":"com.google.android.exoplayer2.ext.leanback","c":"LeanbackPlayerAdapter","l":"setProgressUpdatingEnabled(boolean)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setProjectionData(byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"setPropertyByteArray(String, byte[])","url":"setPropertyByteArray(java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"setPropertyByteArray(String, byte[])","url":"setPropertyByteArray(java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"setPropertyByteArray(String, byte[])","url":"setPropertyByteArray(java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"setPropertyByteArray(String, byte[])","url":"setPropertyByteArray(java.lang.String,byte[])"},{"p":"com.google.android.exoplayer2.drm","c":"DummyExoMediaDrm","l":"setPropertyString(String, String)","url":"setPropertyString(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.drm","c":"ExoMediaDrm","l":"setPropertyString(String, String)","url":"setPropertyString(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaDrm","l":"setPropertyString(String, String)","url":"setPropertyString(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"setPropertyString(String, String)","url":"setPropertyString(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl.Builder","l":"setProportionalControlFactor(float)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm.Builder","l":"setProvisionsRequired(int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setQueueEditor(MediaSessionConnector.QueueEditor)","url":"setQueueEditor(com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.QueueEditor)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setQueueNavigator(MediaSessionConnector.QueueNavigator)","url":"setQueueNavigator(com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.QueueNavigator)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet","l":"setRandomData(String, int)","url":"setRandomData(java.lang.String,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet","l":"setRandomData(Uri, int)","url":"setRandomData(android.net.Uri,int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"setRatingCallback(MediaSessionConnector.RatingCallback)","url":"setRatingCallback(com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.RatingCallback)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"setRatingCallback(SessionCallbackBuilder.RatingCallback)","url":"setRatingCallback(com.google.android.exoplayer2.ext.media2.SessionCallbackBuilder.RatingCallback)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"setReadTimeoutMs(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource.Factory","l":"setReadTimeoutMs(int)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setRecordingDay(Integer)","url":"setRecordingDay(java.lang.Integer)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setRecordingMonth(Integer)","url":"setRecordingMonth(java.lang.Integer)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setRecordingYear(Integer)","url":"setRecordingYear(java.lang.Integer)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"ContentMetadataMutations","l":"setRedirectedUri(ContentMetadataMutations, Uri)","url":"setRedirectedUri(com.google.android.exoplayer2.upstream.cache.ContentMetadataMutations,android.net.Uri)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setReleaseDay(Integer)","url":"setReleaseDay(java.lang.Integer)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setReleaseMonth(Integer)","url":"setReleaseMonth(java.lang.Integer)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"setReleaseTimeoutMs(long)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setReleaseTimeoutMs(long)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setReleaseYear(Integer)","url":"setReleaseYear(java.lang.Integer)"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer.Builder","l":"setRemoveAudio(boolean)"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer.Builder","l":"setRemoveVideo(boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setRendererDisabled(int, boolean)","url":"setRendererDisabled(int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetRendererDisabled","l":"SetRendererDisabled(String, int, boolean)","url":"%3Cinit%3E(java.lang.String,int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setRenderers(Renderer...)","url":"setRenderers(com.google.android.exoplayer2.Renderer...)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"setRenderers(Renderer...)","url":"setRenderers(com.google.android.exoplayer2.Renderer...)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setRenderersFactory(RenderersFactory)","url":"setRenderersFactory(com.google.android.exoplayer2.RenderersFactory)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"setRenderersFactory(RenderersFactory)","url":"setRenderersFactory(com.google.android.exoplayer2.RenderersFactory)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"setRenderTimeLimitMs(long)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"setRepeatMode(int)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setRepeatMode(int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setRepeatMode(int)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setRepeatMode(int)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"setRepeatMode(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"setRepeatMode(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setRepeatMode(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetRepeatMode","l":"SetRepeatMode(String, int)","url":"%3Cinit%3E(java.lang.String,int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setRepeatToggleModes(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setRepeatToggleModes(int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setRepeatToggleModes(int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setRepeatToggleModes(int)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"setRequestPriority(int)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource","l":"setRequestProperty(String, String)","url":"setRequestProperty(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource","l":"setRequestProperty(String, String)","url":"setRequestProperty(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource","l":"setRequestProperty(String, String)","url":"setRequestProperty(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource","l":"setRequestProperty(String, String)","url":"setRequestProperty(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"setRequirements(Requirements)","url":"setRequirements(com.google.android.exoplayer2.scheduler.Requirements)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter.Builder","l":"setResetOnNetworkTypeChange(boolean)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"setResetTimeoutOnRedirects(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"AspectRatioFrameLayout","l":"setResizeMode(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setResizeMode(int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setResizeMode(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"setRetryPosition(long, E)","url":"setRetryPosition(long,E)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"setRetryPosition(long, E)","url":"setRetryPosition(long,E)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"setRetryPosition(long, E)","url":"setRetryPosition(long,E)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"setRetryPosition(long, E)","url":"setRetryPosition(long,E)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setRewindActionIconResourceId(int)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"setRewindIncrementMs(int)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setRoleFlags(int)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setRotationDegrees(int)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setRubyPosition(int)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setSampleMimeType(String)","url":"setSampleMimeType(java.lang.String)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"setSampleOffsetUs(long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunkOutput","l":"setSampleOffsetUs(long)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setSampleRate(int)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil.Uniform","l":"setSamplerTexId(int, int)","url":"setSamplerTexId(int,int)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"setSampleTimestampUpperLimitFilterUs(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"setSchedule(ActionSchedule)","url":"setSchedule(com.google.android.exoplayer2.testutil.ActionSchedule)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setScrubberColor(int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setSeekBackIncrementMs(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"setSeekBackIncrementMs(long)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setSeekForwardIncrementMs(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"setSeekForwardIncrementMs(long)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"setSeekParameters(SeekParameters)","url":"setSeekParameters(com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"setSeekParameters(SeekParameters)","url":"setSeekParameters(com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setSeekParameters(SeekParameters)","url":"setSeekParameters(com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setSeekParameters(SeekParameters)","url":"setSeekParameters(com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setSeekParameters(SeekParameters)","url":"setSeekParameters(com.google.android.exoplayer2.SeekParameters)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"setSeekTargetUs(long)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"setSeekTimeoutMs(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod","l":"setSeekToUsOffset(long)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"setSelectedParserName(String)","url":"setSelectedParserName(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setSelectionFlags(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setSelectionOverride(int, TrackGroupArray, DefaultTrackSelector.SelectionOverride)","url":"setSelectionOverride(int,com.google.android.exoplayer2.source.TrackGroupArray,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setSelectUndeterminedTextLanguage(boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setSelectUndeterminedTextLanguage(boolean)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket.Builder","l":"setSequenceNumber(int)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setSessionAvailabilityListener(SessionAvailabilityListener)","url":"setSessionAvailabilityListener(com.google.android.exoplayer2.ext.cast.SessionAvailabilityListener)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager.Builder","l":"setSessionKeepaliveMs(long)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setShearDegrees(float)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setShowBuffering(int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setShowBuffering(int)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder","l":"setShowDisableOption(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionView","l":"setShowDisableOption(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setShowFastForwardButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setShowFastForwardButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setShowFastForwardButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setShowFastForwardButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setShowMultiWindowTimeBar(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setShowMultiWindowTimeBar(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setShowMultiWindowTimeBar(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setShowMultiWindowTimeBar(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setShowNextButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setShowNextButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setShowNextButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setShowNextButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setShowPreviousButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setShowPreviousButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setShowPreviousButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setShowPreviousButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setShowRewindButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setShowRewindButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setShowRewindButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setShowRewindButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setShowShuffleButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setShowShuffleButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setShowShuffleButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setShowShuffleButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setShowSubtitleButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setShowSubtitleButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setShowTimeoutMs(int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setShowTimeoutMs(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setShowVrButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setShowVrButton(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setShowVrButton(boolean)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"setShuffleMode(int)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"setShuffleModeEnabled(boolean)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setShuffleModeEnabled(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setShuffleModeEnabled(boolean)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setShuffleModeEnabled(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"setShuffleModeEnabled(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setShuffleModeEnabled(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetShuffleModeEnabled","l":"SetShuffleModeEnabled(String, boolean)","url":"%3Cinit%3E(java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"setShuffleOrder(ShuffleOrder, Handler, Runnable)","url":"setShuffleOrder(com.google.android.exoplayer2.source.ShuffleOrder,android.os.Handler,java.lang.Runnable)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer","l":"setShuffleOrder(ShuffleOrder)","url":"setShuffleOrder(com.google.android.exoplayer2.source.ShuffleOrder)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setShuffleOrder(ShuffleOrder)","url":"setShuffleOrder(com.google.android.exoplayer2.source.ShuffleOrder)"},{"p":"com.google.android.exoplayer2.source","c":"ConcatenatingMediaSource","l":"setShuffleOrder(ShuffleOrder)","url":"setShuffleOrder(com.google.android.exoplayer2.source.ShuffleOrder)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"setShuffleOrder(ShuffleOrder)","url":"setShuffleOrder(com.google.android.exoplayer2.source.ShuffleOrder)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setShuffleOrder(ShuffleOrder)","url":"setShuffleOrder(com.google.android.exoplayer2.source.ShuffleOrder)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetShuffleOrder","l":"SetShuffleOrder(String, ShuffleOrder)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.source.ShuffleOrder)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setShutterBackgroundColor(int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setShutterBackgroundColor(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput.Builder","l":"setSimulateIOErrors(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput.Builder","l":"setSimulatePartialReads(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData","l":"setSimulateUnknownLength(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput.Builder","l":"setSimulateUnknownLength(boolean)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setSize(float)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder","l":"setSkipCallback(SessionCallbackBuilder.SkipCallback)","url":"setSkipCallback(com.google.android.exoplayer2.ext.media2.SessionCallbackBuilder.SkipCallback)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioComponent","l":"setSkipSilenceEnabled(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setSkipSilenceEnabled(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setSkipSilenceEnabled(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"setSkipSilenceEnabled(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"setSkipSilenceEnabled(boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"setSkipSilenceEnabled(boolean)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultBandwidthMeter.Builder","l":"setSlidingWindowMaxWeight(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setSmallIcon(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setSmallIconResourceId(int)"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"setSpeed(float)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket.Builder","l":"setSsrc(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setStartTimeMs(long)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"setStartTimeUs(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setState(int)"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloadIndex","l":"setStatesToRemoving()"},{"p":"com.google.android.exoplayer2.offline","c":"WritableDownloadIndex","l":"setStatesToRemoving()"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setStereoMode(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager.Builder","l":"setStopActionIconResourceId(int)"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloadIndex","l":"setStopReason(int)"},{"p":"com.google.android.exoplayer2.offline","c":"WritableDownloadIndex","l":"setStopReason(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setStopReason(int)"},{"p":"com.google.android.exoplayer2.offline","c":"DefaultDownloadIndex","l":"setStopReason(String, int)","url":"setStopReason(java.lang.String,int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadManager","l":"setStopReason(String, int)","url":"setStopReason(java.lang.String,int)"},{"p":"com.google.android.exoplayer2.offline","c":"WritableDownloadIndex","l":"setStopReason(String, int)","url":"setStopReason(java.lang.String,int)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setStreamKeys(List)","url":"setStreamKeys(java.util.List)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest.Builder","l":"setStreamKeys(List)","url":"setStreamKeys(java.util.List)"},{"p":"com.google.android.exoplayer2.source","c":"DefaultMediaSourceFactory","l":"setStreamKeys(List)","url":"setStreamKeys(java.util.List)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceFactory","l":"setStreamKeys(List)","url":"setStreamKeys(java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"setStreamKeys(List)","url":"setStreamKeys(java.util.List)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setStreamKeys(List)","url":"setStreamKeys(java.util.List)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"setStreamKeys(List)","url":"setStreamKeys(java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setStreamKeys(StreamKey...)","url":"setStreamKeys(com.google.android.exoplayer2.offline.StreamKey...)"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"setStyle(CaptionStyleCompat)","url":"setStyle(com.google.android.exoplayer2.ui.CaptionStyleCompat)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setSubsampleOffsetUs(long)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setSubtitle(CharSequence)","url":"setSubtitle(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setSubtitles(List)","url":"setSubtitles(java.util.List)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"setSupportedContentTypes(int...)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsLoader","l":"setSupportedContentTypes(int...)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setSupportedFormats(Format...)","url":"setSupportedFormats(com.google.android.exoplayer2.Format...)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setTag(Object)","url":"setTag(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"ProgressiveMediaSource.Factory","l":"setTag(Object)","url":"setTag(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource.Factory","l":"setTag(Object)","url":"setTag(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource.Factory","l":"setTag(Object)","url":"setTag(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashMediaSource.Factory","l":"setTag(Object)","url":"setTag(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setTag(Object)","url":"setTag(java.lang.Object)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsMediaSource.Factory","l":"setTag(Object)","url":"setTag(java.lang.Object)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl.Builder","l":"setTargetBufferBytes(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultAllocator","l":"setTargetBufferSize(int)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setTargetClasses(String[])","url":"setTargetClasses(java.lang.String[])"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setTargetId(String)","url":"setTargetId(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl.Builder","l":"setTargetLiveOffsetIncrementOnRebufferMs(long)"},{"p":"com.google.android.exoplayer2","c":"DefaultLivePlaybackSpeedControl","l":"setTargetLiveOffsetOverrideUs(long)"},{"p":"com.google.android.exoplayer2","c":"LivePlaybackSpeedControl","l":"setTargetLiveOffsetOverrideUs(long)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setTargetTagName(String)","url":"setTargetTagName(java.lang.String)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setTargetVoice(String)","url":"setTargetVoice(java.lang.String)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setText(CharSequence)","url":"setText(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setTextAlignment(Layout.Alignment)","url":"setTextAlignment(android.text.Layout.Alignment)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setTextSize(float, int)","url":"setTextSize(float,int)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder","l":"setTheme(int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setThrowsWhenUsingWrongThread(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setTimeBarMinUpdateInterval(int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setTimeBarMinUpdateInterval(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setTimeline(Timeline)","url":"setTimeline(com.google.android.exoplayer2.Timeline)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.Factory","l":"setTimeoutMs(long)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket.Builder","l":"setTimestamp(long)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"OutputConsumerAdapterV30","l":"setTimestampAdjuster(TimestampAdjuster)","url":"setTimestampAdjuster(com.google.android.exoplayer2.util.TimestampAdjuster)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setTitle(CharSequence)","url":"setTitle(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setTotalDiscCount(Integer)","url":"setTotalDiscCount(java.lang.Integer)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setTotalTrackCount(Integer)","url":"setTotalTrackCount(java.lang.Integer)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder","l":"setTrackFormatComparator(Comparator)","url":"setTrackFormatComparator(java.util.Comparator)"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource.Factory","l":"setTrackId(String)","url":"setTrackId(java.lang.String)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder","l":"setTrackNameProvider(TrackNameProvider)","url":"setTrackNameProvider(com.google.android.exoplayer2.ui.TrackNameProvider)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionView","l":"setTrackNameProvider(TrackNameProvider)","url":"setTrackNameProvider(com.google.android.exoplayer2.ui.TrackNameProvider)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setTrackNumber(Integer)","url":"setTrackNumber(java.lang.Integer)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setTrackSelector(DefaultTrackSelector)","url":"setTrackSelector(com.google.android.exoplayer2.trackselection.DefaultTrackSelector)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"setTrackSelector(DefaultTrackSelector)","url":"setTrackSelector(com.google.android.exoplayer2.trackselection.DefaultTrackSelector)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"setTrackSelector(TrackSelector)","url":"setTrackSelector(com.google.android.exoplayer2.trackselection.TrackSelector)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setTrackSelector(TrackSelector)","url":"setTrackSelector(com.google.android.exoplayer2.trackselection.TrackSelector)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"setTransferListener(TransferListener)","url":"setTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource.Factory","l":"setTransferListener(TransferListener)","url":"setTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.ext.rtmp","c":"RtmpDataSource.Factory","l":"setTransferListener(TransferListener)","url":"setTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource.Factory","l":"setTransferListener(TransferListener)","url":"setTransferListener(com.google.android.exoplayer2.upstream.TransferListener)"},{"p":"com.google.android.exoplayer2.source","c":"SingleSampleMediaSource.Factory","l":"setTreatLoadErrorsAsEndOfStream(boolean)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionCallbackBuilder.DefaultAllowedCommandProvider","l":"setTrustedPackageNames(List)","url":"setTrustedPackageNames(java.util.List)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"setTsExtractorFlags(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"setTsExtractorMode(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorsFactory","l":"setTsExtractorTimestampSearchBytes(int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setTunnelingEnabled(boolean)"},{"p":"com.google.android.exoplayer2","c":"PlayerMessage","l":"setType(int)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"setUnderline(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"setUnplayedColor(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setUpdateTimeMs(long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"setUpstreamDataSourceFactory(DataSource.Factory)","url":"setUpstreamDataSourceFactory(com.google.android.exoplayer2.upstream.DataSource.Factory)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"setUpstreamFormatChangeListener(SampleQueue.UpstreamFormatChangedListener)","url":"setUpstreamFormatChangeListener(com.google.android.exoplayer2.source.SampleQueue.UpstreamFormatChangedListener)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"setUpstreamPriority(int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSource.Factory","l":"setUpstreamPriorityTaskManager(PriorityTaskManager)","url":"setUpstreamPriorityTaskManager(com.google.android.exoplayer2.util.PriorityTaskManager)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setUri(String)","url":"setUri(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.TestResource.Builder","l":"setUri(String)","url":"setUri(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setUri(String)","url":"setUri(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"setUri(String)","url":"setUri(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Builder","l":"setUri(Uri)","url":"setUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest.TestResource.Builder","l":"setUri(Uri)","url":"setUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2.testutil","c":"DownloadBuilder","l":"setUri(Uri)","url":"setUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"setUri(Uri)","url":"setUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec.Builder","l":"setUriPositionOffset(long)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes.Builder","l":"setUsage(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setUseArtwork(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setUseArtwork(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setUseChronometer(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setUseController(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setUseController(boolean)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager.Builder","l":"setUseDrmSessionsForClearContent(int...)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setUseFastForwardAction(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setUseFastForwardActionInCompactView(boolean)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.Builder","l":"setUseLazyPreparation(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setUseLazyPreparation(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setUseLazyPreparation(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"setUseLazyPreparation(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setUseNextAction(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setUseNextActionInCompactView(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setUsePlayPauseActions(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setUsePreviousAction(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setUsePreviousActionInCompactView(boolean)"},{"p":"com.google.android.exoplayer2.ext.cronet","c":"CronetDataSource.Factory","l":"setUserAgent(String)","url":"setUserAgent(java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.okhttp","c":"OkHttpDataSource.Factory","l":"setUserAgent(String)","url":"setUserAgent(java.lang.String)"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtspMediaSource.Factory","l":"setUserAgent(String)","url":"setUserAgent(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultHttpDataSource.Factory","l":"setUserAgent(String)","url":"setUserAgent(java.lang.String)"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"setUserDefaultStyle()"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"setUserDefaultTextSize()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setUseRewindAction(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setUseRewindActionInCompactView(boolean)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setUserRating(Rating)","url":"setUserRating(com.google.android.exoplayer2.Rating)"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView","l":"setUseSensorRotation(boolean)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsMediaSource.Factory","l":"setUseSessionKeys(boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setUseStopAction(boolean)"},{"p":"com.google.android.exoplayer2.drm","c":"DefaultDrmSessionManager.Builder","l":"setUuidAndExoMediaDrmProvider(UUID, ExoMediaDrm.Provider)","url":"setUuidAndExoMediaDrmProvider(java.util.UUID,com.google.android.exoplayer2.drm.ExoMediaDrm.Provider)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setVastLoadTimeoutMs(int)"},{"p":"com.google.android.exoplayer2.database","c":"VersionTable","l":"setVersion(SQLiteDatabase, int, String, int)","url":"setVersion(android.database.sqlite.SQLiteDatabase,int,java.lang.String,int)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setVerticalType(int)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader.Builder","l":"setVideoAdPlayerCallback(VideoAdPlayer.VideoAdPlayerCallback)","url":"setVideoAdPlayerCallback(com.google.ads.interactivemedia.v3.api.player.VideoAdPlayer.VideoAdPlayerCallback)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"setVideoFrameMetadataListener(VideoFrameMetadataListener)","url":"setVideoFrameMetadataListener(com.google.android.exoplayer2.video.VideoFrameMetadataListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setVideoFrameMetadataListener(VideoFrameMetadataListener)","url":"setVideoFrameMetadataListener(com.google.android.exoplayer2.video.VideoFrameMetadataListener)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"setVideoScalingMode(int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setVideoScalingMode(int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setVideoScalingMode(int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter","l":"setVideoScalingMode(int)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"SynchronousMediaCodecAdapter","l":"setVideoScalingMode(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"setVideoSurface()"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.SetVideoSurface","l":"SetVideoSurface(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"setVideoSurface(Surface)","url":"setVideoSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"setVideoSurface(Surface)","url":"setVideoSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setVideoSurface(Surface)","url":"setVideoSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setVideoSurface(Surface)","url":"setVideoSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setVideoSurface(Surface)","url":"setVideoSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"setVideoSurface(Surface)","url":"setVideoSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setVideoSurface(Surface)","url":"setVideoSurface(android.view.Surface)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"setVideoSurfaceHolder(SurfaceHolder)","url":"setVideoSurfaceHolder(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"setVideoSurfaceHolder(SurfaceHolder)","url":"setVideoSurfaceHolder(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setVideoSurfaceHolder(SurfaceHolder)","url":"setVideoSurfaceHolder(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setVideoSurfaceHolder(SurfaceHolder)","url":"setVideoSurfaceHolder(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setVideoSurfaceHolder(SurfaceHolder)","url":"setVideoSurfaceHolder(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setVideoSurfaceHolder(SurfaceHolder)","url":"setVideoSurfaceHolder(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"setVideoSurfaceView(SurfaceView)","url":"setVideoSurfaceView(android.view.SurfaceView)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"setVideoSurfaceView(SurfaceView)","url":"setVideoSurfaceView(android.view.SurfaceView)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setVideoSurfaceView(SurfaceView)","url":"setVideoSurfaceView(android.view.SurfaceView)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setVideoSurfaceView(SurfaceView)","url":"setVideoSurfaceView(android.view.SurfaceView)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setVideoSurfaceView(SurfaceView)","url":"setVideoSurfaceView(android.view.SurfaceView)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setVideoSurfaceView(SurfaceView)","url":"setVideoSurfaceView(android.view.SurfaceView)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.VideoComponent","l":"setVideoTextureView(TextureView)","url":"setVideoTextureView(android.view.TextureView)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"setVideoTextureView(TextureView)","url":"setVideoTextureView(android.view.TextureView)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setVideoTextureView(TextureView)","url":"setVideoTextureView(android.view.TextureView)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setVideoTextureView(TextureView)","url":"setVideoTextureView(android.view.TextureView)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setVideoTextureView(TextureView)","url":"setVideoTextureView(android.view.TextureView)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setVideoTextureView(TextureView)","url":"setVideoTextureView(android.view.TextureView)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setViewportSize(int, int, boolean)","url":"setViewportSize(int,int,boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setViewportSize(int, int, boolean)","url":"setViewportSize(int,int,boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.ParametersBuilder","l":"setViewportSizeToPhysicalDisplaySize(Context, boolean)","url":"setViewportSizeToPhysicalDisplaySize(android.content.Context,boolean)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters.Builder","l":"setViewportSizeToPhysicalDisplaySize(Context, boolean)","url":"setViewportSizeToPhysicalDisplaySize(android.content.Context,boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"setViewType(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerNotificationManager","l":"setVisibility(int)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"setVisibility(int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"setVisibility(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayer.AudioComponent","l":"setVolume(float)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"setVolume(float)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"setVolume(float)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setVolume(float)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"setVolume(float)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"setVolume(float)"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"setVolume(float)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"setVolume(float)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"setVolume(float)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"setVrButtonListener(View.OnClickListener)","url":"setVrButtonListener(android.view.View.OnClickListener)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"setVrButtonListener(View.OnClickListener)","url":"setVrButtonListener(android.view.View.OnClickListener)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"setWakeMode(int)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer.Builder","l":"setWakeMode(int)"},{"p":"com.google.android.exoplayer2","c":"Format.Builder","l":"setWidth(int)"},{"p":"com.google.android.exoplayer2.text","c":"Cue.Builder","l":"setWindowColor(int)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setWriter(CharSequence)","url":"setWriter(java.lang.CharSequence)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata.Builder","l":"setYear(Integer)","url":"setYear(java.lang.Integer)"},{"p":"com.google.android.exoplayer2.robolectric","c":"ShadowMediaCodecConfig","l":"ShadowMediaCodecConfig()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"sharedInitializeOrWait(boolean, long)","url":"sharedInitializeOrWait(boolean,long)"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"shearDegrees"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"shouldCancelChunkLoad(long, Chunk, List)","url":"shouldCancelChunkLoad(long,com.google.android.exoplayer2.source.chunk.Chunk,java.util.List)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSource","l":"shouldCancelLoad(long, Chunk, List)","url":"shouldCancelLoad(long,com.google.android.exoplayer2.source.chunk.Chunk,java.util.List)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"shouldCancelLoad(long, Chunk, List)","url":"shouldCancelLoad(long,com.google.android.exoplayer2.source.chunk.Chunk,java.util.List)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource","l":"shouldCancelLoad(long, Chunk, List)","url":"shouldCancelLoad(long,com.google.android.exoplayer2.source.chunk.Chunk,java.util.List)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeChunkSource","l":"shouldCancelLoad(long, Chunk, List)","url":"shouldCancelLoad(long,com.google.android.exoplayer2.source.chunk.Chunk,java.util.List)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"shouldContinueLoading(long, long, float)","url":"shouldContinueLoading(long,long,float)"},{"p":"com.google.android.exoplayer2","c":"LoadControl","l":"shouldContinueLoading(long, long, float)","url":"shouldContinueLoading(long,long,float)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"shouldDropBuffersToKeyframe(long, long, boolean)","url":"shouldDropBuffersToKeyframe(long,long,boolean)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"shouldDropBuffersToKeyframe(long, long)","url":"shouldDropBuffersToKeyframe(long,long)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"shouldDropOutputBuffer(long, long, boolean)","url":"shouldDropOutputBuffer(long,long,boolean)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"shouldDropOutputBuffer(long, long)","url":"shouldDropOutputBuffer(long,long)"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"shouldEvaluateQueueSize(long, List)","url":"shouldEvaluateQueueSize(long,java.util.List)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"shouldForceRenderOutputBuffer(long, long)","url":"shouldForceRenderOutputBuffer(long,long)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"shouldForceRenderOutputBuffer(long, long)","url":"shouldForceRenderOutputBuffer(long,long)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"shouldInitCodec(MediaCodecInfo)","url":"shouldInitCodec(com.google.android.exoplayer2.mediacodec.MediaCodecInfo)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"shouldInitCodec(MediaCodecInfo)","url":"shouldInitCodec(com.google.android.exoplayer2.mediacodec.MediaCodecInfo)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"shouldPlayAdGroup()"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeAudioRenderer","l":"shouldProcessBuffer(long, long)","url":"shouldProcessBuffer(long,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"shouldProcessBuffer(long, long)","url":"shouldProcessBuffer(long,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeVideoRenderer","l":"shouldProcessBuffer(long, long)","url":"shouldProcessBuffer(long,long)"},{"p":"com.google.android.exoplayer2","c":"DefaultLoadControl","l":"shouldStartPlayback(long, float, boolean, long)","url":"shouldStartPlayback(long,float,boolean,long)"},{"p":"com.google.android.exoplayer2","c":"LoadControl","l":"shouldStartPlayback(long, float, boolean, long)","url":"shouldStartPlayback(long,float,boolean,long)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"shouldUseBypass(Format)","url":"shouldUseBypass(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"shouldUseBypass(Format)","url":"shouldUseBypass(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"SHOW_BUFFERING_ALWAYS"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"SHOW_BUFFERING_ALWAYS"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"SHOW_BUFFERING_NEVER"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"SHOW_BUFFERING_NEVER"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"SHOW_BUFFERING_WHEN_PLAYING"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"SHOW_BUFFERING_WHEN_PLAYING"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerControlView","l":"show()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"show()"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"showController()"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"showController()"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"showScrubber()"},{"p":"com.google.android.exoplayer2.ui","c":"DefaultTimeBar","l":"showScrubber(long)"},{"p":"com.google.android.exoplayer2.source","c":"SilenceMediaSource","l":"SilenceMediaSource(long)","url":"%3Cinit%3E(long)"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"SilenceSkippingAudioProcessor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.audio","c":"SilenceSkippingAudioProcessor","l":"SilenceSkippingAudioProcessor(long, long, short)","url":"%3Cinit%3E(long,long,short)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"SimpleCache(File, CacheEvictor, byte[], boolean)","url":"%3Cinit%3E(java.io.File,com.google.android.exoplayer2.upstream.cache.CacheEvictor,byte[],boolean)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"SimpleCache(File, CacheEvictor, byte[])","url":"%3Cinit%3E(java.io.File,com.google.android.exoplayer2.upstream.cache.CacheEvictor,byte[])"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"SimpleCache(File, CacheEvictor, DatabaseProvider, byte[], boolean, boolean)","url":"%3Cinit%3E(java.io.File,com.google.android.exoplayer2.upstream.cache.CacheEvictor,com.google.android.exoplayer2.database.DatabaseProvider,byte[],boolean,boolean)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"SimpleCache(File, CacheEvictor, DatabaseProvider)","url":"%3Cinit%3E(java.io.File,com.google.android.exoplayer2.upstream.cache.CacheEvictor,com.google.android.exoplayer2.database.DatabaseProvider)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"SimpleCache(File, CacheEvictor)","url":"%3Cinit%3E(java.io.File,com.google.android.exoplayer2.upstream.cache.CacheEvictor)"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleDecoder","l":"SimpleDecoder(I[], O[])","url":"%3Cinit%3E(I[],O[])"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"SimpleExoPlayer(Context, RenderersFactory, TrackSelector, MediaSourceFactory, LoadControl, BandwidthMeter, AnalyticsCollector, boolean, Clock, Looper)","url":"%3Cinit%3E(android.content.Context,com.google.android.exoplayer2.RenderersFactory,com.google.android.exoplayer2.trackselection.TrackSelector,com.google.android.exoplayer2.source.MediaSourceFactory,com.google.android.exoplayer2.LoadControl,com.google.android.exoplayer2.upstream.BandwidthMeter,com.google.android.exoplayer2.analytics.AnalyticsCollector,boolean,com.google.android.exoplayer2.util.Clock,android.os.Looper)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"SimpleExoPlayer(SimpleExoPlayer.Builder)","url":"%3Cinit%3E(com.google.android.exoplayer2.SimpleExoPlayer.Builder)"},{"p":"com.google.android.exoplayer2.metadata","c":"SimpleMetadataDecoder","l":"SimpleMetadataDecoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.decoder","c":"SimpleOutputBuffer","l":"SimpleOutputBuffer(OutputBuffer.Owner)","url":"%3Cinit%3E(com.google.android.exoplayer2.decoder.OutputBuffer.Owner)"},{"p":"com.google.android.exoplayer2.text","c":"SimpleSubtitleDecoder","l":"SimpleSubtitleDecoder(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput.SimulatedIOException","l":"SimulatedIOException(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts.SimulationConfig","l":"simulateIOErrors"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts.SimulationConfig","l":"simulatePartialReads"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts.SimulationConfig","l":"simulateUnknownLength"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"SINGLE_WINDOW_UID"},{"p":"com.google.android.exoplayer2.source.ads","c":"SinglePeriodAdTimeline","l":"SinglePeriodAdTimeline(Timeline, AdPlaybackState)","url":"%3Cinit%3E(com.google.android.exoplayer2.Timeline,com.google.android.exoplayer2.source.ads.AdPlaybackState)"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"SinglePeriodTimeline(long, boolean, boolean, boolean, Object, MediaItem)","url":"%3Cinit%3E(long,boolean,boolean,boolean,java.lang.Object,com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"SinglePeriodTimeline(long, boolean, boolean, boolean, Object, Object)","url":"%3Cinit%3E(long,boolean,boolean,boolean,java.lang.Object,java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"SinglePeriodTimeline(long, long, long, long, boolean, boolean, boolean, Object, MediaItem)","url":"%3Cinit%3E(long,long,long,long,boolean,boolean,boolean,java.lang.Object,com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"SinglePeriodTimeline(long, long, long, long, boolean, boolean, boolean, Object, Object)","url":"%3Cinit%3E(long,long,long,long,boolean,boolean,boolean,java.lang.Object,java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"SinglePeriodTimeline(long, long, long, long, long, long, long, boolean, boolean, boolean, Object, MediaItem, MediaItem.LiveConfiguration)","url":"%3Cinit%3E(long,long,long,long,long,long,long,boolean,boolean,boolean,java.lang.Object,com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.MediaItem.LiveConfiguration)"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"SinglePeriodTimeline(long, long, long, long, long, long, long, boolean, boolean, boolean, Object, Object)","url":"%3Cinit%3E(long,long,long,long,long,long,long,boolean,boolean,boolean,java.lang.Object,java.lang.Object)"},{"p":"com.google.android.exoplayer2.source","c":"SinglePeriodTimeline","l":"SinglePeriodTimeline(long, long, long, long, long, long, long, boolean, boolean, Object, MediaItem, MediaItem.LiveConfiguration)","url":"%3Cinit%3E(long,long,long,long,long,long,long,boolean,boolean,java.lang.Object,com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.MediaItem.LiveConfiguration)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"SingleSampleMediaChunk","l":"SingleSampleMediaChunk(DataSource, DataSpec, Format, int, Object, long, long, long, int, Format)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSpec,com.google.android.exoplayer2.Format,int,java.lang.Object,long,long,long,int,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeMediaPeriod.TrackDataFactory","l":"singleSampleWithTimeUs(long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SingleSegmentBase","l":"SingleSegmentBase()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"SegmentBase.SingleSegmentBase","l":"SingleSegmentBase(RangedUri, long, long, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.dash.manifest.RangedUri,long,long,long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.SingleSegmentRepresentation","l":"SingleSegmentRepresentation(long, Format, List, SegmentBase.SingleSegmentBase, List, String, long)","url":"%3Cinit%3E(long,com.google.android.exoplayer2.Format,java.util.List,com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase,java.util.List,java.lang.String,long)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"SINK_FORMAT_SUPPORTED_DIRECTLY"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"SINK_FORMAT_SUPPORTED_WITH_TRANSCODING"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"SINK_FORMAT_UNSUPPORTED"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"sinkSupportsFormat(Format)","url":"sinkSupportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"size"},{"p":"com.google.android.exoplayer2","c":"Player.Commands","l":"size()"},{"p":"com.google.android.exoplayer2","c":"Player.Events","l":"size()"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.Events","l":"size()"},{"p":"com.google.android.exoplayer2.util","c":"FlagSet","l":"size()"},{"p":"com.google.android.exoplayer2.util","c":"IntArrayQueue","l":"size()"},{"p":"com.google.android.exoplayer2.util","c":"ListenerSet","l":"size()"},{"p":"com.google.android.exoplayer2.util","c":"LongArray","l":"size()"},{"p":"com.google.android.exoplayer2.util","c":"TimedValueQueue","l":"size()"},{"p":"com.google.android.exoplayer2.extractor","c":"ChunkIndex","l":"sizes"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"skip(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"skip(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"skip(int)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"skip(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"skip(int)"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"skipAd()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"skipBit()"},{"p":"com.google.android.exoplayer2.util","c":"ParsableNalUnitBitArray","l":"skipBit()"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisBitArray","l":"skipBits(int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"skipBits(int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableNalUnitBitArray","l":"skipBits(int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableBitArray","l":"skipBytes(int)"},{"p":"com.google.android.exoplayer2.util","c":"ParsableByteArray","l":"skipBytes(int)"},{"p":"com.google.android.exoplayer2.source","c":"EmptySampleStream","l":"skipData(long)"},{"p":"com.google.android.exoplayer2.source","c":"SampleStream","l":"skipData(long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream","l":"skipData(long)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkSampleStream.EmbeddedSampleStream","l":"skipData(long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"skipData(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"skipFully(int, boolean)","url":"skipFully(int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"skipFully(int, boolean)","url":"skipFully(int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"skipFully(int, boolean)","url":"skipFully(int,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"skipFully(int, boolean)","url":"skipFully(int,boolean)"},{"p":"com.google.android.exoplayer2.extractor","c":"DefaultExtractorInput","l":"skipFully(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorInput","l":"skipFully(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ForwardingExtractorInput","l":"skipFully(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorInput","l":"skipFully(int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorUtil","l":"skipFullyQuietly(ExtractorInput, int)","url":"skipFullyQuietly(com.google.android.exoplayer2.extractor.ExtractorInput,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"skipInputUntilPosition(ExtractorInput, long)","url":"skipInputUntilPosition(com.google.android.exoplayer2.extractor.ExtractorInput,long)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"skipOutputBuffer(MediaCodecAdapter, int, long)","url":"skipOutputBuffer(com.google.android.exoplayer2.mediacodec.MediaCodecAdapter,int,long)"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"skipOutputBuffer(VideoDecoderOutputBuffer)","url":"skipOutputBuffer(com.google.android.exoplayer2.video.VideoDecoderOutputBuffer)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"skippedInputBufferCount"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"skippedOutputBufferCount"},{"p":"com.google.android.exoplayer2.decoder","c":"OutputBuffer","l":"skippedOutputBufferCount"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner.Builder","l":"skipSettingMediaSources()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener.EventDispatcher","l":"skipSilenceEnabledChanged(boolean)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"skipSource(long)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"skipToNextPlaylistItem()"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"skipToPlaylistItem(int)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"skipToPreviousPlaylistItem()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.ServerControl","l":"skipUntilUs"},{"p":"com.google.android.exoplayer2.util","c":"SlidingPercentile","l":"SlidingPercentile(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData","l":"SlowMotionData(List)","url":"%3Cinit%3E(java.util.List)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SmtaMetadataEntry","l":"SmtaMetadataEntry(float, int)","url":"%3Cinit%3E(float,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"sneakyThrow(Throwable)","url":"sneakyThrow(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"FlacExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor","c":"Extractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.amr","c":"AmrExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.flac","c":"FlacExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.flv","c":"FlvExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.jpeg","c":"JpegExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.mp3","c":"Mp3Extractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"FragmentedMp4Extractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Mp4Extractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.ogg","c":"OggExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.rawcc","c":"RawCcExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac3Extractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"Ac4Extractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"AdtsExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.extractor.wav","c":"WavExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.source.hls","c":"WebvttExtractor","l":"sniff(ExtractorInput)","url":"sniff(com.google.android.exoplayer2.extractor.ExtractorInput)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts.SimulationConfig","l":"sniffFirst"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"softwareOnly"},{"p":"com.google.android.exoplayer2.audio","c":"SonicAudioProcessor","l":"SonicAudioProcessor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ProgramInformation","l":"source"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"sourceId(int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject","l":"spanned()"},{"p":"com.google.android.exoplayer2","c":"PlaybackParameters","l":"speed"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData.Segment","l":"speedDivisor"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView","l":"SphericalGLSurfaceView(Context, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.video.spherical","c":"SphericalGLSurfaceView","l":"SphericalGLSurfaceView(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.source","c":"SampleQueue","l":"splice()"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceCommand","l":"SpliceCommand()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"spliceEventCancelIndicator"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.Event","l":"spliceEventCancelIndicator"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"spliceEventId"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.Event","l":"spliceEventId"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"spliceImmediateFlag"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInfoDecoder","l":"SpliceInfoDecoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceNullCommand","l":"SpliceNullCommand()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"split(String, String)","url":"split(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"splitAtFirst(String, String)","url":"splitAtFirst(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"splitCodecs(String)","url":"splitCodecs(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"CodecSpecificDataUtil","l":"splitNalUnits(byte[])"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"SpsData(int, int, int, int, int, int, float, boolean, boolean, int, int, int, boolean)","url":"%3Cinit%3E(int,int,int,int,int,int,float,boolean,boolean,int,int,int,boolean)"},{"p":"com.google.android.exoplayer2.text.ssa","c":"SsaDecoder","l":"SsaDecoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.text.ssa","c":"SsaDecoder","l":"SsaDecoder(List)","url":"%3Cinit%3E(java.util.List)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.offline","c":"SsDownloader","l":"SsDownloader(MediaItem, CacheDataSource.Factory, Executor)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.offline","c":"SsDownloader","l":"SsDownloader(MediaItem, CacheDataSource.Factory)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.offline","c":"SsDownloader","l":"SsDownloader(MediaItem, ParsingLoadable.Parser, CacheDataSource.Factory, Executor)","url":"%3Cinit%3E(com.google.android.exoplayer2.MediaItem,com.google.android.exoplayer2.upstream.ParsingLoadable.Parser,com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory,java.util.concurrent.Executor)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest","l":"SsManifest(int, int, long, long, long, int, boolean, SsManifest.ProtectionElement, SsManifest.StreamElement[])","url":"%3Cinit%3E(int,int,long,long,long,int,boolean,com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest.ProtectionElement,com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest.StreamElement[])"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifestParser","l":"SsManifestParser()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"ssrc"},{"p":"com.google.android.exoplayer2.util","c":"StandaloneMediaClock","l":"StandaloneMediaClock(Clock)","url":"%3Cinit%3E(com.google.android.exoplayer2.util.Clock)"},{"p":"com.google.android.exoplayer2","c":"StarRating","l":"StarRating(int, float)","url":"%3Cinit%3E(int,float)"},{"p":"com.google.android.exoplayer2","c":"StarRating","l":"StarRating(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"RangedUri","l":"start"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekPoint","l":"START"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"start()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"start()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"start()"},{"p":"com.google.android.exoplayer2.scheduler","c":"RequirementsWatcher","l":"start()"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"start()"},{"p":"com.google.android.exoplayer2.util","c":"DebugTextViewHelper","l":"start()"},{"p":"com.google.android.exoplayer2.util","c":"StandaloneMediaClock","l":"start()"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"start(AdsMediaSource, DataSpec, Object, AdViewProvider, AdsLoader.EventListener)","url":"start(com.google.android.exoplayer2.source.ads.AdsMediaSource,com.google.android.exoplayer2.upstream.DataSpec,java.lang.Object,com.google.android.exoplayer2.ui.AdViewProvider,com.google.android.exoplayer2.source.ads.AdsLoader.EventListener)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsLoader","l":"start(AdsMediaSource, DataSpec, Object, AdViewProvider, AdsLoader.EventListener)","url":"start(com.google.android.exoplayer2.source.ads.AdsMediaSource,com.google.android.exoplayer2.upstream.DataSpec,java.lang.Object,com.google.android.exoplayer2.ui.AdViewProvider,com.google.android.exoplayer2.source.ads.AdsLoader.EventListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"start(boolean)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"start(Context, Class)","url":"start(android.content.Context,java.lang.Class)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"start(Uri, MediaSourceEventListener.EventDispatcher, HlsPlaylistTracker.PrimaryPlaylistListener)","url":"start(android.net.Uri,com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher,com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker.PrimaryPlaylistListener)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"start(Uri, MediaSourceEventListener.EventDispatcher, HlsPlaylistTracker.PrimaryPlaylistListener)","url":"start(android.net.Uri,com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher,com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker.PrimaryPlaylistListener)"},{"p":"com.google.android.exoplayer2.testutil","c":"Dumper","l":"startBlock(String)","url":"startBlock(java.lang.String)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"startFile(String, long, long)","url":"startFile(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"startFile(String, long, long)","url":"startFile(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadService","l":"startForeground(Context, Class)","url":"startForeground(android.content.Context,java.lang.Class)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"startForegroundService(Context, Intent)","url":"startForegroundService(android.content.Context,android.content.Intent)"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader","l":"startLoading(T, Loader.Callback, int)","url":"startLoading(T,com.google.android.exoplayer2.upstream.Loader.Callback,int)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"startMasterElement(int, long, long)","url":"startMasterElement(int,long,long)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"startMasterElement(int, long, long)","url":"startMasterElement(int,long,long)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Period","l":"startMs"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"startOffset"},{"p":"com.google.android.exoplayer2.extractor.jpeg","c":"StartOffsetExtractorOutput","l":"StartOffsetExtractorOutput(long, ExtractorOutput)","url":"%3Cinit%3E(long,com.google.android.exoplayer2.extractor.ExtractorOutput)"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"startOffsetUs"},{"p":"com.google.android.exoplayer2","c":"MediaItem.ClippingProperties","l":"startPositionMs"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"startReadWrite(String, long, long)","url":"startReadWrite(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"startReadWrite(String, long, long)","url":"startReadWrite(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"startReadWriteNonBlocking(String, long, long)","url":"startReadWriteNonBlocking(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"SimpleCache","l":"startReadWriteNonBlocking(String, long, long)","url":"startReadWriteNonBlocking(java.lang.String,long,long)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.ClippingProperties","l":"startsAtKeyFrame"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"startTimeMs"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData.Segment","l":"startTimeMs"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"startTimeMs"},{"p":"com.google.android.exoplayer2.offline","c":"SegmentDownloader.Segment","l":"startTimeUs"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"startTimeUs"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"startTimeUs"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCueInfo","l":"startTimeUs"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer","l":"startTransformation(MediaItem, ParcelFileDescriptor)","url":"startTransformation(com.google.android.exoplayer2.MediaItem,android.os.ParcelFileDescriptor)"},{"p":"com.google.android.exoplayer2.transformer","c":"Transformer","l":"startTransformation(MediaItem, String)","url":"startTransformation(com.google.android.exoplayer2.MediaItem,java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"AtomicFile","l":"startWrite()"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"state"},{"p":"com.google.android.exoplayer2","c":"Player","l":"STATE_BUFFERING"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"STATE_COMPLETED"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"STATE_DISABLED"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"STATE_DOWNLOADING"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"STATE_ENABLED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"STATE_ENDED"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"STATE_ERROR"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"STATE_FAILED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"STATE_IDLE"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"STATE_OPENED"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"STATE_OPENED_WITH_KEYS"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"STATE_OPENING"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"STATE_QUEUED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"STATE_READY"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSession","l":"STATE_RELEASED"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"STATE_REMOVING"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"STATE_RESTARTING"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"STATE_STARTED"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"STATE_STOPPED"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"states"},{"p":"com.google.android.exoplayer2.upstream","c":"StatsDataSource","l":"StatsDataSource(DataSource)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource)"},{"p":"com.google.android.exoplayer2","c":"C","l":"STEREO_MODE_LEFT_RIGHT"},{"p":"com.google.android.exoplayer2","c":"C","l":"STEREO_MODE_MONO"},{"p":"com.google.android.exoplayer2","c":"C","l":"STEREO_MODE_STEREO_MESH"},{"p":"com.google.android.exoplayer2","c":"C","l":"STEREO_MODE_TOP_BOTTOM"},{"p":"com.google.android.exoplayer2","c":"Format","l":"stereoMode"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"STOP_REASON_NONE"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"stop()"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"stop()"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"stop()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"stop()"},{"p":"com.google.android.exoplayer2","c":"Player","l":"stop()"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"stop()"},{"p":"com.google.android.exoplayer2.scheduler","c":"RequirementsWatcher","l":"stop()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"DefaultHlsPlaylistTracker","l":"stop()"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker","l":"stop()"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"stop()"},{"p":"com.google.android.exoplayer2.util","c":"DebugTextViewHelper","l":"stop()"},{"p":"com.google.android.exoplayer2.util","c":"StandaloneMediaClock","l":"stop()"},{"p":"com.google.android.exoplayer2.ext.ima","c":"ImaAdsLoader","l":"stop(AdsMediaSource, AdsLoader.EventListener)","url":"stop(com.google.android.exoplayer2.source.ads.AdsMediaSource,com.google.android.exoplayer2.source.ads.AdsLoader.EventListener)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsLoader","l":"stop(AdsMediaSource, AdsLoader.EventListener)","url":"stop(com.google.android.exoplayer2.source.ads.AdsMediaSource,com.google.android.exoplayer2.source.ads.AdsLoader.EventListener)"},{"p":"com.google.android.exoplayer2","c":"ForwardingPlayer","l":"stop(boolean)"},{"p":"com.google.android.exoplayer2","c":"Player","l":"stop(boolean)"},{"p":"com.google.android.exoplayer2","c":"SimpleExoPlayer","l":"stop(boolean)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"CastPlayer","l":"stop(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"stop(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"stop(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.Stop","l":"Stop(String, boolean)","url":"%3Cinit%3E(java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.Stop","l":"Stop(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"stopReason"},{"p":"com.google.android.exoplayer2.util","c":"FlacConstants","l":"STREAM_INFO_BLOCK_SIZE"},{"p":"com.google.android.exoplayer2.util","c":"FlacConstants","l":"STREAM_MARKER_SIZE"},{"p":"com.google.android.exoplayer2","c":"C","l":"STREAM_TYPE_ALARM"},{"p":"com.google.android.exoplayer2","c":"C","l":"STREAM_TYPE_DEFAULT"},{"p":"com.google.android.exoplayer2","c":"C","l":"STREAM_TYPE_DTMF"},{"p":"com.google.android.exoplayer2","c":"C","l":"STREAM_TYPE_MUSIC"},{"p":"com.google.android.exoplayer2","c":"C","l":"STREAM_TYPE_NOTIFICATION"},{"p":"com.google.android.exoplayer2","c":"C","l":"STREAM_TYPE_RING"},{"p":"com.google.android.exoplayer2","c":"C","l":"STREAM_TYPE_SYSTEM"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util.SyncFrameInfo","l":"STREAM_TYPE_TYPE0"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util.SyncFrameInfo","l":"STREAM_TYPE_TYPE1"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util.SyncFrameInfo","l":"STREAM_TYPE_TYPE2"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util.SyncFrameInfo","l":"STREAM_TYPE_UNDEFINED"},{"p":"com.google.android.exoplayer2","c":"C","l":"STREAM_TYPE_VOICE_CALL"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"StreamElement(String, String, int, String, long, String, int, int, int, int, String, Format[], List, long)","url":"%3Cinit%3E(java.lang.String,java.lang.String,int,java.lang.String,long,java.lang.String,int,int,int,int,java.lang.String,com.google.android.exoplayer2.Format[],java.util.List,long)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest","l":"streamElements"},{"p":"com.google.android.exoplayer2.offline","c":"StreamKey","l":"StreamKey(int, int, int)","url":"%3Cinit%3E(int,int,int)"},{"p":"com.google.android.exoplayer2.offline","c":"StreamKey","l":"StreamKey(int, int)","url":"%3Cinit%3E(int,int)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.PlaybackProperties","l":"streamKeys"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"streamKeys"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util.SyncFrameInfo","l":"streamType"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.EsInfo","l":"streamType"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"EbmlProcessor","l":"stringElement(int, String)","url":"stringElement(int,java.lang.String)"},{"p":"com.google.android.exoplayer2.extractor.mkv","c":"MatroskaExtractor","l":"stringElement(int, String)","url":"stringElement(int,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"StubExoPlayer","l":"StubExoPlayer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"STYLE_BOLD"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"STYLE_BOLD_ITALIC"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"STYLE_ITALIC"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"STYLE_NORMAL"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"StyledPlayerControlView(Context, AttributeSet, int, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet,int,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"StyledPlayerControlView(Context, AttributeSet, int)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet,int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"StyledPlayerControlView(Context, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerControlView","l":"StyledPlayerControlView(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"StyledPlayerView(Context, AttributeSet, int)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet,int)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"StyledPlayerView(Context, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"StyledPlayerView(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"subrange(long, long)","url":"subrange(long,long)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"subrange(long)"},{"p":"com.google.android.exoplayer2.text.subrip","c":"SubripDecoder","l":"SubripDecoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"Format","l":"subsampleOffsetUs"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataInputBuffer","l":"subsampleOffsetUs"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleInputBuffer","l":"subsampleOffsetUs"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts.RequestSet","l":"subset(DataSpec...)","url":"subset(com.google.android.exoplayer2.upstream.DataSpec...)"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts.RequestSet","l":"subset(String...)","url":"subset(java.lang.String...)"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts.RequestSet","l":"subset(Uri...)","url":"subset(android.net.Uri...)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"subtitle"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Subtitle","l":"Subtitle(Uri, String, String, int, int, String)","url":"%3Cinit%3E(android.net.Uri,java.lang.String,java.lang.String,int,int,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Subtitle","l":"Subtitle(Uri, String, String, int)","url":"%3Cinit%3E(android.net.Uri,java.lang.String,java.lang.String,int)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Subtitle","l":"Subtitle(Uri, String, String)","url":"%3Cinit%3E(android.net.Uri,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleDecoderException","l":"SubtitleDecoderException(String, Throwable)","url":"%3Cinit%3E(java.lang.String,java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleDecoderException","l":"SubtitleDecoderException(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleDecoderException","l":"SubtitleDecoderException(Throwable)","url":"%3Cinit%3E(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry.VariantInfo","l":"subtitleGroupId"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Variant","l":"subtitleGroupId"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleInputBuffer","l":"SubtitleInputBuffer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleOutputBuffer","l":"SubtitleOutputBuffer()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.PlaybackProperties","l":"subtitles"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"subtitles"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"SubtitleView(Context, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"SubtitleView(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"subtractWithOverflowDefault(long, long, long)","url":"subtractWithOverflowDefault(long,long,long)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"subType"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"suggestedPresentationDelayMs"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"supplementalData"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"supplementalData"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"AdaptationSet","l":"supplementalProperties"},{"p":"com.google.android.exoplayer2.audio","c":"AudioCapabilities","l":"supportsEncoding(int)"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"DefaultAudioSink","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"ForwardingAudioSink","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Libgav1VideoRenderer","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"LibvpxVideoRenderer","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataDecoderFactory","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.metadata","c":"MetadataRenderer","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeRenderer","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.text","c":"SubtitleDecoderFactory","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.text","c":"TextRenderer","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.video.spherical","c":"CameraMotionRenderer","l":"supportsFormat(Format)","url":"supportsFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"MediaCodecAudioRenderer","l":"supportsFormat(MediaCodecSelector, Format)","url":"supportsFormat(com.google.android.exoplayer2.mediacodec.MediaCodecSelector,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"supportsFormat(MediaCodecSelector, Format)","url":"supportsFormat(com.google.android.exoplayer2.mediacodec.MediaCodecSelector,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"supportsFormat(MediaCodecSelector, Format)","url":"supportsFormat(com.google.android.exoplayer2.mediacodec.MediaCodecSelector,com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegLibrary","l":"supportsFormat(String)","url":"supportsFormat(java.lang.String)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"supportsFormatDrm(Format)","url":"supportsFormatDrm(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.audio","c":"DecoderAudioRenderer","l":"supportsFormatInternal(Format)","url":"supportsFormatInternal(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegAudioRenderer","l":"supportsFormatInternal(Format)","url":"supportsFormatInternal(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.ext.flac","c":"LibflacAudioRenderer","l":"supportsFormatInternal(Format)","url":"supportsFormatInternal(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.ext.opus","c":"LibopusAudioRenderer","l":"supportsFormatInternal(Format)","url":"supportsFormatInternal(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2","c":"BaseRenderer","l":"supportsMixedMimeTypeAdaptation()"},{"p":"com.google.android.exoplayer2","c":"NoSampleRenderer","l":"supportsMixedMimeTypeAdaptation()"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"supportsMixedMimeTypeAdaptation()"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","c":"FfmpegAudioRenderer","l":"supportsMixedMimeTypeAdaptation()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"supportsMixedMimeTypeAdaptation()"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource","l":"supportsRangeRequests()"},{"p":"com.google.android.exoplayer2.testutil","c":"WebServerDispatcher.Resource.Builder","l":"supportsRangeRequests(boolean)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecAdapter.Configuration","l":"surface"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity","l":"surfaceChanged(SurfaceHolder, int, int, int)","url":"surfaceChanged(android.view.SurfaceHolder,int,int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity","l":"surfaceCreated(SurfaceHolder)","url":"surfaceCreated(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2.testutil","c":"HostActivity","l":"surfaceDestroyed(SurfaceHolder)","url":"surfaceDestroyed(android.view.SurfaceHolder)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoDecoderException","l":"surfaceIdentityHashCode"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SmtaMetadataEntry","l":"svcTemporalLayerCount"},{"p":"com.google.android.exoplayer2.ui","c":"PlayerView","l":"switchTargetView(Player, PlayerView, PlayerView)","url":"switchTargetView(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ui.PlayerView,com.google.android.exoplayer2.ui.PlayerView)"},{"p":"com.google.android.exoplayer2.ui","c":"StyledPlayerView","l":"switchTargetView(Player, StyledPlayerView, StyledPlayerView)","url":"switchTargetView(com.google.android.exoplayer2.Player,com.google.android.exoplayer2.ui.StyledPlayerView,com.google.android.exoplayer2.ui.StyledPlayerView)"},{"p":"com.google.android.exoplayer2.util","c":"SystemClock","l":"SystemClock()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.database","c":"DatabaseProvider","l":"TABLE_PREFIX"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"tableExists(SQLiteDatabase, String)","url":"tableExists(android.database.sqlite.SQLiteDatabase,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.PlaybackProperties","l":"tag"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"tag"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoHostedTest","l":"tag"},{"p":"com.google.android.exoplayer2","c":"ExoPlayerLibraryInfo","l":"TAG"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"TAG"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylist","l":"tags"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"targetDurationUs"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.TimestampSearchResult","l":"targetFoundResult(long)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.LiveConfiguration","l":"targetOffsetMs"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ServiceDescriptionElement","l":"targetOffsetMs"},{"p":"com.google.android.exoplayer2.audio","c":"TeeAudioProcessor","l":"TeeAudioProcessor(TeeAudioProcessor.AudioBufferSink)","url":"%3Cinit%3E(com.google.android.exoplayer2.audio.TeeAudioProcessor.AudioBufferSink)"},{"p":"com.google.android.exoplayer2.upstream","c":"TeeDataSource","l":"TeeDataSource(DataSource, DataSink)","url":"%3Cinit%3E(com.google.android.exoplayer2.upstream.DataSource,com.google.android.exoplayer2.upstream.DataSink)"},{"p":"com.google.android.exoplayer2.robolectric","c":"TestDownloadManagerListener","l":"TestDownloadManagerListener(DownloadManager)","url":"%3Cinit%3E(com.google.android.exoplayer2.offline.DownloadManager)"},{"p":"com.google.android.exoplayer2.testutil","c":"TestExoPlayerBuilder","l":"TestExoPlayerBuilder(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"CommentFrame","l":"text"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"InternalFrame","l":"text"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"text"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"TEXT_SIZE_TYPE_ABSOLUTE"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"TEXT_SIZE_TYPE_FRACTIONAL"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"TEXT_SIZE_TYPE_FRACTIONAL_IGNORE_PADDING"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"TEXT_SSA"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"TEXT_VTT"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"textAlignment"},{"p":"com.google.android.exoplayer2.text.span","c":"TextEmphasisSpan","l":"TextEmphasisSpan(int, int, int)","url":"%3Cinit%3E(int,int,int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"TextInformationFrame","l":"TextInformationFrame(String, String, String)","url":"%3Cinit%3E(java.lang.String,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.text","c":"TextRenderer","l":"TextRenderer(TextOutput, Looper, SubtitleDecoderFactory)","url":"%3Cinit%3E(com.google.android.exoplayer2.text.TextOutput,android.os.Looper,com.google.android.exoplayer2.text.SubtitleDecoderFactory)"},{"p":"com.google.android.exoplayer2.text","c":"TextRenderer","l":"TextRenderer(TextOutput, Looper)","url":"%3Cinit%3E(com.google.android.exoplayer2.text.TextOutput,android.os.Looper)"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"textSize"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"textSizeType"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.TextTrackScore","l":"TextTrackScore(Format, DefaultTrackSelector.Parameters, int, String)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters,int,java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.av1","c":"Libgav1VideoRenderer","l":"THREAD_COUNT_AUTODETECT"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"throwPlaybackException(ExoPlaybackException)","url":"throwPlaybackException(com.google.android.exoplayer2.ExoPlaybackException)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.ThrowPlaybackException","l":"ThrowPlaybackException(String, ExoPlaybackException)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.ExoPlaybackException)"},{"p":"com.google.android.exoplayer2","c":"ThumbRating","l":"ThumbRating()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"ThumbRating","l":"ThumbRating(boolean)","url":"%3Cinit%3E(boolean)"},{"p":"com.google.android.exoplayer2","c":"C","l":"TIME_END_OF_SOURCE"},{"p":"com.google.android.exoplayer2","c":"C","l":"TIME_UNSET"},{"p":"com.google.android.exoplayer2.util","c":"TimedValueQueue","l":"TimedValueQueue()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.util","c":"TimedValueQueue","l":"TimedValueQueue(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2","c":"IllegalSeekPositionException","l":"timeline"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"timeline"},{"p":"com.google.android.exoplayer2.source","c":"ForwardingTimeline","l":"timeline"},{"p":"com.google.android.exoplayer2","c":"Player","l":"TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED"},{"p":"com.google.android.exoplayer2","c":"Player","l":"TIMELINE_CHANGE_REASON_SOURCE_UPDATE"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"Timeline()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor","l":"TimelineQueueEditor(MediaControllerCompat, TimelineQueueEditor.QueueDataAdapter, TimelineQueueEditor.MediaDescriptionConverter, TimelineQueueEditor.MediaDescriptionEqualityChecker)","url":"%3Cinit%3E(android.support.v4.media.session.MediaControllerCompat,com.google.android.exoplayer2.ext.mediasession.TimelineQueueEditor.QueueDataAdapter,com.google.android.exoplayer2.ext.mediasession.TimelineQueueEditor.MediaDescriptionConverter,com.google.android.exoplayer2.ext.mediasession.TimelineQueueEditor.MediaDescriptionEqualityChecker)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueEditor","l":"TimelineQueueEditor(MediaControllerCompat, TimelineQueueEditor.QueueDataAdapter, TimelineQueueEditor.MediaDescriptionConverter)","url":"%3Cinit%3E(android.support.v4.media.session.MediaControllerCompat,com.google.android.exoplayer2.ext.mediasession.TimelineQueueEditor.QueueDataAdapter,com.google.android.exoplayer2.ext.mediasession.TimelineQueueEditor.MediaDescriptionConverter)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueNavigator","l":"TimelineQueueNavigator(MediaSessionCompat, int)","url":"%3Cinit%3E(android.support.v4.media.session.MediaSessionCompat,int)"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"TimelineQueueNavigator","l":"TimelineQueueNavigator(MediaSessionCompat)","url":"%3Cinit%3E(android.support.v4.media.session.MediaSessionCompat)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"TimelineWindowDefinition(boolean, boolean, long)","url":"%3Cinit%3E(boolean,boolean,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"TimelineWindowDefinition(int, Object, boolean, boolean, boolean, boolean, long, long, long, AdPlaybackState, MediaItem)","url":"%3Cinit%3E(int,java.lang.Object,boolean,boolean,boolean,boolean,long,long,long,com.google.android.exoplayer2.source.ads.AdPlaybackState,com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"TimelineWindowDefinition(int, Object, boolean, boolean, boolean, boolean, long, long, long, AdPlaybackState)","url":"%3Cinit%3E(int,java.lang.Object,boolean,boolean,boolean,boolean,long,long,long,com.google.android.exoplayer2.source.ads.AdPlaybackState)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"TimelineWindowDefinition(int, Object, boolean, boolean, long, AdPlaybackState)","url":"%3Cinit%3E(int,java.lang.Object,boolean,boolean,long,com.google.android.exoplayer2.source.ads.AdPlaybackState)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"TimelineWindowDefinition(int, Object, boolean, boolean, long)","url":"%3Cinit%3E(int,java.lang.Object,boolean,boolean,long)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"TimelineWindowDefinition(int, Object)","url":"%3Cinit%3E(int,java.lang.Object)"},{"p":"com.google.android.exoplayer2.testutil","c":"DummyMainThread","l":"TIMEOUT_MS"},{"p":"com.google.android.exoplayer2.testutil","c":"MediaSourceTestRunner","l":"TIMEOUT_MS"},{"p":"com.google.android.exoplayer2","c":"ExoTimeoutException","l":"TIMEOUT_OPERATION_DETACH_SURFACE"},{"p":"com.google.android.exoplayer2","c":"ExoTimeoutException","l":"TIMEOUT_OPERATION_RELEASE"},{"p":"com.google.android.exoplayer2","c":"ExoTimeoutException","l":"TIMEOUT_OPERATION_SET_FOREGROUND_MODE"},{"p":"com.google.android.exoplayer2","c":"ExoTimeoutException","l":"TIMEOUT_OPERATION_UNDEFINED"},{"p":"com.google.android.exoplayer2","c":"ExoTimeoutException","l":"timeoutOperation"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"timescale"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"EventStream","l":"timescale"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"timescale"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"timeShiftBufferDepthMs"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"timestamp"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"TimestampAdjuster(long)","url":"%3Cinit%3E(long)"},{"p":"com.google.android.exoplayer2.source.hls","c":"TimestampAdjusterProvider","l":"TimestampAdjusterProvider()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"timestampMs"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker","l":"timestampSeeker"},{"p":"com.google.android.exoplayer2.extractor","c":"ChunkIndex","l":"timesUs"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"timeUs"},{"p":"com.google.android.exoplayer2.decoder","c":"OutputBuffer","l":"timeUs"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekPoint","l":"timeUs"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"timeUs"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.BinarySearchSeekMap","l":"timeUsToTargetTime(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.DefaultSeekTimestampConverter","l":"timeUsToTargetTime(long)"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.SeekTimestampConverter","l":"timeUsToTargetTime(long)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"title"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyInfo","l":"title"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"ProgramInformation","l":"title"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.Segment","l":"title"},{"p":"com.google.android.exoplayer2.util","c":"LongArray","l":"toArray()"},{"p":"com.google.android.exoplayer2","c":"Bundleable","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"HeartRating","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"MediaItem","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.ClippingProperties","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.LiveConfiguration","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"PercentageRating","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"PlaybackException","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"PlaybackParameters","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"Player.Commands","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"StarRating","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"ThumbRating","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"toBundle()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes","l":"toBundle()"},{"p":"com.google.android.exoplayer2.device","c":"DeviceInfo","l":"toBundle()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"toBundle()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"toBundle()"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"toBundle()"},{"p":"com.google.android.exoplayer2.video","c":"VideoSize","l":"toBundle()"},{"p":"com.google.android.exoplayer2","c":"Timeline","l":"toBundle(boolean)"},{"p":"com.google.android.exoplayer2.util","c":"BundleableUtils","l":"toBundleArrayList(List)","url":"toBundleArrayList(java.util.List)"},{"p":"com.google.android.exoplayer2.util","c":"BundleableUtils","l":"toBundleList(List)","url":"toBundleList(java.util.List)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"toByteArray(InputStream)","url":"toByteArray(java.io.InputStream)"},{"p":"com.google.android.exoplayer2.source.mediaparser","c":"MediaParserUtil","l":"toCaptionsMediaFormat(Format)","url":"toCaptionsMediaFormat(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"toHexString(byte[])"},{"p":"com.google.android.exoplayer2","c":"SeekParameters","l":"toleranceAfterUs"},{"p":"com.google.android.exoplayer2","c":"SeekParameters","l":"toleranceBeforeUs"},{"p":"com.google.android.exoplayer2","c":"Format","l":"toLogString(Format)","url":"toLogString(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"toLong(int, int)","url":"toLong(int,int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"toMediaItem()"},{"p":"com.google.android.exoplayer2.ext.cast","c":"DefaultMediaItemConverter","l":"toMediaItem(MediaQueueItem)","url":"toMediaItem(com.google.android.gms.cast.MediaQueueItem)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"MediaItemConverter","l":"toMediaItem(MediaQueueItem)","url":"toMediaItem(com.google.android.gms.cast.MediaQueueItem)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"DefaultMediaItemConverter","l":"toMediaQueueItem(MediaItem)","url":"toMediaQueueItem(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.ext.cast","c":"MediaItemConverter","l":"toMediaQueueItem(MediaItem)","url":"toMediaQueueItem(com.google.android.exoplayer2.MediaItem)"},{"p":"com.google.android.exoplayer2.util","c":"BundleableUtils","l":"toNullableBundle(Bundleable)","url":"toNullableBundle(com.google.android.exoplayer2.Bundleable)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"toString()"},{"p":"com.google.android.exoplayer2","c":"PlaybackParameters","l":"toString()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioCapabilities","l":"toString()"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor.AudioFormat","l":"toString()"},{"p":"com.google.android.exoplayer2.extractor","c":"ChunkIndex","l":"toString()"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap.SeekPoints","l":"toString()"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekPoint","l":"toString()"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","c":"AppInfoTable","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"VorbisComment","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyInfo","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ApicFrame","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"CommentFrame","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"GeobFrame","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"Id3Frame","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"InternalFrame","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"PrivFrame","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"TextInformationFrame","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"UrlLinkFrame","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MdtaMetadataEntry","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MotionPhotoMetadata","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData.Segment","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SmtaMetadataEntry","l":"toString()"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceCommand","l":"toString()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"toString()"},{"p":"com.google.android.exoplayer2.offline","c":"StreamKey","l":"toString()"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"toString()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"RangedUri","l":"toString()"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"UtcTimingElement","l":"toString()"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry","l":"toString()"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"toString()"},{"p":"com.google.android.exoplayer2.testutil","c":"Dumper","l":"toString()"},{"p":"com.google.android.exoplayer2.testutil","c":"ExtractorAsserts.SimulationConfig","l":"toString()"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"toString()"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheSpan","l":"toString()"},{"p":"com.google.android.exoplayer2.video","c":"ColorInfo","l":"toString()"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalAudioFormatBitrateTimeProduct"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalAudioFormatTimeMs"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalAudioUnderruns"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection.AdaptationCheckpoint","l":"totalBandwidth"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalBandwidthBytes"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalBandwidthTimeMs"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"totalBufferedDurationMs"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"totalDiscCount"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalDroppedFrames"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalInitialAudioFormatBitrate"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalInitialVideoFormatBitrate"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalInitialVideoFormatHeight"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalPauseBufferCount"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalPauseCount"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalRebufferCount"},{"p":"com.google.android.exoplayer2.extractor","c":"FlacStreamMetadata","l":"totalSamples"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalSeekCount"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"totalTrackCount"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalValidJoinTimeMs"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalVideoFormatBitrateTimeMs"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalVideoFormatBitrateTimeProduct"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalVideoFormatHeightTimeMs"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"totalVideoFormatHeightTimeProduct"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"totalVideoFrameProcessingOffsetUs"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"toUnsignedLong(int)"},{"p":"com.google.android.exoplayer2","c":"ExoPlayerLibraryInfo","l":"TRACE_ENABLED"},{"p":"com.google.android.exoplayer2","c":"C","l":"TRACK_TYPE_AUDIO"},{"p":"com.google.android.exoplayer2","c":"C","l":"TRACK_TYPE_CAMERA_MOTION"},{"p":"com.google.android.exoplayer2","c":"C","l":"TRACK_TYPE_CUSTOM_BASE"},{"p":"com.google.android.exoplayer2","c":"C","l":"TRACK_TYPE_DEFAULT"},{"p":"com.google.android.exoplayer2","c":"C","l":"TRACK_TYPE_IMAGE"},{"p":"com.google.android.exoplayer2","c":"C","l":"TRACK_TYPE_METADATA"},{"p":"com.google.android.exoplayer2","c":"C","l":"TRACK_TYPE_NONE"},{"p":"com.google.android.exoplayer2","c":"C","l":"TRACK_TYPE_TEXT"},{"p":"com.google.android.exoplayer2","c":"C","l":"TRACK_TYPE_UNKNOWN"},{"p":"com.google.android.exoplayer2","c":"C","l":"TRACK_TYPE_VIDEO"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"Track(int, int, long, long, long, Format, int, TrackEncryptionBox[], int, long[], long[])","url":"%3Cinit%3E(int,int,long,long,long,com.google.android.exoplayer2.Format,int,com.google.android.exoplayer2.extractor.mp4.TrackEncryptionBox[],int,long[],long[])"},{"p":"com.google.android.exoplayer2.extractor","c":"DummyExtractorOutput","l":"track(int, int)","url":"track(int,int)"},{"p":"com.google.android.exoplayer2.extractor","c":"ExtractorOutput","l":"track(int, int)","url":"track(int,int)"},{"p":"com.google.android.exoplayer2.extractor.jpeg","c":"StartOffsetExtractorOutput","l":"track(int, int)","url":"track(int,int)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BaseMediaChunkOutput","l":"track(int, int)","url":"track(int,int)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"BundledChunkExtractor","l":"track(int, int)","url":"track(int,int)"},{"p":"com.google.android.exoplayer2.source.chunk","c":"ChunkExtractor.TrackOutputProvider","l":"track(int, int)","url":"track(int,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorOutput","l":"track(int, int)","url":"track(int,int)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"TrackEncryptionBox","l":"TrackEncryptionBox(boolean, String, int, byte[], int, int, byte[])","url":"%3Cinit%3E(boolean,java.lang.String,int,byte[],int,int,byte[])"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.ProtectionElement","l":"trackEncryptionBoxes"},{"p":"com.google.android.exoplayer2.source","c":"MediaLoadData","l":"trackFormat"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"trackFormat"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroup","l":"TrackGroup(Format...)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format...)"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroupArray","l":"TrackGroupArray(TrackGroup...)","url":"%3Cinit%3E(com.google.android.exoplayer2.source.TrackGroup...)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.TrackIdGenerator","l":"TrackIdGenerator(int, int, int)","url":"%3Cinit%3E(int,int,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.TrackIdGenerator","l":"TrackIdGenerator(int, int)","url":"%3Cinit%3E(int,int)"},{"p":"com.google.android.exoplayer2.offline","c":"StreamKey","l":"trackIndex"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"trackNumber"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorOutput","l":"trackOutputs"},{"p":"com.google.android.exoplayer2.trackselection","c":"BaseTrackSelection","l":"tracks"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.SelectionOverride","l":"tracks"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection.Definition","l":"tracks"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionArray","l":"TrackSelectionArray(TrackSelection...)","url":"%3Cinit%3E(com.google.android.exoplayer2.trackselection.TrackSelection...)"},{"p":"com.google.android.exoplayer2.source","c":"MediaLoadData","l":"trackSelectionData"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"trackSelectionData"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder","l":"TrackSelectionDialogBuilder(Context, CharSequence, DefaultTrackSelector, int)","url":"%3Cinit%3E(android.content.Context,java.lang.CharSequence,com.google.android.exoplayer2.trackselection.DefaultTrackSelector,int)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionDialogBuilder","l":"TrackSelectionDialogBuilder(Context, CharSequence, MappingTrackSelector.MappedTrackInfo, int, TrackSelectionDialogBuilder.DialogCallback)","url":"%3Cinit%3E(android.content.Context,java.lang.CharSequence,com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo,int,com.google.android.exoplayer2.ui.TrackSelectionDialogBuilder.DialogCallback)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"TrackSelectionParameters(TrackSelectionParameters.Builder)","url":"%3Cinit%3E(com.google.android.exoplayer2.trackselection.TrackSelectionParameters.Builder)"},{"p":"com.google.android.exoplayer2.source","c":"MediaLoadData","l":"trackSelectionReason"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"trackSelectionReason"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionView","l":"TrackSelectionView(Context, AttributeSet, int)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet,int)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionView","l":"TrackSelectionView(Context, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.ui","c":"TrackSelectionView","l":"TrackSelectionView(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelector","l":"TrackSelector()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectorResult","l":"TrackSelectorResult(RendererConfiguration[], ExoTrackSelection[], Object)","url":"%3Cinit%3E(com.google.android.exoplayer2.RendererConfiguration[],com.google.android.exoplayer2.trackselection.ExoTrackSelection[],java.lang.Object)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExtractorOutput","l":"tracksEnded"},{"p":"com.google.android.exoplayer2.source","c":"MediaLoadData","l":"trackType"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"trailingParts"},{"p":"com.google.android.exoplayer2.upstream","c":"BaseDataSource","l":"transferEnded()"},{"p":"com.google.android.exoplayer2.upstream","c":"BaseDataSource","l":"transferInitializing(DataSpec)","url":"transferInitializing(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"transferListenerCallbacks()"},{"p":"com.google.android.exoplayer2.upstream","c":"BaseDataSource","l":"transferStarted(DataSpec)","url":"transferStarted(com.google.android.exoplayer2.upstream.DataSpec)"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"TRANSFORMATION_CEA608_CDAT"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"TRANSFORMATION_NONE"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.Mode","l":"transformType"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"triggerEvent(Predicate, int, int, byte[])","url":"triggerEvent(com.google.common.base.Predicate,int,int,byte[])"},{"p":"com.google.android.exoplayer2.upstream","c":"Allocator","l":"trim()"},{"p":"com.google.android.exoplayer2.upstream","c":"DefaultAllocator","l":"trim()"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"TRUEHD_MAX_RATE_BYTES_PER_SECOND"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"TRUEHD_RECHUNK_SAMPLE_COUNT"},{"p":"com.google.android.exoplayer2.audio","c":"Ac3Util","l":"TRUEHD_SYNCFRAME_PREFIX_LENGTH"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"truncateAscii(CharSequence, int)","url":"truncateAscii(java.lang.CharSequence,int)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"TS"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_PACKET_SIZE"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_AAC_ADTS"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_AAC_LATM"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_AC3"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_AC4"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_AIT"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_DTS"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_DVBSUBS"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_E_AC3"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_H262"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_H263"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_H264"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_H265"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_HDMV_DTS"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_ID3"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_MPA"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_MPA_LSF"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_STREAM_TYPE_SPLICE_INFO"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TS_SYNC_BYTE"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TsExtractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TsExtractor(int, int, int)","url":"%3Cinit%3E(int,int,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TsExtractor(int, TimestampAdjuster, TsPayloadReader.Factory, int)","url":"%3Cinit%3E(int,com.google.android.exoplayer2.util.TimestampAdjuster,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.Factory,int)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TsExtractor(int, TimestampAdjuster, TsPayloadReader.Factory)","url":"%3Cinit%3E(int,com.google.android.exoplayer2.util.TimestampAdjuster,com.google.android.exoplayer2.extractor.ts.TsPayloadReader.Factory)"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsExtractor","l":"TsExtractor(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.text.ttml","c":"TtmlDecoder","l":"TtmlDecoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2","c":"RendererConfiguration","l":"tunneling"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"tunneling"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"TUNNELING_NOT_SUPPORTED"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"TUNNELING_SUPPORT_MASK"},{"p":"com.google.android.exoplayer2","c":"RendererCapabilities","l":"TUNNELING_SUPPORTED"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"tunnelingEnabled"},{"p":"com.google.android.exoplayer2.text.tx3g","c":"Tx3gDecoder","l":"Tx3gDecoder(List)","url":"%3Cinit%3E(java.util.List)"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"type"},{"p":"com.google.android.exoplayer2.extractor.mp4","c":"Track","l":"type"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"TsPayloadReader.DvbSubtitleInfo","l":"type"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource.AdLoadException","l":"type"},{"p":"com.google.android.exoplayer2.source.chunk","c":"Chunk","l":"type"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"AdaptationSet","l":"type"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.StreamElement","l":"type"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.SelectionOverride","l":"type"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection.Definition","l":"type"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.HttpDataSourceException","l":"type"},{"p":"com.google.android.exoplayer2.upstream","c":"LoadErrorHandlingPolicy.FallbackSelection","l":"type"},{"p":"com.google.android.exoplayer2.upstream","c":"ParsingLoadable","l":"type"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource.AdLoadException","l":"TYPE_AD"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource.AdLoadException","l":"TYPE_AD_GROUP"},{"p":"com.google.android.exoplayer2.audio","c":"WavUtil","l":"TYPE_ALAW"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource.AdLoadException","l":"TYPE_ALL_ADS"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.HttpDataSourceException","l":"TYPE_CLOSE"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelection","l":"TYPE_CUSTOM_BASE"},{"p":"com.google.android.exoplayer2","c":"C","l":"TYPE_DASH"},{"p":"com.google.android.exoplayer2.audio","c":"WavUtil","l":"TYPE_FLOAT"},{"p":"com.google.android.exoplayer2","c":"C","l":"TYPE_HLS"},{"p":"com.google.android.exoplayer2.audio","c":"WavUtil","l":"TYPE_IMA_ADPCM"},{"p":"com.google.android.exoplayer2.audio","c":"WavUtil","l":"TYPE_MLAW"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.TimestampSearchResult","l":"TYPE_NO_TIMESTAMP"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.HttpDataSourceException","l":"TYPE_OPEN"},{"p":"com.google.android.exoplayer2","c":"C","l":"TYPE_OTHER"},{"p":"com.google.android.exoplayer2.audio","c":"WavUtil","l":"TYPE_PCM"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.TimestampSearchResult","l":"TYPE_POSITION_OVERESTIMATED"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.TimestampSearchResult","l":"TYPE_POSITION_UNDERESTIMATED"},{"p":"com.google.android.exoplayer2.upstream","c":"HttpDataSource.HttpDataSourceException","l":"TYPE_READ"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"TYPE_REMOTE"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"TYPE_RENDERER"},{"p":"com.google.android.exoplayer2","c":"C","l":"TYPE_RTSP"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"TYPE_SOURCE"},{"p":"com.google.android.exoplayer2","c":"C","l":"TYPE_SS"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.TimestampSearchResult","l":"TYPE_TARGET_TIMESTAMP_FOUND"},{"p":"com.google.android.exoplayer2","c":"ExoPlaybackException","l":"TYPE_UNEXPECTED"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdsMediaSource.AdLoadException","l":"TYPE_UNEXPECTED"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"TYPE_UNSET"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelection","l":"TYPE_UNSET"},{"p":"com.google.android.exoplayer2.audio","c":"WavUtil","l":"TYPE_WAVE_FORMAT_EXTENSIBLE"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"typeface"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MdtaMetadataEntry","l":"typeIndicator"},{"p":"com.google.android.exoplayer2.upstream","c":"UdpDataSource","l":"UDP_PORT_UNSET"},{"p":"com.google.android.exoplayer2.upstream","c":"UdpDataSource","l":"UdpDataSource()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream","c":"UdpDataSource","l":"UdpDataSource(int, int)","url":"%3Cinit%3E(int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"UdpDataSource","l":"UdpDataSource(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"UdpDataSource.UdpDataSourceException","l":"UdpDataSourceException(Throwable, int)","url":"%3Cinit%3E(java.lang.Throwable,int)"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"uid"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"uid"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"Cache","l":"UID_UNSET"},{"p":"com.google.android.exoplayer2.video","c":"VideoSize","l":"unappliedRotationDegrees"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"unboundedDataSpec_readUntilEnd()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"unboundedDataSpecWithGzipFlag_readUntilEnd()"},{"p":"com.google.android.exoplayer2.testutil","c":"DataSourceContractTest","l":"unboundedReadsAreIndefinite()"},{"p":"com.google.android.exoplayer2.extractor","c":"BinarySearchSeeker.TimestampSearchResult","l":"underestimatedResult(long, long)","url":"underestimatedResult(long,long)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioRendererEventListener.EventDispatcher","l":"underrun(int, long, long)","url":"underrun(int,long,long)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"unescapeFileName(String)","url":"unescapeFileName(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil","l":"unescapeStream(byte[], int)","url":"unescapeStream(byte[],int)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.UnexpectedDiscontinuityException","l":"UnexpectedDiscontinuityException(long, long)","url":"%3Cinit%3E(long,long)"},{"p":"com.google.android.exoplayer2.upstream","c":"Loader.UnexpectedLoaderException","l":"UnexpectedLoaderException(Throwable)","url":"%3Cinit%3E(java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioProcessor.UnhandledAudioFormatException","l":"UnhandledAudioFormatException(AudioProcessor.AudioFormat)","url":"%3Cinit%3E(com.google.android.exoplayer2.audio.AudioProcessor.AudioFormat)"},{"p":"com.google.android.exoplayer2.util","c":"GlUtil.Uniform","l":"Uniform(int, int)","url":"%3Cinit%3E(int,int)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"uniqueProgramId"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.Event","l":"uniqueProgramId"},{"p":"com.google.android.exoplayer2.device","c":"DeviceInfo","l":"UNKNOWN"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"UNKNOWN"},{"p":"com.google.android.exoplayer2.video","c":"VideoSize","l":"UNKNOWN"},{"p":"com.google.android.exoplayer2.source","c":"UnrecognizedInputFormatException","l":"UnrecognizedInputFormatException(String, Uri)","url":"%3Cinit%3E(java.lang.String,android.net.Uri)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioCapabilitiesReceiver","l":"unregister()"},{"p":"com.google.android.exoplayer2.ext.mediasession","c":"MediaSessionConnector","l":"unregisterCustomCommandReceiver(MediaSessionConnector.CommandReceiver)","url":"unregisterCustomCommandReceiver(com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.CommandReceiver)"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap.Unseekable","l":"Unseekable(long, long)","url":"%3Cinit%3E(long,long)"},{"p":"com.google.android.exoplayer2.extractor","c":"SeekMap.Unseekable","l":"Unseekable(long)","url":"%3Cinit%3E(long)"},{"p":"com.google.android.exoplayer2","c":"MediaItem.LiveConfiguration","l":"UNSET"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest","l":"UNSET_LOOKAHEAD"},{"p":"com.google.android.exoplayer2.source","c":"ShuffleOrder.UnshuffledShuffleOrder","l":"UnshuffledShuffleOrder(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"UNSPECIFIED"},{"p":"com.google.android.exoplayer2.drm","c":"UnsupportedDrmException","l":"UnsupportedDrmException(int, Exception)","url":"%3Cinit%3E(int,java.lang.Exception)"},{"p":"com.google.android.exoplayer2.drm","c":"UnsupportedDrmException","l":"UnsupportedDrmException(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.drm","c":"UnsupportedMediaCrypto","l":"UnsupportedMediaCrypto()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest.UnsupportedRequestException","l":"UnsupportedRequestException()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesFlushingCipher","l":"update(byte[], int, int, byte[], int)","url":"update(byte[],int,int,byte[],int)"},{"p":"com.google.android.exoplayer2.util","c":"DebugTextViewHelper","l":"updateAndPost()"},{"p":"com.google.android.exoplayer2.source","c":"ClippingMediaPeriod","l":"updateClipping(long, long)","url":"updateClipping(long,long)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"updateCodecOperatingRate()"},{"p":"com.google.android.exoplayer2.video","c":"DecoderVideoRenderer","l":"updateDroppedBufferCounters(int)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"updateDroppedBufferCounters(int)"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesFlushingCipher","l":"updateInPlace(byte[], int, int)","url":"updateInPlace(byte[],int,int)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashChunkSource","l":"updateManifest(DashManifest, int)","url":"updateManifest(com.google.android.exoplayer2.source.dash.manifest.DashManifest,int)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"updateManifest(DashManifest, int)","url":"updateManifest(com.google.android.exoplayer2.source.dash.manifest.DashManifest,int)"},{"p":"com.google.android.exoplayer2.source.dash","c":"PlayerEmsgHandler","l":"updateManifest(DashManifest)","url":"updateManifest(com.google.android.exoplayer2.source.dash.manifest.DashManifest)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource","l":"updateManifest(SsManifest)","url":"updateManifest(com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsChunkSource","l":"updateManifest(SsManifest)","url":"updateManifest(com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest)"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsCollector","l":"updateMediaPeriodQueueInfo(List, MediaSource.MediaPeriodId)","url":"updateMediaPeriodQueueInfo(java.util.List,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.ext.gvr","c":"GvrAudioProcessor","l":"updateOrientation(float, float, float, float)","url":"updateOrientation(float,float,float,float)"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecRenderer","l":"updateOutputFormatForTime(long)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionUtil","l":"updateParametersWithOverride(DefaultTrackSelector.Parameters, int, TrackGroupArray, boolean, DefaultTrackSelector.SelectionOverride)","url":"updateParametersWithOverride(com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters,int,com.google.android.exoplayer2.source.TrackGroupArray,boolean,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride)"},{"p":"com.google.android.exoplayer2.ext.media2","c":"SessionPlayerConnector","l":"updatePlaylistMetadata(MediaMetadata)","url":"updatePlaylistMetadata(androidx.media2.common.MediaMetadata)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTrackSelection","l":"updateSelectedTrack(long, long, long, List, MediaChunkIterator[])","url":"updateSelectedTrack(long,long,long,java.util.List,com.google.android.exoplayer2.source.chunk.MediaChunkIterator[])"},{"p":"com.google.android.exoplayer2.trackselection","c":"AdaptiveTrackSelection","l":"updateSelectedTrack(long, long, long, List, MediaChunkIterator[])","url":"updateSelectedTrack(long,long,long,java.util.List,com.google.android.exoplayer2.source.chunk.MediaChunkIterator[])"},{"p":"com.google.android.exoplayer2.trackselection","c":"ExoTrackSelection","l":"updateSelectedTrack(long, long, long, List, MediaChunkIterator[])","url":"updateSelectedTrack(long,long,long,java.util.List,com.google.android.exoplayer2.source.chunk.MediaChunkIterator[])"},{"p":"com.google.android.exoplayer2.trackselection","c":"FixedTrackSelection","l":"updateSelectedTrack(long, long, long, List, MediaChunkIterator[])","url":"updateSelectedTrack(long,long,long,java.util.List,com.google.android.exoplayer2.source.chunk.MediaChunkIterator[])"},{"p":"com.google.android.exoplayer2.trackselection","c":"RandomTrackSelection","l":"updateSelectedTrack(long, long, long, List, MediaChunkIterator[])","url":"updateSelectedTrack(long,long,long,java.util.List,com.google.android.exoplayer2.source.chunk.MediaChunkIterator[])"},{"p":"com.google.android.exoplayer2.analytics","c":"DefaultPlaybackSessionManager","l":"updateSessions(AnalyticsListener.EventTime)","url":"updateSessions(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackSessionManager","l":"updateSessions(AnalyticsListener.EventTime)","url":"updateSessions(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.analytics","c":"DefaultPlaybackSessionManager","l":"updateSessionsWithDiscontinuity(AnalyticsListener.EventTime, int)","url":"updateSessionsWithDiscontinuity(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackSessionManager","l":"updateSessionsWithDiscontinuity(AnalyticsListener.EventTime, int)","url":"updateSessionsWithDiscontinuity(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime,int)"},{"p":"com.google.android.exoplayer2.analytics","c":"DefaultPlaybackSessionManager","l":"updateSessionsWithTimelineChange(AnalyticsListener.EventTime)","url":"updateSessionsWithTimelineChange(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackSessionManager","l":"updateSessionsWithTimelineChange(AnalyticsListener.EventTime)","url":"updateSessionsWithTimelineChange(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)"},{"p":"com.google.android.exoplayer2.offline","c":"Download","l":"updateTimeMs"},{"p":"com.google.android.exoplayer2.source.dash","c":"DashChunkSource","l":"updateTrackSelection(ExoTrackSelection)","url":"updateTrackSelection(com.google.android.exoplayer2.trackselection.ExoTrackSelection)"},{"p":"com.google.android.exoplayer2.source.dash","c":"DefaultDashChunkSource","l":"updateTrackSelection(ExoTrackSelection)","url":"updateTrackSelection(com.google.android.exoplayer2.trackselection.ExoTrackSelection)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"DefaultSsChunkSource","l":"updateTrackSelection(ExoTrackSelection)","url":"updateTrackSelection(com.google.android.exoplayer2.trackselection.ExoTrackSelection)"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","c":"SsChunkSource","l":"updateTrackSelection(ExoTrackSelection)","url":"updateTrackSelection(com.google.android.exoplayer2.trackselection.ExoTrackSelection)"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer","l":"updateVideoFrameProcessingOffsetCounters(long)"},{"p":"com.google.android.exoplayer2.offline","c":"ActionFileUpgradeUtil","l":"upgradeAndDelete(File, ActionFileUpgradeUtil.DownloadIdProvider, DefaultDownloadIndex, boolean, boolean)","url":"upgradeAndDelete(java.io.File,com.google.android.exoplayer2.offline.ActionFileUpgradeUtil.DownloadIdProvider,com.google.android.exoplayer2.offline.DefaultDownloadIndex,boolean,boolean)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"upstreamDiscarded(int, long, long)","url":"upstreamDiscarded(int,long,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"upstreamDiscarded(MediaLoadData)","url":"upstreamDiscarded(com.google.android.exoplayer2.source.MediaLoadData)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeClock","l":"uptimeMillis()"},{"p":"com.google.android.exoplayer2.util","c":"Clock","l":"uptimeMillis()"},{"p":"com.google.android.exoplayer2.util","c":"SystemClock","l":"uptimeMillis()"},{"p":"com.google.android.exoplayer2","c":"MediaItem.PlaybackProperties","l":"uri"},{"p":"com.google.android.exoplayer2","c":"MediaItem.Subtitle","l":"uri"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"uri"},{"p":"com.google.android.exoplayer2.source","c":"LoadEventInfo","l":"uri"},{"p":"com.google.android.exoplayer2.source","c":"UnrecognizedInputFormatException","l":"uri"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Representation.SingleSegmentRepresentation","l":"uri"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeDataSet.FakeData","l":"uri"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"uri"},{"p":"com.google.android.exoplayer2.drm","c":"MediaDrmCallbackException","l":"uriAfterRedirects"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"uriPositionOffset"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"uris"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","c":"AppInfoTable","l":"url"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"url"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyInfo","l":"url"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"UrlLinkFrame","l":"url"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"BaseUrl","l":"url"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Rendition","l":"url"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Variant","l":"url"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist.SegmentBase","l":"url"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker.PlaylistResetException","l":"url"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsPlaylistTracker.PlaylistStuckException","l":"url"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"UrlLinkFrame","l":"UrlLinkFrame(String, String, String)","url":"%3Cinit%3E(java.lang.String,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioAttributes","l":"usage"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_ALARM"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_ASSISTANCE_ACCESSIBILITY"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_ASSISTANCE_SONIFICATION"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_ASSISTANT"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_GAME"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_MEDIA"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_NOTIFICATION"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_NOTIFICATION_COMMUNICATION_DELAYED"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_NOTIFICATION_COMMUNICATION_INSTANT"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_NOTIFICATION_COMMUNICATION_REQUEST"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_NOTIFICATION_EVENT"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_NOTIFICATION_RINGTONE"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_UNKNOWN"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_VOICE_COMMUNICATION"},{"p":"com.google.android.exoplayer2","c":"C","l":"USAGE_VOICE_COMMUNICATION_SIGNALLING"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"USE_TRACK_COLOR_SETTINGS"},{"p":"com.google.android.exoplayer2.testutil","c":"CacheAsserts.RequestSet","l":"useBoundedDataSpecFor(String)","url":"useBoundedDataSpecFor(java.lang.String)"},{"p":"com.google.android.exoplayer2.extractor","c":"CeaUtil","l":"USER_DATA_IDENTIFIER_GA94"},{"p":"com.google.android.exoplayer2.extractor","c":"CeaUtil","l":"USER_DATA_TYPE_CODE_MPEG_CC"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"userRating"},{"p":"com.google.android.exoplayer2","c":"C","l":"usToMs(long)"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"usToNonWrappedPts(long)"},{"p":"com.google.android.exoplayer2.util","c":"TimestampAdjuster","l":"usToWrappedPts(long)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.ComponentSplice","l":"utcSpliceTime"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand.Event","l":"utcSpliceTime"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"DashManifest","l":"utcTiming"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"UtcTimingElement","l":"UtcTimingElement(String, String)","url":"%3Cinit%3E(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2","c":"C","l":"UTF16_NAME"},{"p":"com.google.android.exoplayer2","c":"C","l":"UTF16LE_NAME"},{"p":"com.google.android.exoplayer2","c":"C","l":"UTF8_NAME"},{"p":"com.google.android.exoplayer2","c":"MediaItem.DrmConfiguration","l":"uuid"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"uuid"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaCrypto","l":"uuid"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","c":"SsManifest.ProtectionElement","l":"uuid"},{"p":"com.google.android.exoplayer2","c":"C","l":"UUID_NIL"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeExoMediaDrm","l":"VALID_PROVISION_RESPONSE"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttParserUtil","l":"validateWebvttHeaderLine(ParsableByteArray)","url":"validateWebvttHeaderLine(com.google.android.exoplayer2.util.ParsableByteArray)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"validJoinTimeCount"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"value"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"VorbisComment","l":"value"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"TextInformationFrame","l":"value"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MdtaMetadataEntry","l":"value"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"Descriptor","l":"value"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"EventStream","l":"value"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"UtcTimingElement","l":"value"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"variableDefinitions"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Variant","l":"Variant(Uri, Format, String, String, String, String)","url":"%3Cinit%3E(android.net.Uri,com.google.android.exoplayer2.Format,java.lang.String,java.lang.String,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry.VariantInfo","l":"VariantInfo(int, int, String, String, String, String)","url":"%3Cinit%3E(int,int,java.lang.String,java.lang.String,java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry","l":"variantInfos"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"variants"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.CommentHeader","l":"vendor"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecInfo","l":"vendor"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil","l":"verifyVorbisHeaderCapturePattern(int, ParsableByteArray, boolean)","url":"verifyVorbisHeaderCapturePattern(int,com.google.android.exoplayer2.util.ParsableByteArray,boolean)"},{"p":"com.google.android.exoplayer2.audio","c":"MpegAudioUtil.Header","l":"version"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.VorbisIdHeader","l":"version"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMediaPlaylist","l":"version"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"version"},{"p":"com.google.android.exoplayer2","c":"ExoPlayerLibraryInfo","l":"VERSION"},{"p":"com.google.android.exoplayer2","c":"ExoPlayerLibraryInfo","l":"VERSION_INT"},{"p":"com.google.android.exoplayer2","c":"ExoPlayerLibraryInfo","l":"VERSION_SLASHY"},{"p":"com.google.android.exoplayer2.database","c":"VersionTable","l":"VERSION_UNSET"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"VERTICAL_TYPE_LR"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"VERTICAL_TYPE_RL"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"verticalType"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_AV1"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_DIVX"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_DOLBY_VISION"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_FLV"},{"p":"com.google.android.exoplayer2.testutil","c":"ExoPlayerTestRunner","l":"VIDEO_FORMAT"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_H263"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_H264"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_H265"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_MATROSKA"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_MP2T"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_MP4"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_MP4V"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_MPEG"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_MPEG2"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_OGG"},{"p":"com.google.android.exoplayer2","c":"C","l":"VIDEO_OUTPUT_MODE_NONE"},{"p":"com.google.android.exoplayer2","c":"C","l":"VIDEO_OUTPUT_MODE_SURFACE_YUV"},{"p":"com.google.android.exoplayer2","c":"C","l":"VIDEO_OUTPUT_MODE_YUV"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_PS"},{"p":"com.google.android.exoplayer2","c":"C","l":"VIDEO_SCALING_MODE_DEFAULT"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"VIDEO_SCALING_MODE_DEFAULT"},{"p":"com.google.android.exoplayer2","c":"C","l":"VIDEO_SCALING_MODE_SCALE_TO_FIT"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"VIDEO_SCALING_MODE_SCALE_TO_FIT"},{"p":"com.google.android.exoplayer2","c":"C","l":"VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING"},{"p":"com.google.android.exoplayer2","c":"Renderer","l":"VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"VIDEO_STREAM"},{"p":"com.google.android.exoplayer2.extractor.ts","c":"PsExtractor","l":"VIDEO_STREAM_MASK"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_UNKNOWN"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_VC1"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_VP8"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_VP9"},{"p":"com.google.android.exoplayer2.util","c":"MimeTypes","l":"VIDEO_WEBM"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener.EventDispatcher","l":"videoCodecError(Exception)","url":"videoCodecError(java.lang.Exception)"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderGLSurfaceView","l":"VideoDecoderGLSurfaceView(Context, AttributeSet)","url":"%3Cinit%3E(android.content.Context,android.util.AttributeSet)"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderGLSurfaceView","l":"VideoDecoderGLSurfaceView(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderInputBuffer","l":"VideoDecoderInputBuffer(int, int)","url":"%3Cinit%3E(int,int)"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderInputBuffer","l":"VideoDecoderInputBuffer(int)","url":"%3Cinit%3E(int)"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"VideoDecoderOutputBuffer(OutputBuffer.Owner)","url":"%3Cinit%3E(com.google.android.exoplayer2.decoder.OutputBuffer.Owner)"},{"p":"com.google.android.exoplayer2.analytics","c":"PlaybackStats","l":"videoFormatHistory"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderCounters","l":"videoFrameProcessingOffsetCount"},{"p":"com.google.android.exoplayer2.video","c":"VideoFrameReleaseHelper","l":"VideoFrameReleaseHelper(Context)","url":"%3Cinit%3E(android.content.Context)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry.VariantInfo","l":"videoGroupId"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist.Variant","l":"videoGroupId"},{"p":"com.google.android.exoplayer2.source.hls.playlist","c":"HlsMasterPlaylist","l":"videos"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MotionPhotoMetadata","l":"videoSize"},{"p":"com.google.android.exoplayer2.video","c":"VideoSize","l":"VideoSize(int, int, int, float)","url":"%3Cinit%3E(int,int,int,float)"},{"p":"com.google.android.exoplayer2.video","c":"VideoSize","l":"VideoSize(int, int)","url":"%3Cinit%3E(int,int)"},{"p":"com.google.android.exoplayer2.video","c":"VideoRendererEventListener.EventDispatcher","l":"videoSizeChanged(VideoSize)","url":"videoSizeChanged(com.google.android.exoplayer2.video.VideoSize)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MotionPhotoMetadata","l":"videoStartPosition"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.VideoTrackScore","l":"VideoTrackScore(Format, DefaultTrackSelector.Parameters, int, boolean)","url":"%3Cinit%3E(com.google.android.exoplayer2.Format,com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters,int,boolean)"},{"p":"com.google.android.exoplayer2.ui","c":"AdOverlayInfo","l":"view"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"VIEW_TYPE_CANVAS"},{"p":"com.google.android.exoplayer2.ui","c":"SubtitleView","l":"VIEW_TYPE_WEB"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"viewportHeight"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"viewportOrientationMayChange"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"viewportWidth"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisBitArray","l":"VorbisBitArray(byte[])","url":"%3Cinit%3E(byte[])"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"VorbisComment","l":"VorbisComment(String, String)","url":"%3Cinit%3E(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.VorbisIdHeader","l":"VorbisIdHeader(int, int, int, int, int, int, int, int, boolean, byte[])","url":"%3Cinit%3E(int,int,int,int,int,int,int,int,boolean,byte[])"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxDecoder","l":"VpxDecoder(int, int, int, ExoMediaCrypto, int)","url":"%3Cinit%3E(int,int,int,com.google.android.exoplayer2.drm.ExoMediaCrypto,int)"},{"p":"com.google.android.exoplayer2.ext.vp9","c":"VpxLibrary","l":"vpxIsSecureDecodeSupported()"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"w(String, String, Throwable)","url":"w(java.lang.String,java.lang.String,java.lang.Throwable)"},{"p":"com.google.android.exoplayer2.util","c":"Log","l":"w(String, String)","url":"w(java.lang.String,java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"waitForIsLoading(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForIsLoading","l":"WaitForIsLoading(String, boolean)","url":"%3Cinit%3E(java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"waitForMessage(ActionSchedule.PlayerTarget)","url":"waitForMessage(com.google.android.exoplayer2.testutil.ActionSchedule.PlayerTarget)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForMessage","l":"WaitForMessage(String, ActionSchedule.PlayerTarget)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.testutil.ActionSchedule.PlayerTarget)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"waitForPendingPlayerCommands()"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForPendingPlayerCommands","l":"WaitForPendingPlayerCommands(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"waitForPlaybackState(int)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForPlaybackState","l":"WaitForPlaybackState(String, int)","url":"%3Cinit%3E(java.lang.String,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"waitForPlayWhenReady(boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForPlayWhenReady","l":"WaitForPlayWhenReady(String, boolean)","url":"%3Cinit%3E(java.lang.String,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"waitForPositionDiscontinuity()"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForPositionDiscontinuity","l":"WaitForPositionDiscontinuity(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"waitForTimelineChanged()"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForTimelineChanged","l":"WaitForTimelineChanged(String, Timeline, int)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.Timeline,int)"},{"p":"com.google.android.exoplayer2.testutil","c":"Action.WaitForTimelineChanged","l":"WaitForTimelineChanged(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"ActionSchedule.Builder","l":"waitForTimelineChanged(Timeline, int)","url":"waitForTimelineChanged(com.google.android.exoplayer2.Timeline,int)"},{"p":"com.google.android.exoplayer2.decoder","c":"DecoderInputBuffer","l":"waitingForKeys"},{"p":"com.google.android.exoplayer2","c":"C","l":"WAKE_MODE_LOCAL"},{"p":"com.google.android.exoplayer2","c":"C","l":"WAKE_MODE_NETWORK"},{"p":"com.google.android.exoplayer2","c":"C","l":"WAKE_MODE_NONE"},{"p":"com.google.android.exoplayer2.mediacodec","c":"MediaCodecUtil","l":"warmDecoderInfoCache(String, boolean, boolean)","url":"warmDecoderInfoCache(java.lang.String,boolean,boolean)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"WAV"},{"p":"com.google.android.exoplayer2.audio","c":"WavUtil","l":"WAVE_FOURCC"},{"p":"com.google.android.exoplayer2.extractor.wav","c":"WavExtractor","l":"WavExtractor()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.audio","c":"TeeAudioProcessor.WavFileAudioBufferSink","l":"WavFileAudioBufferSink(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.util","c":"FileTypes","l":"WEBVTT"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCssStyle","l":"WebvttCssStyle()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCueInfo","l":"WebvttCueInfo(Cue, long, long)","url":"%3Cinit%3E(com.google.android.exoplayer2.text.Cue,long,long)"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttCueParser","l":"WebvttCueParser()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.text.webvtt","c":"WebvttDecoder","l":"WebvttDecoder()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.source.hls","c":"WebvttExtractor","l":"WebvttExtractor(String, TimestampAdjuster)","url":"%3Cinit%3E(java.lang.String,com.google.android.exoplayer2.util.TimestampAdjuster)"},{"p":"com.google.android.exoplayer2.source.dash.manifest","c":"BaseUrl","l":"weight"},{"p":"com.google.android.exoplayer2","c":"C","l":"WIDEVINE_UUID"},{"p":"com.google.android.exoplayer2","c":"Format","l":"width"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"width"},{"p":"com.google.android.exoplayer2.util","c":"NalUnitUtil.SpsData","l":"width"},{"p":"com.google.android.exoplayer2.video","c":"AvcConfig","l":"width"},{"p":"com.google.android.exoplayer2.video","c":"MediaCodecVideoRenderer.CodecMaxValues","l":"width"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"width"},{"p":"com.google.android.exoplayer2.video","c":"VideoSize","l":"width"},{"p":"com.google.android.exoplayer2","c":"BasePlayer","l":"window"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"Window()","url":"%3Cinit%3E()"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"windowColor"},{"p":"com.google.android.exoplayer2.ui","c":"CaptionStyleCompat","l":"windowColor"},{"p":"com.google.android.exoplayer2.text","c":"Cue","l":"windowColorSet"},{"p":"com.google.android.exoplayer2","c":"IllegalSeekPositionException","l":"windowIndex"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"windowIndex"},{"p":"com.google.android.exoplayer2","c":"Timeline.Period","l":"windowIndex"},{"p":"com.google.android.exoplayer2.analytics","c":"AnalyticsListener.EventTime","l":"windowIndex"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener.EventDispatcher","l":"windowIndex"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"windowIndex"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeTimeline.TimelineWindowDefinition","l":"windowOffsetInFirstPeriodUs"},{"p":"com.google.android.exoplayer2.source","c":"MediaPeriodId","l":"windowSequenceNumber"},{"p":"com.google.android.exoplayer2","c":"Timeline.Window","l":"windowStartTimeMs"},{"p":"com.google.android.exoplayer2.extractor","c":"VorbisUtil.Mode","l":"windowType"},{"p":"com.google.android.exoplayer2","c":"Player.PositionInfo","l":"windowUid"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject.AbsoluteSized","l":"withAbsoluteSize(int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"withAdCount(int, int)","url":"withAdCount(int,int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"withAdCount(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"withAdditionalHeaders(Map)","url":"withAdditionalHeaders(java.util.Map)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"withAdDurationsUs(int, long...)","url":"withAdDurationsUs(int,long...)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"withAdDurationsUs(long[])"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"withAdDurationsUs(long[][])"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"withAdGroupTimeUs(int, long)","url":"withAdGroupTimeUs(int,long)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"withAdLoadError(int, int)","url":"withAdLoadError(int,int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"withAdResumePositionUs(long)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"withAdState(int, int)","url":"withAdState(int,int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"withAdUri(int, int, Uri)","url":"withAdUri(int,int,android.net.Uri)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"withAdUri(Uri, int)","url":"withAdUri(android.net.Uri,int)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject.Aligned","l":"withAlignment(Layout.Alignment)","url":"withAlignment(android.text.Layout.Alignment)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"withAllAdsSkipped()"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject.Colored","l":"withColor(int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"withContentDurationUs(long)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"withContentResumeOffsetUs(int, long)","url":"withContentResumeOffsetUs(int,long)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"withContentResumeOffsetUs(long)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject.Typefaced","l":"withFamily(String)","url":"withFamily(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject.WithSpanFlags","l":"withFlags(int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"withIsServerSideInserted(boolean)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"withIsServerSideInserted(int, boolean)","url":"withIsServerSideInserted(int,boolean)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"withManifestFormatInfo(Format)","url":"withManifestFormatInfo(com.google.android.exoplayer2.Format)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject.EmphasizedText","l":"withMarkAndPosition(int, int, int)","url":"withMarkAndPosition(int,int,int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"withNewAdGroup(int, long)","url":"withNewAdGroup(int,long)"},{"p":"com.google.android.exoplayer2.source","c":"MediaSourceEventListener.EventDispatcher","l":"withParameters(int, MediaSource.MediaPeriodId, long)","url":"withParameters(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId,long)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmSessionEventListener.EventDispatcher","l":"withParameters(int, MediaSource.MediaPeriodId)","url":"withParameters(int,com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"withPlayedAd(int, int)","url":"withPlayedAd(int,int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"withRemovedAdGroupCount(int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"withRequestHeaders(Map)","url":"withRequestHeaders(java.util.Map)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject.RelativeSized","l":"withSizeChange(float)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"withSkippedAd(int, int)","url":"withSkippedAd(int,int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState","l":"withSkippedAdGroup(int)"},{"p":"com.google.android.exoplayer2","c":"PlaybackParameters","l":"withSpeed(float)"},{"p":"com.google.android.exoplayer2.testutil.truth","c":"SpannedSubject.RubyText","l":"withTextAndPosition(String, int)","url":"withTextAndPosition(java.lang.String,int)"},{"p":"com.google.android.exoplayer2.source.ads","c":"AdPlaybackState.AdGroup","l":"withTimeUs(long)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSpec","l":"withUri(Uri)","url":"withUri(android.net.Uri)"},{"p":"com.google.android.exoplayer2.drm","c":"FrameworkMediaCrypto","l":"WORKAROUND_DEVICE_NEEDS_KEYS_TO_CONFIGURE_CODEC"},{"p":"com.google.android.exoplayer2.ext.workmanager","c":"WorkManagerScheduler","l":"WorkManagerScheduler(Context, String)","url":"%3Cinit%3E(android.content.Context,java.lang.String)"},{"p":"com.google.android.exoplayer2.ext.workmanager","c":"WorkManagerScheduler","l":"WorkManagerScheduler(String)","url":"%3Cinit%3E(java.lang.String)"},{"p":"com.google.android.exoplayer2.testutil","c":"FailOnCloseDataSink","l":"write(byte[], int, int)","url":"write(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"ByteArrayDataSink","l":"write(byte[], int, int)","url":"write(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream","c":"DataSink","l":"write(byte[], int, int)","url":"write(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream.cache","c":"CacheDataSink","l":"write(byte[], int, int)","url":"write(byte[],int,int)"},{"p":"com.google.android.exoplayer2.upstream.crypto","c":"AesCipherDataSink","l":"write(byte[], int, int)","url":"write(byte[],int,int)"},{"p":"com.google.android.exoplayer2.util","c":"Util","l":"writeBoolean(Parcel, boolean)","url":"writeBoolean(android.os.Parcel,boolean)"},{"p":"com.google.android.exoplayer2.testutil","c":"FakeSampleStream","l":"writeData(long)"},{"p":"com.google.android.exoplayer2.audio","c":"AudioSink.WriteException","l":"WriteException(int, Format, boolean)","url":"%3Cinit%3E(int,com.google.android.exoplayer2.Format,boolean)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"writer"},{"p":"com.google.android.exoplayer2.source.rtsp","c":"RtpPacket","l":"writeToBuffer(byte[], int, int)","url":"writeToBuffer(byte[],int,int)"},{"p":"com.google.android.exoplayer2","c":"Format","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.drm","c":"DrmInitData.SchemeData","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata","c":"Metadata","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","c":"AppInfoTable","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.emsg","c":"EventMessage","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"PictureFrame","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.flac","c":"VorbisComment","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyHeaders","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.icy","c":"IcyInfo","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ApicFrame","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"BinaryFrame","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterFrame","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"ChapterTocFrame","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"CommentFrame","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"GeobFrame","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"InternalFrame","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"MlltFrame","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"PrivFrame","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"TextInformationFrame","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.id3","c":"UrlLinkFrame","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MdtaMetadataEntry","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"MotionPhotoMetadata","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SlowMotionData.Segment","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.mp4","c":"SmtaMetadataEntry","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"PrivateCommand","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceNullCommand","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceScheduleCommand","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"TimeSignalCommand","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.offline","c":"DownloadRequest","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.offline","c":"StreamKey","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.scheduler","c":"Requirements","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroup","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.source","c":"TrackGroupArray","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.source.hls","c":"HlsTrackMetadataEntry.VariantInfo","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.Parameters","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"DefaultTrackSelector.SelectionOverride","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.trackselection","c":"TrackSelectionParameters","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.video","c":"ColorInfo","l":"writeToParcel(Parcel, int)","url":"writeToParcel(android.os.Parcel,int)"},{"p":"com.google.android.exoplayer2.metadata.scte35","c":"SpliceInsertCommand.ComponentSplice","l":"writeToParcel(Parcel)","url":"writeToParcel(android.os.Parcel)"},{"p":"com.google.android.exoplayer2","c":"MediaMetadata","l":"year"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"yuvPlanes"},{"p":"com.google.android.exoplayer2.video","c":"VideoDecoderOutputBuffer","l":"yuvStrides"}] \ No newline at end of file diff --git a/docs/doc/reference/member-search-index.zip b/docs/doc/reference/member-search-index.zip index 4bcb39d4f4b..c5b1a94e4d6 100644 Binary files a/docs/doc/reference/member-search-index.zip and b/docs/doc/reference/member-search-index.zip differ diff --git a/docs/doc/reference/overview-tree.html b/docs/doc/reference/overview-tree.html index 2040e675f56..5104fc92a2c 100644 --- a/docs/doc/reference/overview-tree.html +++ b/docs/doc/reference/overview-tree.html @@ -313,6 +313,7 @@

    Class Hierarchy

  • com.google.android.exoplayer2.source.hls.HlsMediaSource (implements com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker.PrimaryPlaylistListener)
  • com.google.android.exoplayer2.source.ProgressiveMediaSource
  • com.google.android.exoplayer2.source.rtsp.RtspMediaSource
  • +
  • com.google.android.exoplayer2.source.ads.ServerSideInsertedAdsMediaSource (implements com.google.android.exoplayer2.drm.DrmSessionEventListener, com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller, com.google.android.exoplayer2.source.MediaSourceEventListener)
  • com.google.android.exoplayer2.source.SilenceMediaSource
  • com.google.android.exoplayer2.source.SingleSampleMediaSource
  • com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource (implements com.google.android.exoplayer2.upstream.Loader.Callback<T>)
  • @@ -365,6 +366,8 @@

    Class Hierarchy

  • com.google.android.exoplayer2.trackselection.RandomTrackSelection
  • +
  • com.google.android.exoplayer2.source.dash.manifest.BaseUrl
  • +
  • com.google.android.exoplayer2.source.dash.BaseUrlExclusionList
  • com.google.android.exoplayer2.extractor.BinarySearchSeeker
  • com.google.android.exoplayer2.extractor.BinarySearchSeeker.BinarySearchSeekMap (implements com.google.android.exoplayer2.extractor.SeekMap)
  • com.google.android.exoplayer2.extractor.BinarySearchSeeker.DefaultSeekTimestampConverter (implements com.google.android.exoplayer2.extractor.BinarySearchSeeker.SeekTimestampConverter)
  • @@ -388,15 +391,12 @@

    Class Hierarchy

    +
  • com.google.android.exoplayer2.util.BundleableUtils
  • com.google.android.exoplayer2.source.chunk.BundledChunkExtractor (implements com.google.android.exoplayer2.source.chunk.ChunkExtractor, com.google.android.exoplayer2.extractor.ExtractorOutput)
  • com.google.android.exoplayer2.source.BundledExtractorsAdapter (implements com.google.android.exoplayer2.source.ProgressiveMediaExtractor)
  • com.google.android.exoplayer2.source.hls.BundledHlsMediaChunkExtractor (implements com.google.android.exoplayer2.source.hls.HlsMediaChunkExtractor)
  • @@ -478,8 +478,9 @@

    Class Hierarchy

  • com.google.android.exoplayer2.util.CopyOnWriteMultiset<E> (implements java.lang.Iterable<T>)
  • com.google.android.exoplayer2.ext.cronet.CronetDataSource.Factory (implements com.google.android.exoplayer2.upstream.HttpDataSource.Factory)
  • com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper
  • +
  • com.google.android.exoplayer2.ext.cronet.CronetUtil
  • com.google.android.exoplayer2.decoder.CryptoInfo
  • -
  • com.google.android.exoplayer2.text.Cue
  • +
  • com.google.android.exoplayer2.text.Cue (implements com.google.android.exoplayer2.Bundleable)
  • com.google.android.exoplayer2.text.Cue.Builder
  • com.google.android.exoplayer2.source.dash.manifest.DashManifest (implements com.google.android.exoplayer2.offline.FilterableManifest<T>)
  • com.google.android.exoplayer2.source.dash.manifest.DashManifestParser.RepresentationInfo
  • @@ -533,6 +534,7 @@

    Class Hierarchy

  • com.google.android.exoplayer2.DefaultLoadControl (implements com.google.android.exoplayer2.LoadControl)
  • com.google.android.exoplayer2.DefaultLoadControl.Builder
  • com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy (implements com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy)
  • +
  • com.google.android.exoplayer2.ui.DefaultMediaDescriptionAdapter (implements com.google.android.exoplayer2.ui.PlayerNotificationManager.MediaDescriptionAdapter)
  • com.google.android.exoplayer2.ext.cast.DefaultMediaItemConverter (implements com.google.android.exoplayer2.ext.cast.MediaItemConverter)
  • com.google.android.exoplayer2.ext.media2.DefaultMediaItemConverter (implements com.google.android.exoplayer2.ext.media2.MediaItemConverter)
  • com.google.android.exoplayer2.source.DefaultMediaSourceFactory (implements com.google.android.exoplayer2.source.MediaSourceFactory)
  • @@ -568,6 +570,7 @@

    Class Hierarchy

  • com.google.android.exoplayer2.drm.DrmInitData (implements java.util.Comparator<T>, android.os.Parcelable)
  • com.google.android.exoplayer2.drm.DrmInitData.SchemeData (implements android.os.Parcelable)
  • com.google.android.exoplayer2.drm.DrmSessionEventListener.EventDispatcher
  • +
  • com.google.android.exoplayer2.drm.DrmUtil
  • com.google.android.exoplayer2.extractor.ts.DtsReader (implements com.google.android.exoplayer2.extractor.ts.ElementaryStreamReader)
  • com.google.android.exoplayer2.audio.DtsUtil
  • com.google.android.exoplayer2.upstream.DummyDataSource (implements com.google.android.exoplayer2.upstream.DataSource)
  • @@ -586,8 +589,6 @@

    Class Hierarchy

  • com.google.android.exoplayer2.metadata.emsg.EventMessage (implements com.google.android.exoplayer2.metadata.Metadata.Entry)
  • com.google.android.exoplayer2.metadata.emsg.EventMessageEncoder
  • com.google.android.exoplayer2.source.dash.manifest.EventStream
  • -
  • com.google.android.exoplayer2.util.ExoFlags
  • -
  • com.google.android.exoplayer2.util.ExoFlags.Builder
  • com.google.android.exoplayer2.testutil.ExoHostedTest (implements com.google.android.exoplayer2.analytics.AnalyticsListener, com.google.android.exoplayer2.testutil.HostActivity.HostedTest)
  • com.google.android.exoplayer2.drm.ExoMediaDrm.AppManagedProvider (implements com.google.android.exoplayer2.drm.ExoMediaDrm.Provider)
  • com.google.android.exoplayer2.drm.ExoMediaDrm.KeyRequest
  • @@ -655,6 +656,8 @@

    Class Hierarchy

  • com.google.android.exoplayer2.extractor.FlacSeekTableSeekMap (implements com.google.android.exoplayer2.extractor.SeekMap)
  • com.google.android.exoplayer2.extractor.FlacStreamMetadata
  • com.google.android.exoplayer2.extractor.FlacStreamMetadata.SeekTable
  • +
  • com.google.android.exoplayer2.util.FlagSet
  • +
  • com.google.android.exoplayer2.util.FlagSet.Builder
  • com.google.android.exoplayer2.extractor.flv.FlvExtractor (implements com.google.android.exoplayer2.extractor.Extractor)
  • com.google.android.exoplayer2.Format (implements android.os.Parcelable)
  • com.google.android.exoplayer2.Format.Builder
  • @@ -665,6 +668,7 @@

    Class Hierarchy

  • com.google.android.exoplayer2.extractor.ForwardingExtractorInput (implements com.google.android.exoplayer2.extractor.ExtractorInput)
  • +
  • com.google.android.exoplayer2.ForwardingPlayer (implements com.google.android.exoplayer2.Player)
  • com.google.android.exoplayer2.extractor.mp4.FragmentedMp4Extractor (implements com.google.android.exoplayer2.extractor.Extractor)
  • com.google.android.exoplayer2.drm.FrameworkMediaCrypto (implements com.google.android.exoplayer2.drm.ExoMediaCrypto)
  • com.google.android.exoplayer2.drm.FrameworkMediaDrm (implements com.google.android.exoplayer2.drm.ExoMediaDrm)
  • @@ -758,6 +762,8 @@

    Class Hierarchy

  • com.google.android.exoplayer2.upstream.Loader (implements com.google.android.exoplayer2.upstream.LoaderErrorThrower)
  • com.google.android.exoplayer2.upstream.Loader.LoadErrorAction
  • com.google.android.exoplayer2.upstream.LoaderErrorThrower.Dummy (implements com.google.android.exoplayer2.upstream.LoaderErrorThrower)
  • +
  • com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.FallbackOptions
  • +
  • com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.FallbackSelection
  • com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.LoadErrorInfo
  • com.google.android.exoplayer2.source.LoadEventInfo
  • com.google.android.exoplayer2.drm.LocalMediaDrmCallback (implements com.google.android.exoplayer2.drm.MediaDrmCallback)
  • @@ -810,6 +816,7 @@

    Class Hierarchy

  • com.google.android.exoplayer2.util.NalUnitUtil.PpsData
  • com.google.android.exoplayer2.util.NalUnitUtil.SpsData
  • com.google.android.exoplayer2.util.NetworkTypeObserver
  • +
  • com.google.android.exoplayer2.util.NetworkTypeObserver.Config
  • com.google.android.exoplayer2.upstream.cache.NoOpCacheEvictor (implements com.google.android.exoplayer2.upstream.cache.CacheEvictor)
  • com.google.android.exoplayer2.NoSampleRenderer (implements com.google.android.exoplayer2.Renderer, com.google.android.exoplayer2.RendererCapabilities)
  • com.google.android.exoplayer2.util.NotificationUtil
  • @@ -848,7 +855,7 @@

    Class Hierarchy

  • com.google.android.exoplayer2.analytics.PlaybackStats.EventTimeAndFormat
  • com.google.android.exoplayer2.analytics.PlaybackStats.EventTimeAndPlaybackState
  • com.google.android.exoplayer2.analytics.PlaybackStatsListener (implements com.google.android.exoplayer2.analytics.AnalyticsListener, com.google.android.exoplayer2.analytics.PlaybackSessionManager.Listener)
  • -
  • com.google.android.exoplayer2.Player.Commands
  • +
  • com.google.android.exoplayer2.Player.Commands (implements com.google.android.exoplayer2.Bundleable)
  • com.google.android.exoplayer2.Player.Commands.Builder
  • com.google.android.exoplayer2.Player.Events
  • com.google.android.exoplayer2.Player.PositionInfo (implements com.google.android.exoplayer2.Bundleable)
  • @@ -899,6 +906,7 @@

    Class Hierarchy

  • com.google.android.exoplayer2.upstream.ResolvingDataSource (implements com.google.android.exoplayer2.upstream.DataSource)
  • com.google.android.exoplayer2.upstream.ResolvingDataSource.Factory (implements com.google.android.exoplayer2.upstream.DataSource.Factory)
  • com.google.android.exoplayer2.robolectric.RobolectricUtil
  • +
  • com.google.android.exoplayer2.ext.rtmp.RtmpDataSource.Factory (implements com.google.android.exoplayer2.upstream.DataSource.Factory)
  • com.google.android.exoplayer2.ext.rtmp.RtmpDataSourceFactory (implements com.google.android.exoplayer2.upstream.DataSource.Factory)
  • com.google.android.exoplayer2.source.rtsp.reader.RtpAc3Reader (implements com.google.android.exoplayer2.source.rtsp.reader.RtpPayloadReader)
  • com.google.android.exoplayer2.source.rtsp.RtpPacket
  • @@ -935,6 +943,7 @@

    Class Hierarchy

  • com.google.android.exoplayer2.offline.SegmentDownloader.Segment (implements java.lang.Comparable<T>)
  • com.google.android.exoplayer2.extractor.ts.SeiReader
  • +
  • com.google.android.exoplayer2.source.ads.ServerSideInsertedAdsUtil
  • com.google.android.exoplayer2.source.dash.manifest.ServiceDescriptionElement
  • com.google.android.exoplayer2.ext.media2.SessionCallbackBuilder
  • com.google.android.exoplayer2.ext.media2.SessionCallbackBuilder.DefaultAllowedCommandProvider (implements com.google.android.exoplayer2.ext.media2.SessionCallbackBuilder.AllowedCommandProvider)
  • @@ -1059,12 +1068,9 @@

    Class Hierarchy

  • com.google.android.exoplayer2.drm.DecryptionException
  • com.google.android.exoplayer2.drm.DefaultDrmSessionManager.MissingSchemeDataException
  • -
  • com.google.android.exoplayer2.ExoPlaybackException (implements com.google.android.exoplayer2.Bundleable)
  • -
  • com.google.android.exoplayer2.ExoTimeoutException
  • java.io.IOException
  • com.google.android.exoplayer2.util.PriorityTaskManager.PriorityTooLowException
  • -
  • com.google.android.exoplayer2.upstream.RawResourceDataSource.RawResourceDataSourceException
  • com.google.android.exoplayer2.source.rtsp.RtspMediaSource.RtspPlaybackException
  • com.google.android.exoplayer2.source.hls.SampleQueueMappingException
  • -
  • com.google.android.exoplayer2.upstream.UdpDataSource.UdpDataSourceException
  • com.google.android.exoplayer2.drm.KeysExpiredException
  • com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.DecoderInitializationException
  • com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException
  • +
  • com.google.android.exoplayer2.PlaybackException (implements com.google.android.exoplayer2.Bundleable) + +
  • java.lang.RuntimeException
  • com.google.android.exoplayer2.upstream.ParsingLoadable.Parser<T>
  • -
  • com.google.android.exoplayer2.PlaybackPreparer
  • com.google.android.exoplayer2.analytics.PlaybackSessionManager
  • com.google.android.exoplayer2.analytics.PlaybackSessionManager.Listener
  • com.google.android.exoplayer2.analytics.PlaybackStatsListener.Callback
  • @@ -1594,6 +1610,7 @@

    Annotation Type Hierarchy

  • com.google.android.exoplayer2.C.ColorTransfer (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.C.ContentType (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.C.CryptoMode (implements java.lang.annotation.Annotation)
  • +
  • com.google.android.exoplayer2.C.DataType (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.C.Encoding (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.C.FormatSupport (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.C.NetworkType (implements java.lang.annotation.Annotation)
  • @@ -1610,7 +1627,6 @@

    Annotation Type Hierarchy

  • com.google.android.exoplayer2.upstream.cache.CacheDataSource.Flags (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.ui.CaptionStyleCompat.EdgeType (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.source.ClippingMediaSource.IllegalClippingException.Reason (implements java.lang.annotation.Annotation)
  • -
  • com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper.CronetEngineSource (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.text.Cue.AnchorType (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.text.Cue.LineType (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.text.Cue.TextSizeType (implements java.lang.annotation.Annotation)
  • @@ -1628,6 +1644,7 @@

    Annotation Type Hierarchy

  • com.google.android.exoplayer2.offline.Download.FailureReason (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.offline.Download.State (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.drm.DrmSession.State (implements java.lang.annotation.Annotation)
  • +
  • com.google.android.exoplayer2.drm.DrmUtil.ErrorSource (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.extractor.mkv.EbmlProcessor.ElementType (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.util.EGLSurfaceTexture.SecureMode (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.drm.ExoMediaDrm.KeyRequest.RequestType (implements java.lang.annotation.Annotation)
  • @@ -1641,17 +1658,21 @@

    Annotation Type Hierarchy

  • com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.PlaylistType (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.source.hls.HlsMediaSource.MetadataType (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.upstream.HttpDataSource.HttpDataSourceException.Type (implements java.lang.annotation.Annotation)
  • +
  • com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.FallbackType (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor.Flags (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.MediaMetadata.FolderType (implements java.lang.annotation.Annotation)
  • +
  • com.google.android.exoplayer2.MediaMetadata.PictureType (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.PlaybackActions (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.source.MergingMediaSource.IllegalMergeException.Reason (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.extractor.mp3.Mp3Extractor.Flags (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.extractor.mp4.Mp4Extractor.Flags (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.util.NonNullApi (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.util.NotificationUtil.Importance (implements java.lang.annotation.Annotation)
  • +
  • com.google.android.exoplayer2.PlaybackException.ErrorCode (implements java.lang.annotation.Annotation)
  • +
  • com.google.android.exoplayer2.PlaybackException.FieldNumber (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.Player.Command (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.Player.DiscontinuityReason (implements java.lang.annotation.Annotation)
  • -
  • com.google.android.exoplayer2.Player.EventFlags (implements java.lang.annotation.Annotation)
  • +
  • com.google.android.exoplayer2.Player.Event (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.Player.MediaItemTransitionReason (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.Player.PlaybackSuppressionReason (implements java.lang.annotation.Annotation)
  • com.google.android.exoplayer2.Player.PlayWhenReadyChangeReason (implements java.lang.annotation.Annotation)
  • diff --git a/docs/doc/reference/package-search-index.zip b/docs/doc/reference/package-search-index.zip index e07c33ac262..aa8bb32d54f 100644 Binary files a/docs/doc/reference/package-search-index.zip and b/docs/doc/reference/package-search-index.zip differ diff --git a/docs/doc/reference/serialized-form.html b/docs/doc/reference/serialized-form.html index 061f3127159..7ddcf4a9566 100644 --- a/docs/doc/reference/serialized-form.html +++ b/docs/doc/reference/serialized-form.html @@ -102,16 +102,12 @@

    Package com.google.android.exoplayer2

  • -

    Class com.google.android.exoplayer2.ExoPlaybackException extends Exception implements Serializable

    +

    Class com.google.android.exoplayer2.ExoPlaybackException extends PlaybackException implements Serializable

    • Serialized Fields

    • @@ -913,7 +955,7 @@

      reason

    • -

      Class com.google.android.exoplayer2.upstream.FileDataSource.FileDataSourceException extends IOException implements Serializable

      +

      Class com.google.android.exoplayer2.upstream.FileDataSource.FileDataSourceException extends DataSourceException implements Serializable

    • @@ -923,7 +965,7 @@

      Class -

      Class com.google.android.exoplayer2.upstream.HttpDataSource.HttpDataSourceException extends IOException implements Serializable

      +

      Class com.google.android.exoplayer2.upstream.HttpDataSource.HttpDataSourceException extends DataSourceException implements Serializable

      diff --git a/docs/doc/reference/type-search-index.js b/docs/doc/reference/type-search-index.js index cf4c7f3072f..427279dba23 100644 --- a/docs/doc/reference/type-search-index.js +++ b/docs/doc/reference/type-search-index.js @@ -1 +1 @@ -typeSearchIndex = [{"p":"com.google.android.exoplayer2.audio","l":"AacUtil.AacAudioObjectType"},{"p":"com.google.android.exoplayer2.audio","l":"AacUtil"},{"p":"com.google.android.exoplayer2.testutil.truth","l":"SpannedSubject.AbsoluteSized"},{"p":"com.google.android.exoplayer2","l":"AbstractConcatenatedTimeline"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"Ac3Extractor"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"Ac3Reader"},{"p":"com.google.android.exoplayer2.audio","l":"Ac3Util"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"Ac4Extractor"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"Ac4Reader"},{"p":"com.google.android.exoplayer2.audio","l":"Ac4Util"},{"p":"com.google.android.exoplayer2.testutil","l":"Action"},{"p":"com.google.android.exoplayer2.offline","l":"ActionFileUpgradeUtil"},{"p":"com.google.android.exoplayer2.testutil","l":"ActionSchedule"},{"p":"com.google.android.exoplayer2.trackselection","l":"AdaptiveTrackSelection.AdaptationCheckpoint"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"AdaptationSet"},{"p":"com.google.android.exoplayer2","l":"RendererCapabilities.AdaptiveSupport"},{"p":"com.google.android.exoplayer2.trackselection","l":"AdaptiveTrackSelection"},{"p":"com.google.android.exoplayer2.trackselection","l":"TrackSelectionUtil.AdaptiveTrackSelectionFactory"},{"p":"com.google.android.exoplayer2.testutil","l":"AdditionalFailureInfo"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.AddMediaItems"},{"p":"com.google.android.exoplayer2.source.ads","l":"AdPlaybackState.AdGroup"},{"p":"com.google.android.exoplayer2.source.ads","l":"AdsMediaSource.AdLoadException"},{"p":"com.google.android.exoplayer2.ui","l":"AdOverlayInfo"},{"p":"com.google.android.exoplayer2.source.ads","l":"AdPlaybackState"},{"p":"com.google.android.exoplayer2","l":"MediaItem.AdsConfiguration"},{"p":"com.google.android.exoplayer2.source.ads","l":"AdsLoader"},{"p":"com.google.android.exoplayer2.source","l":"DefaultMediaSourceFactory.AdsLoaderProvider"},{"p":"com.google.android.exoplayer2.source.ads","l":"AdsMediaSource"},{"p":"com.google.android.exoplayer2.source.ads","l":"AdPlaybackState.AdState"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"AdtsExtractor"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"AdtsReader"},{"p":"com.google.android.exoplayer2.ui","l":"AdViewProvider"},{"p":"com.google.android.exoplayer2.upstream.crypto","l":"AesCipherDataSink"},{"p":"com.google.android.exoplayer2.upstream.crypto","l":"AesCipherDataSource"},{"p":"com.google.android.exoplayer2.upstream.crypto","l":"AesFlushingCipher"},{"p":"com.google.android.exoplayer2.testutil.truth","l":"SpannedSubject.Aligned"},{"l":"All Classes","url":"allclasses-index.html"},{"p":"com.google.android.exoplayer2.upstream","l":"Allocation"},{"p":"com.google.android.exoplayer2.upstream","l":"Allocator"},{"p":"com.google.android.exoplayer2.ext.media2","l":"SessionCallbackBuilder.AllowedCommandProvider"},{"p":"com.google.android.exoplayer2.extractor.amr","l":"AmrExtractor"},{"p":"com.google.android.exoplayer2.analytics","l":"AnalyticsCollector"},{"p":"com.google.android.exoplayer2.analytics","l":"AnalyticsListener"},{"p":"com.google.android.exoplayer2.text","l":"Cue.AnchorType"},{"p":"com.google.android.exoplayer2.testutil.truth","l":"SpannedSubject.AndSpanFlags"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"ApicFrame"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","l":"AppInfoTable"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","l":"AppInfoTableDecoder"},{"p":"com.google.android.exoplayer2.drm","l":"ExoMediaDrm.AppManagedProvider"},{"p":"com.google.android.exoplayer2.ui","l":"AspectRatioFrameLayout"},{"p":"com.google.android.exoplayer2.ui","l":"AspectRatioFrameLayout.AspectRatioListener"},{"p":"com.google.android.exoplayer2.testutil","l":"ExtractorAsserts.AssertionConfig"},{"p":"com.google.android.exoplayer2.util","l":"Assertions"},{"p":"com.google.android.exoplayer2.upstream","l":"AssetDataSource"},{"p":"com.google.android.exoplayer2.upstream","l":"AssetDataSource.AssetDataSourceException"},{"p":"com.google.android.exoplayer2.util","l":"AtomicFile"},{"p":"com.google.android.exoplayer2.util","l":"GlUtil.Attribute"},{"p":"com.google.android.exoplayer2","l":"C.AudioAllowedCapturePolicy"},{"p":"com.google.android.exoplayer2.audio","l":"AudioAttributes"},{"p":"com.google.android.exoplayer2.audio","l":"TeeAudioProcessor.AudioBufferSink"},{"p":"com.google.android.exoplayer2.audio","l":"AudioCapabilities"},{"p":"com.google.android.exoplayer2.audio","l":"AudioCapabilitiesReceiver"},{"p":"com.google.android.exoplayer2","l":"ExoPlayer.AudioComponent"},{"p":"com.google.android.exoplayer2","l":"C.AudioContentType"},{"p":"com.google.android.exoplayer2","l":"C.AudioFlags"},{"p":"com.google.android.exoplayer2","l":"C.AudioFocusGain"},{"p":"com.google.android.exoplayer2.audio","l":"AudioProcessor.AudioFormat"},{"p":"com.google.android.exoplayer2.audio","l":"AudioListener"},{"p":"com.google.android.exoplayer2","l":"ExoPlayer.AudioOffloadListener"},{"p":"com.google.android.exoplayer2.audio","l":"AudioProcessor"},{"p":"com.google.android.exoplayer2.audio","l":"DefaultAudioSink.AudioProcessorChain"},{"p":"com.google.android.exoplayer2.audio","l":"AudioRendererEventListener"},{"p":"com.google.android.exoplayer2.audio","l":"AudioSink"},{"p":"com.google.android.exoplayer2.trackselection","l":"DefaultTrackSelector.AudioTrackScore"},{"p":"com.google.android.exoplayer2","l":"C.AudioUsage"},{"p":"com.google.android.exoplayer2.audio","l":"AuxEffectInfo"},{"p":"com.google.android.exoplayer2.video","l":"AvcConfig"},{"p":"com.google.android.exoplayer2.upstream","l":"BandwidthMeter"},{"p":"com.google.android.exoplayer2.audio","l":"BaseAudioProcessor"},{"p":"com.google.android.exoplayer2.upstream","l":"BaseDataSource"},{"p":"com.google.android.exoplayer2.upstream","l":"HttpDataSource.BaseFactory"},{"p":"com.google.android.exoplayer2.source.chunk","l":"BaseMediaChunk"},{"p":"com.google.android.exoplayer2.source.chunk","l":"BaseMediaChunkIterator"},{"p":"com.google.android.exoplayer2.source.chunk","l":"BaseMediaChunkOutput"},{"p":"com.google.android.exoplayer2.source","l":"BaseMediaSource"},{"p":"com.google.android.exoplayer2","l":"BasePlayer"},{"p":"com.google.android.exoplayer2","l":"BaseRenderer"},{"p":"com.google.android.exoplayer2.trackselection","l":"BaseTrackSelection"},{"p":"com.google.android.exoplayer2.source","l":"BehindLiveWindowException"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"BinaryFrame"},{"p":"com.google.android.exoplayer2.extractor","l":"BinarySearchSeeker"},{"p":"com.google.android.exoplayer2.extractor","l":"BinarySearchSeeker.BinarySearchSeekMap"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerNotificationManager.BitmapCallback"},{"p":"com.google.android.exoplayer2.decoder","l":"Buffer"},{"p":"com.google.android.exoplayer2","l":"C.BufferFlags"},{"p":"com.google.android.exoplayer2.decoder","l":"DecoderInputBuffer.BufferReplacementMode"},{"p":"com.google.android.exoplayer2","l":"DefaultLivePlaybackSpeedControl.Builder"},{"p":"com.google.android.exoplayer2","l":"DefaultLoadControl.Builder"},{"p":"com.google.android.exoplayer2","l":"ExoPlayer.Builder"},{"p":"com.google.android.exoplayer2","l":"Format.Builder"},{"p":"com.google.android.exoplayer2","l":"MediaItem.Builder"},{"p":"com.google.android.exoplayer2","l":"MediaMetadata.Builder"},{"p":"com.google.android.exoplayer2","l":"Player.Commands.Builder"},{"p":"com.google.android.exoplayer2","l":"SimpleExoPlayer.Builder"},{"p":"com.google.android.exoplayer2.audio","l":"AudioAttributes.Builder"},{"p":"com.google.android.exoplayer2.drm","l":"DefaultDrmSessionManager.Builder"},{"p":"com.google.android.exoplayer2.ext.ima","l":"ImaAdsLoader.Builder"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadRequest.Builder"},{"p":"com.google.android.exoplayer2.source.rtsp","l":"RtpPacket.Builder"},{"p":"com.google.android.exoplayer2.testutil","l":"ActionSchedule.Builder"},{"p":"com.google.android.exoplayer2.testutil","l":"DataSourceContractTest.TestResource.Builder"},{"p":"com.google.android.exoplayer2.testutil","l":"ExoPlayerTestRunner.Builder"},{"p":"com.google.android.exoplayer2.testutil","l":"ExtractorAsserts.AssertionConfig.Builder"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeExoMediaDrm.Builder"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeExtractorInput.Builder"},{"p":"com.google.android.exoplayer2.testutil","l":"WebServerDispatcher.Resource.Builder"},{"p":"com.google.android.exoplayer2.text","l":"Cue.Builder"},{"p":"com.google.android.exoplayer2.trackselection","l":"TrackSelectionParameters.Builder"},{"p":"com.google.android.exoplayer2.transformer","l":"Transformer.Builder"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerNotificationManager.Builder"},{"p":"com.google.android.exoplayer2.upstream","l":"DataSpec.Builder"},{"p":"com.google.android.exoplayer2.upstream","l":"DefaultBandwidthMeter.Builder"},{"p":"com.google.android.exoplayer2.util","l":"ExoFlags.Builder"},{"p":"com.google.android.exoplayer2","l":"Bundleable"},{"p":"com.google.android.exoplayer2.source.chunk","l":"BundledChunkExtractor"},{"p":"com.google.android.exoplayer2.source","l":"BundledExtractorsAdapter"},{"p":"com.google.android.exoplayer2.source.hls","l":"BundledHlsMediaChunkExtractor"},{"p":"com.google.android.exoplayer2","l":"BundleListRetriever"},{"p":"com.google.android.exoplayer2.util","l":"BundleUtil"},{"p":"com.google.android.exoplayer2.upstream","l":"ByteArrayDataSink"},{"p":"com.google.android.exoplayer2.upstream","l":"ByteArrayDataSource"},{"p":"com.google.android.exoplayer2","l":"C"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"Cache"},{"p":"com.google.android.exoplayer2.testutil","l":"CacheAsserts"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheDataSink"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheDataSink.CacheDataSinkException"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheDataSinkFactory"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheDataSource"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheDataSourceFactory"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CachedRegionTracker"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheEvictor"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"Cache.CacheException"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheDataSource.CacheIgnoredReason"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheKeyFactory"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheSpan"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheWriter"},{"p":"com.google.android.exoplayer2.analytics","l":"PlaybackStatsListener.Callback"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadHelper.Callback"},{"p":"com.google.android.exoplayer2.source","l":"MediaPeriod.Callback"},{"p":"com.google.android.exoplayer2.source","l":"SequenceableLoader.Callback"},{"p":"com.google.android.exoplayer2.testutil","l":"ActionSchedule.Callback"},{"p":"com.google.android.exoplayer2.testutil","l":"ActionSchedule.PlayerTarget.Callback"},{"p":"com.google.android.exoplayer2.upstream","l":"Loader.Callback"},{"p":"com.google.android.exoplayer2.video.spherical","l":"CameraMotionListener"},{"p":"com.google.android.exoplayer2.video.spherical","l":"CameraMotionRenderer"},{"p":"com.google.android.exoplayer2","l":"RendererCapabilities.Capabilities"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"MediaSessionConnector.CaptionCallback"},{"p":"com.google.android.exoplayer2.ui","l":"CaptionStyleCompat"},{"p":"com.google.android.exoplayer2.testutil","l":"CapturingAudioSink"},{"p":"com.google.android.exoplayer2.testutil","l":"CapturingRenderersFactory"},{"p":"com.google.android.exoplayer2.ext.cast","l":"CastPlayer"},{"p":"com.google.android.exoplayer2.text.cea","l":"Cea608Decoder"},{"p":"com.google.android.exoplayer2.text.cea","l":"Cea708Decoder"},{"p":"com.google.android.exoplayer2.extractor","l":"CeaUtil"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"ChapterFrame"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"ChapterTocFrame"},{"p":"com.google.android.exoplayer2.source.chunk","l":"Chunk"},{"p":"com.google.android.exoplayer2.source.chunk","l":"ChunkExtractor"},{"p":"com.google.android.exoplayer2.source.chunk","l":"ChunkHolder"},{"p":"com.google.android.exoplayer2.extractor","l":"ChunkIndex"},{"p":"com.google.android.exoplayer2.source.chunk","l":"ChunkSampleStream"},{"p":"com.google.android.exoplayer2.source.chunk","l":"ChunkSource"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.ClearMediaItems"},{"p":"com.google.android.exoplayer2.upstream","l":"HttpDataSource.CleartextNotPermittedException"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.ClearVideoSurface"},{"p":"com.google.android.exoplayer2.source","l":"ClippingMediaPeriod"},{"p":"com.google.android.exoplayer2.source","l":"ClippingMediaSource"},{"p":"com.google.android.exoplayer2","l":"MediaItem.ClippingProperties"},{"p":"com.google.android.exoplayer2.util","l":"Clock"},{"p":"com.google.android.exoplayer2.video","l":"MediaCodecVideoRenderer.CodecMaxValues"},{"p":"com.google.android.exoplayer2.util","l":"CodecSpecificDataUtil"},{"p":"com.google.android.exoplayer2.testutil.truth","l":"SpannedSubject.Colored"},{"p":"com.google.android.exoplayer2.video","l":"ColorInfo"},{"p":"com.google.android.exoplayer2.util","l":"ColorParser"},{"p":"com.google.android.exoplayer2","l":"C.ColorRange"},{"p":"com.google.android.exoplayer2","l":"C.ColorSpace"},{"p":"com.google.android.exoplayer2","l":"C.ColorTransfer"},{"p":"com.google.android.exoplayer2","l":"Player.Command"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"MediaSessionConnector.CommandReceiver"},{"p":"com.google.android.exoplayer2","l":"Player.Commands"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"CommentFrame"},{"p":"com.google.android.exoplayer2.extractor","l":"VorbisUtil.CommentHeader"},{"p":"com.google.android.exoplayer2.metadata.scte35","l":"SpliceInsertCommand.ComponentSplice"},{"p":"com.google.android.exoplayer2.metadata.scte35","l":"SpliceScheduleCommand.ComponentSplice"},{"p":"com.google.android.exoplayer2.source","l":"CompositeMediaSource"},{"p":"com.google.android.exoplayer2.source","l":"CompositeSequenceableLoader"},{"p":"com.google.android.exoplayer2.source","l":"CompositeSequenceableLoaderFactory"},{"p":"com.google.android.exoplayer2.source","l":"ConcatenatingMediaSource"},{"p":"com.google.android.exoplayer2.util","l":"ConditionVariable"},{"p":"com.google.android.exoplayer2.audio","l":"AacUtil.Config"},{"p":"com.google.android.exoplayer2.mediacodec","l":"MediaCodecAdapter.Configuration"},{"p":"com.google.android.exoplayer2.audio","l":"AudioSink.ConfigurationException"},{"p":"com.google.android.exoplayer2.extractor","l":"ConstantBitrateSeekMap"},{"p":"com.google.android.exoplayer2.util","l":"Consumer"},{"p":"com.google.android.exoplayer2.source.chunk","l":"ContainerMediaChunk"},{"p":"com.google.android.exoplayer2.upstream","l":"ContentDataSource"},{"p":"com.google.android.exoplayer2.upstream","l":"ContentDataSource.ContentDataSourceException"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"ContentMetadata"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"ContentMetadataMutations"},{"p":"com.google.android.exoplayer2","l":"C.ContentType"},{"p":"com.google.android.exoplayer2","l":"ControlDispatcher"},{"p":"com.google.android.exoplayer2.util","l":"CopyOnWriteMultiset"},{"p":"com.google.android.exoplayer2","l":"Bundleable.Creator"},{"p":"com.google.android.exoplayer2.ext.cronet","l":"CronetDataSource"},{"p":"com.google.android.exoplayer2.ext.cronet","l":"CronetDataSourceFactory"},{"p":"com.google.android.exoplayer2.ext.cronet","l":"CronetEngineWrapper.CronetEngineSource"},{"p":"com.google.android.exoplayer2.ext.cronet","l":"CronetEngineWrapper"},{"p":"com.google.android.exoplayer2.extractor","l":"TrackOutput.CryptoData"},{"p":"com.google.android.exoplayer2.decoder","l":"CryptoInfo"},{"p":"com.google.android.exoplayer2","l":"C.CryptoMode"},{"p":"com.google.android.exoplayer2.text","l":"Cue"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"MediaSessionConnector.CustomActionProvider"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerNotificationManager.CustomActionReceiver"},{"p":"com.google.android.exoplayer2.ext.media2","l":"SessionCallbackBuilder.CustomCommandProvider"},{"p":"com.google.android.exoplayer2.source.dash","l":"DashChunkSource"},{"p":"com.google.android.exoplayer2.source.dash.offline","l":"DashDownloader"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"DashManifest"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"DashManifestParser"},{"p":"com.google.android.exoplayer2.source.dash","l":"DashManifestStaleException"},{"p":"com.google.android.exoplayer2.source.dash","l":"DashMediaSource"},{"p":"com.google.android.exoplayer2.source.dash","l":"DashSegmentIndex"},{"p":"com.google.android.exoplayer2.source.dash","l":"DashUtil"},{"p":"com.google.android.exoplayer2.source.dash","l":"DashWrappingSegmentIndex"},{"p":"com.google.android.exoplayer2.database","l":"DatabaseIOException"},{"p":"com.google.android.exoplayer2.database","l":"DatabaseProvider"},{"p":"com.google.android.exoplayer2.source.chunk","l":"DataChunk"},{"p":"com.google.android.exoplayer2.upstream","l":"DataReader"},{"p":"com.google.android.exoplayer2.upstream","l":"DataSchemeDataSource"},{"p":"com.google.android.exoplayer2.upstream","l":"DataSink"},{"p":"com.google.android.exoplayer2.upstream","l":"DataSource"},{"p":"com.google.android.exoplayer2.testutil","l":"DataSourceContractTest"},{"p":"com.google.android.exoplayer2.upstream","l":"DataSourceException"},{"p":"com.google.android.exoplayer2.upstream","l":"DataSourceInputStream"},{"p":"com.google.android.exoplayer2.upstream","l":"DataSpec"},{"p":"com.google.android.exoplayer2.util","l":"DebugTextViewHelper"},{"p":"com.google.android.exoplayer2.decoder","l":"Decoder"},{"p":"com.google.android.exoplayer2.audio","l":"DecoderAudioRenderer"},{"p":"com.google.android.exoplayer2.decoder","l":"DecoderCounters"},{"p":"com.google.android.exoplayer2.testutil","l":"DecoderCountersUtil"},{"p":"com.google.android.exoplayer2.decoder","l":"DecoderReuseEvaluation.DecoderDiscardReasons"},{"p":"com.google.android.exoplayer2.decoder","l":"DecoderException"},{"p":"com.google.android.exoplayer2.mediacodec","l":"MediaCodecRenderer.DecoderInitializationException"},{"p":"com.google.android.exoplayer2.decoder","l":"DecoderInputBuffer"},{"p":"com.google.android.exoplayer2.mediacodec","l":"MediaCodecUtil.DecoderQueryException"},{"p":"com.google.android.exoplayer2.decoder","l":"DecoderReuseEvaluation"},{"p":"com.google.android.exoplayer2.decoder","l":"DecoderReuseEvaluation.DecoderReuseResult"},{"p":"com.google.android.exoplayer2.video","l":"DecoderVideoRenderer"},{"p":"com.google.android.exoplayer2.drm","l":"DecryptionException"},{"p":"com.google.android.exoplayer2.upstream","l":"DefaultAllocator"},{"p":"com.google.android.exoplayer2.ext.media2","l":"SessionCallbackBuilder.DefaultAllowedCommandProvider"},{"p":"com.google.android.exoplayer2.audio","l":"DefaultAudioSink.DefaultAudioProcessorChain"},{"p":"com.google.android.exoplayer2.audio","l":"DefaultAudioSink"},{"p":"com.google.android.exoplayer2.upstream","l":"DefaultBandwidthMeter"},{"p":"com.google.android.exoplayer2.ext.cast","l":"DefaultCastOptionsProvider"},{"p":"com.google.android.exoplayer2.source","l":"DefaultCompositeSequenceableLoaderFactory"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"DefaultContentMetadata"},{"p":"com.google.android.exoplayer2","l":"DefaultControlDispatcher"},{"p":"com.google.android.exoplayer2.source.dash","l":"DefaultDashChunkSource"},{"p":"com.google.android.exoplayer2.database","l":"DefaultDatabaseProvider"},{"p":"com.google.android.exoplayer2.upstream","l":"DefaultDataSource"},{"p":"com.google.android.exoplayer2.upstream","l":"DefaultDataSourceFactory"},{"p":"com.google.android.exoplayer2.offline","l":"DefaultDownloaderFactory"},{"p":"com.google.android.exoplayer2.offline","l":"DefaultDownloadIndex"},{"p":"com.google.android.exoplayer2.drm","l":"DefaultDrmSessionManager"},{"p":"com.google.android.exoplayer2.drm","l":"DefaultDrmSessionManagerProvider"},{"p":"com.google.android.exoplayer2.extractor","l":"DefaultExtractorInput"},{"p":"com.google.android.exoplayer2.extractor","l":"DefaultExtractorsFactory"},{"p":"com.google.android.exoplayer2.source.hls","l":"DefaultHlsDataSourceFactory"},{"p":"com.google.android.exoplayer2.source.hls","l":"DefaultHlsExtractorFactory"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"DefaultHlsPlaylistParserFactory"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"DefaultHlsPlaylistTracker"},{"p":"com.google.android.exoplayer2.upstream","l":"DefaultHttpDataSource"},{"p":"com.google.android.exoplayer2.upstream","l":"DefaultHttpDataSourceFactory"},{"p":"com.google.android.exoplayer2","l":"DefaultLivePlaybackSpeedControl"},{"p":"com.google.android.exoplayer2","l":"DefaultLoadControl"},{"p":"com.google.android.exoplayer2.upstream","l":"DefaultLoadErrorHandlingPolicy"},{"p":"com.google.android.exoplayer2.ext.cast","l":"DefaultMediaItemConverter"},{"p":"com.google.android.exoplayer2.ext.media2","l":"DefaultMediaItemConverter"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"MediaSessionConnector.DefaultMediaMetadataProvider"},{"p":"com.google.android.exoplayer2.source","l":"DefaultMediaSourceFactory"},{"p":"com.google.android.exoplayer2.analytics","l":"DefaultPlaybackSessionManager"},{"p":"com.google.android.exoplayer2","l":"DefaultRenderersFactory"},{"p":"com.google.android.exoplayer2.testutil","l":"DefaultRenderersFactoryAsserts"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","l":"DefaultRtpPayloadReaderFactory"},{"p":"com.google.android.exoplayer2.extractor","l":"BinarySearchSeeker.DefaultSeekTimestampConverter"},{"p":"com.google.android.exoplayer2.source","l":"ShuffleOrder.DefaultShuffleOrder"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","l":"DefaultSsChunkSource"},{"p":"com.google.android.exoplayer2.ui","l":"DefaultTimeBar"},{"p":"com.google.android.exoplayer2.ui","l":"DefaultTrackNameProvider"},{"p":"com.google.android.exoplayer2.trackselection","l":"DefaultTrackSelector"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"DefaultTsPayloadReaderFactory"},{"p":"com.google.android.exoplayer2.trackselection","l":"ExoTrackSelection.Definition"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsPlaylistParser.DeltaUpdateException"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"Descriptor"},{"p":"com.google.android.exoplayer2","l":"ExoPlayer.DeviceComponent"},{"p":"com.google.android.exoplayer2.device","l":"DeviceInfo"},{"p":"com.google.android.exoplayer2.device","l":"DeviceListener"},{"p":"com.google.android.exoplayer2.ui","l":"TrackSelectionDialogBuilder.DialogCallback"},{"p":"com.google.android.exoplayer2.ext.media2","l":"SessionCallbackBuilder.DisconnectedCallback"},{"p":"com.google.android.exoplayer2","l":"Player.DiscontinuityReason"},{"p":"com.google.android.exoplayer2.video","l":"DolbyVisionConfig"},{"p":"com.google.android.exoplayer2.offline","l":"Download"},{"p":"com.google.android.exoplayer2.testutil","l":"DownloadBuilder"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadCursor"},{"p":"com.google.android.exoplayer2.offline","l":"Downloader"},{"p":"com.google.android.exoplayer2.offline","l":"DownloaderFactory"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadException"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadHelper"},{"p":"com.google.android.exoplayer2.offline","l":"ActionFileUpgradeUtil.DownloadIdProvider"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadIndex"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadManager"},{"p":"com.google.android.exoplayer2.ui","l":"DownloadNotificationHelper"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadProgress"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadRequest"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadService"},{"p":"com.google.android.exoplayer2","l":"MediaItem.DrmConfiguration"},{"p":"com.google.android.exoplayer2.drm","l":"DrmInitData"},{"p":"com.google.android.exoplayer2.drm","l":"DrmSession"},{"p":"com.google.android.exoplayer2.drm","l":"DrmSessionEventListener"},{"p":"com.google.android.exoplayer2.drm","l":"DrmSession.DrmSessionException"},{"p":"com.google.android.exoplayer2.drm","l":"DrmSessionManager"},{"p":"com.google.android.exoplayer2.drm","l":"DrmSessionManagerProvider"},{"p":"com.google.android.exoplayer2.drm","l":"DrmSessionManager.DrmSessionReference"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"DtsReader"},{"p":"com.google.android.exoplayer2.audio","l":"DtsUtil"},{"p":"com.google.android.exoplayer2.upstream","l":"LoaderErrorThrower.Dummy"},{"p":"com.google.android.exoplayer2.upstream","l":"DummyDataSource"},{"p":"com.google.android.exoplayer2.drm","l":"DummyExoMediaDrm"},{"p":"com.google.android.exoplayer2.extractor","l":"DummyExtractorOutput"},{"p":"com.google.android.exoplayer2.testutil","l":"DummyMainThread"},{"p":"com.google.android.exoplayer2.video","l":"DummySurface"},{"p":"com.google.android.exoplayer2.extractor","l":"DummyTrackOutput"},{"p":"com.google.android.exoplayer2.testutil","l":"Dumper.Dumpable"},{"p":"com.google.android.exoplayer2.testutil","l":"DumpableFormat"},{"p":"com.google.android.exoplayer2.testutil","l":"Dumper"},{"p":"com.google.android.exoplayer2.testutil","l":"DumpFileAsserts"},{"p":"com.google.android.exoplayer2.text.dvb","l":"DvbDecoder"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"TsPayloadReader.DvbSubtitleInfo"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"DvbSubtitleReader"},{"p":"com.google.android.exoplayer2.extractor.mkv","l":"EbmlProcessor"},{"p":"com.google.android.exoplayer2.ui","l":"CaptionStyleCompat.EdgeType"},{"p":"com.google.android.exoplayer2.util","l":"EGLSurfaceTexture"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"ElementaryStreamReader"},{"p":"com.google.android.exoplayer2.extractor.mkv","l":"EbmlProcessor.ElementType"},{"p":"com.google.android.exoplayer2.source.chunk","l":"ChunkSampleStream.EmbeddedSampleStream"},{"p":"com.google.android.exoplayer2.testutil.truth","l":"SpannedSubject.EmphasizedText"},{"p":"com.google.android.exoplayer2.source","l":"EmptySampleStream"},{"p":"com.google.android.exoplayer2","l":"C.Encoding"},{"p":"com.google.android.exoplayer2.metadata","l":"Metadata.Entry"},{"p":"com.google.android.exoplayer2.util","l":"ErrorMessageProvider"},{"p":"com.google.android.exoplayer2.drm","l":"ErrorStateDrmSession"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"TsPayloadReader.EsInfo"},{"p":"com.google.android.exoplayer2.metadata.scte35","l":"SpliceScheduleCommand.Event"},{"p":"com.google.android.exoplayer2.util","l":"ListenerSet.Event"},{"p":"com.google.android.exoplayer2.audio","l":"AudioRendererEventListener.EventDispatcher"},{"p":"com.google.android.exoplayer2.drm","l":"DrmSessionEventListener.EventDispatcher"},{"p":"com.google.android.exoplayer2.source","l":"MediaSourceEventListener.EventDispatcher"},{"p":"com.google.android.exoplayer2.upstream","l":"BandwidthMeter.EventListener.EventDispatcher"},{"p":"com.google.android.exoplayer2.video","l":"VideoRendererEventListener.EventDispatcher"},{"p":"com.google.android.exoplayer2","l":"Player.EventFlags"},{"p":"com.google.android.exoplayer2.analytics","l":"AnalyticsListener.EventFlags"},{"p":"com.google.android.exoplayer2","l":"Player.EventListener"},{"p":"com.google.android.exoplayer2.source.ads","l":"AdsLoader.EventListener"},{"p":"com.google.android.exoplayer2.upstream","l":"BandwidthMeter.EventListener"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheDataSource.EventListener"},{"p":"com.google.android.exoplayer2.util","l":"EventLogger"},{"p":"com.google.android.exoplayer2.metadata.emsg","l":"EventMessage"},{"p":"com.google.android.exoplayer2.metadata.emsg","l":"EventMessageDecoder"},{"p":"com.google.android.exoplayer2.metadata.emsg","l":"EventMessageEncoder"},{"p":"com.google.android.exoplayer2","l":"Player.Events"},{"p":"com.google.android.exoplayer2.analytics","l":"AnalyticsListener.Events"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"EventStream"},{"p":"com.google.android.exoplayer2.analytics","l":"AnalyticsListener.EventTime"},{"p":"com.google.android.exoplayer2.analytics","l":"PlaybackStats.EventTimeAndException"},{"p":"com.google.android.exoplayer2.analytics","l":"PlaybackStats.EventTimeAndFormat"},{"p":"com.google.android.exoplayer2.analytics","l":"PlaybackStats.EventTimeAndPlaybackState"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.ExecuteRunnable"},{"p":"com.google.android.exoplayer2.database","l":"ExoDatabaseProvider"},{"p":"com.google.android.exoplayer2.util","l":"ExoFlags"},{"p":"com.google.android.exoplayer2.testutil","l":"ExoHostedTest"},{"p":"com.google.android.exoplayer2.drm","l":"ExoMediaCrypto"},{"p":"com.google.android.exoplayer2.drm","l":"ExoMediaDrm"},{"p":"com.google.android.exoplayer2","l":"ExoPlaybackException"},{"p":"com.google.android.exoplayer2","l":"ExoPlayer"},{"p":"com.google.android.exoplayer2","l":"ExoPlayerLibraryInfo"},{"p":"com.google.android.exoplayer2.testutil","l":"ExoPlayerTestRunner"},{"p":"com.google.android.exoplayer2","l":"ExoTimeoutException"},{"p":"com.google.android.exoplayer2.trackselection","l":"ExoTrackSelection"},{"p":"com.google.android.exoplayer2","l":"DefaultRenderersFactory.ExtensionRendererMode"},{"p":"com.google.android.exoplayer2.extractor","l":"Extractor"},{"p":"com.google.android.exoplayer2.testutil","l":"ExtractorAsserts"},{"p":"com.google.android.exoplayer2.testutil","l":"ExtractorAsserts.ExtractorFactory"},{"p":"com.google.android.exoplayer2.extractor","l":"ExtractorInput"},{"p":"com.google.android.exoplayer2.extractor","l":"ExtractorOutput"},{"p":"com.google.android.exoplayer2.extractor","l":"ExtractorsFactory"},{"p":"com.google.android.exoplayer2.extractor","l":"ExtractorUtil"},{"p":"com.google.android.exoplayer2.ext.cronet","l":"CronetDataSource.Factory"},{"p":"com.google.android.exoplayer2.ext.okhttp","l":"OkHttpDataSource.Factory"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"TsPayloadReader.Factory"},{"p":"com.google.android.exoplayer2.mediacodec","l":"MediaCodecAdapter.Factory"},{"p":"com.google.android.exoplayer2.mediacodec","l":"SynchronousMediaCodecAdapter.Factory"},{"p":"com.google.android.exoplayer2.source","l":"ProgressiveMediaExtractor.Factory"},{"p":"com.google.android.exoplayer2.source","l":"ProgressiveMediaSource.Factory"},{"p":"com.google.android.exoplayer2.source","l":"SilenceMediaSource.Factory"},{"p":"com.google.android.exoplayer2.source","l":"SingleSampleMediaSource.Factory"},{"p":"com.google.android.exoplayer2.source.chunk","l":"ChunkExtractor.Factory"},{"p":"com.google.android.exoplayer2.source.dash","l":"DashChunkSource.Factory"},{"p":"com.google.android.exoplayer2.source.dash","l":"DashMediaSource.Factory"},{"p":"com.google.android.exoplayer2.source.dash","l":"DefaultDashChunkSource.Factory"},{"p":"com.google.android.exoplayer2.source.hls","l":"HlsMediaSource.Factory"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsPlaylistTracker.Factory"},{"p":"com.google.android.exoplayer2.source.rtsp","l":"RtspMediaSource.Factory"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","l":"RtpPayloadReader.Factory"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","l":"DefaultSsChunkSource.Factory"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","l":"SsChunkSource.Factory"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","l":"SsMediaSource.Factory"},{"p":"com.google.android.exoplayer2.testutil","l":"FailOnCloseDataSink.Factory"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeAdaptiveDataSet.Factory"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeChunkSource.Factory"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeDataSource.Factory"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeTrackOutput.Factory"},{"p":"com.google.android.exoplayer2.trackselection","l":"AdaptiveTrackSelection.Factory"},{"p":"com.google.android.exoplayer2.trackselection","l":"ExoTrackSelection.Factory"},{"p":"com.google.android.exoplayer2.trackselection","l":"RandomTrackSelection.Factory"},{"p":"com.google.android.exoplayer2.upstream","l":"DataSink.Factory"},{"p":"com.google.android.exoplayer2.upstream","l":"DataSource.Factory"},{"p":"com.google.android.exoplayer2.upstream","l":"DefaultHttpDataSource.Factory"},{"p":"com.google.android.exoplayer2.upstream","l":"FileDataSource.Factory"},{"p":"com.google.android.exoplayer2.upstream","l":"HttpDataSource.Factory"},{"p":"com.google.android.exoplayer2.upstream","l":"ResolvingDataSource.Factory"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheDataSink.Factory"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheDataSource.Factory"},{"p":"com.google.android.exoplayer2.testutil","l":"FailOnCloseDataSink"},{"p":"com.google.android.exoplayer2.offline","l":"Download.FailureReason"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeAdaptiveDataSet"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeAdaptiveMediaPeriod"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeAdaptiveMediaSource"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeAudioRenderer"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeChunkSource"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeClock"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeDataSet.FakeData"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeDataSet"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeDataSource"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeExoMediaDrm"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeExtractorInput"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeExtractorOutput"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeMediaChunk"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeMediaChunkIterator"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeMediaClockRenderer"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeMediaPeriod"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeMediaSource"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeRenderer"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeSampleStream"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeSampleStream.FakeSampleStreamItem"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeShuffleOrder"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeTimeline"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeTrackOutput"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeTrackSelection"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeTrackSelector"},{"p":"com.google.android.exoplayer2.testutil","l":"DataSourceContractTest.FakeTransferListener"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeVideoRenderer"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","l":"FfmpegAudioRenderer"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","l":"FfmpegDecoderException"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","l":"FfmpegLibrary"},{"p":"com.google.android.exoplayer2.upstream","l":"FileDataSource"},{"p":"com.google.android.exoplayer2.upstream","l":"FileDataSource.FileDataSourceException"},{"p":"com.google.android.exoplayer2.upstream","l":"FileDataSourceFactory"},{"p":"com.google.android.exoplayer2.util","l":"FileTypes"},{"p":"com.google.android.exoplayer2.offline","l":"FilterableManifest"},{"p":"com.google.android.exoplayer2.testutil","l":"MediaPeriodAsserts.FilterableManifestMediaPeriodFactory"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"FilteringHlsPlaylistParserFactory"},{"p":"com.google.android.exoplayer2.offline","l":"FilteringManifestParser"},{"p":"com.google.android.exoplayer2.trackselection","l":"FixedTrackSelection"},{"p":"com.google.android.exoplayer2.util","l":"FlacConstants"},{"p":"com.google.android.exoplayer2.ext.flac","l":"FlacDecoder"},{"p":"com.google.android.exoplayer2.ext.flac","l":"FlacDecoderException"},{"p":"com.google.android.exoplayer2.ext.flac","l":"FlacExtractor"},{"p":"com.google.android.exoplayer2.extractor.flac","l":"FlacExtractor"},{"p":"com.google.android.exoplayer2.extractor","l":"FlacFrameReader"},{"p":"com.google.android.exoplayer2.ext.flac","l":"FlacLibrary"},{"p":"com.google.android.exoplayer2.extractor","l":"FlacMetadataReader"},{"p":"com.google.android.exoplayer2.extractor","l":"FlacSeekTableSeekMap"},{"p":"com.google.android.exoplayer2.extractor","l":"FlacStreamMetadata"},{"p":"com.google.android.exoplayer2.extractor","l":"FlacMetadataReader.FlacStreamMetadataHolder"},{"p":"com.google.android.exoplayer2.ext.flac","l":"FlacExtractor.Flags"},{"p":"com.google.android.exoplayer2.extractor.amr","l":"AmrExtractor.Flags"},{"p":"com.google.android.exoplayer2.extractor.flac","l":"FlacExtractor.Flags"},{"p":"com.google.android.exoplayer2.extractor.mkv","l":"MatroskaExtractor.Flags"},{"p":"com.google.android.exoplayer2.extractor.mp3","l":"Mp3Extractor.Flags"},{"p":"com.google.android.exoplayer2.extractor.mp4","l":"FragmentedMp4Extractor.Flags"},{"p":"com.google.android.exoplayer2.extractor.mp4","l":"Mp4Extractor.Flags"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"AdtsExtractor.Flags"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"DefaultTsPayloadReaderFactory.Flags"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"TsPayloadReader.Flags"},{"p":"com.google.android.exoplayer2.upstream","l":"DataSpec.Flags"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheDataSource.Flags"},{"p":"com.google.android.exoplayer2.extractor.flv","l":"FlvExtractor"},{"p":"com.google.android.exoplayer2","l":"MediaMetadata.FolderType"},{"p":"com.google.android.exoplayer2.text.webvtt","l":"WebvttCssStyle.FontSizeUnit"},{"p":"com.google.android.exoplayer2","l":"Format"},{"p":"com.google.android.exoplayer2","l":"FormatHolder"},{"p":"com.google.android.exoplayer2","l":"C.FormatSupport"},{"p":"com.google.android.exoplayer2","l":"RendererCapabilities.FormatSupport"},{"p":"com.google.android.exoplayer2.audio","l":"ForwardingAudioSink"},{"p":"com.google.android.exoplayer2.extractor","l":"ForwardingExtractorInput"},{"p":"com.google.android.exoplayer2.source","l":"ForwardingTimeline"},{"p":"com.google.android.exoplayer2.extractor.mp4","l":"FragmentedMp4Extractor"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"Id3Decoder.FramePredicate"},{"p":"com.google.android.exoplayer2.drm","l":"FrameworkMediaCrypto"},{"p":"com.google.android.exoplayer2.drm","l":"FrameworkMediaDrm"},{"p":"com.google.android.exoplayer2.extractor","l":"GaplessInfoHolder"},{"p":"com.google.android.exoplayer2.ext.av1","l":"Gav1Decoder"},{"p":"com.google.android.exoplayer2.ext.av1","l":"Gav1DecoderException"},{"p":"com.google.android.exoplayer2.ext.av1","l":"Gav1Library"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"GeobFrame"},{"p":"com.google.android.exoplayer2.util","l":"EGLSurfaceTexture.GlException"},{"p":"com.google.android.exoplayer2.util","l":"GlUtil"},{"p":"com.google.android.exoplayer2.ext.gvr","l":"GvrAudioProcessor"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"H262Reader"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"H263Reader"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"H264Reader"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"H265Reader"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeClock.HandlerMessage"},{"p":"com.google.android.exoplayer2.util","l":"HandlerWrapper"},{"p":"com.google.android.exoplayer2.audio","l":"MpegAudioUtil.Header"},{"p":"com.google.android.exoplayer2","l":"HeartRating"},{"p":"com.google.android.exoplayer2.video","l":"HevcConfig"},{"p":"com.google.android.exoplayer2.source.hls","l":"HlsDataSourceFactory"},{"p":"com.google.android.exoplayer2.source.hls.offline","l":"HlsDownloader"},{"p":"com.google.android.exoplayer2.source.hls","l":"HlsExtractorFactory"},{"p":"com.google.android.exoplayer2.source.hls","l":"HlsManifest"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsMasterPlaylist"},{"p":"com.google.android.exoplayer2.source.hls","l":"HlsMediaChunkExtractor"},{"p":"com.google.android.exoplayer2.source.hls","l":"HlsMediaPeriod"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsMediaPlaylist"},{"p":"com.google.android.exoplayer2.source.hls","l":"HlsMediaSource"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsPlaylist"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsPlaylistParser"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsPlaylistParserFactory"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsPlaylistTracker"},{"p":"com.google.android.exoplayer2.source.hls","l":"HlsTrackMetadataEntry"},{"p":"com.google.android.exoplayer2.text.span","l":"HorizontalTextInVerticalContextSpan"},{"p":"com.google.android.exoplayer2.testutil","l":"HostActivity"},{"p":"com.google.android.exoplayer2.testutil","l":"HostActivity.HostedTest"},{"p":"com.google.android.exoplayer2.upstream","l":"HttpDataSource"},{"p":"com.google.android.exoplayer2.upstream","l":"HttpDataSource.HttpDataSourceException"},{"p":"com.google.android.exoplayer2.testutil","l":"HttpDataSourceTestEnv"},{"p":"com.google.android.exoplayer2.drm","l":"HttpMediaDrmCallback"},{"p":"com.google.android.exoplayer2.upstream","l":"DataSpec.HttpMethod"},{"p":"com.google.android.exoplayer2.upstream","l":"HttpUtil"},{"p":"com.google.android.exoplayer2.metadata.icy","l":"IcyDecoder"},{"p":"com.google.android.exoplayer2.metadata.icy","l":"IcyHeaders"},{"p":"com.google.android.exoplayer2.metadata.icy","l":"IcyInfo"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"Id3Decoder"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"Id3Frame"},{"p":"com.google.android.exoplayer2.extractor","l":"Id3Peeker"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"Id3Reader"},{"p":"com.google.android.exoplayer2.source","l":"ClippingMediaSource.IllegalClippingException"},{"p":"com.google.android.exoplayer2.source","l":"MergingMediaSource.IllegalMergeException"},{"p":"com.google.android.exoplayer2","l":"IllegalSeekPositionException"},{"p":"com.google.android.exoplayer2.ext.ima","l":"ImaAdsLoader"},{"p":"com.google.android.exoplayer2.util","l":"NotificationUtil.Importance"},{"p":"com.google.android.exoplayer2.extractor","l":"IndexSeekMap"},{"p":"com.google.android.exoplayer2.util","l":"SntpClient.InitializationCallback"},{"p":"com.google.android.exoplayer2.source.chunk","l":"InitializationChunk"},{"p":"com.google.android.exoplayer2.audio","l":"AudioSink.InitializationException"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeMediaSource.InitialTimeline"},{"p":"com.google.android.exoplayer2.source.mediaparser","l":"InputReaderAdapterV30"},{"p":"com.google.android.exoplayer2.decoder","l":"DecoderInputBuffer.InsufficientCapacityException"},{"p":"com.google.android.exoplayer2.util","l":"IntArrayQueue"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"InternalFrame"},{"p":"com.google.android.exoplayer2.trackselection","l":"TrackSelector.InvalidationListener"},{"p":"com.google.android.exoplayer2.audio","l":"DefaultAudioSink.InvalidAudioTrackTimestampException"},{"p":"com.google.android.exoplayer2.upstream","l":"HttpDataSource.InvalidContentTypeException"},{"p":"com.google.android.exoplayer2.upstream","l":"HttpDataSource.InvalidResponseCodeException"},{"p":"com.google.android.exoplayer2.util","l":"ListenerSet.IterationFinishedEvent"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeAdaptiveDataSet.Iterator"},{"p":"com.google.android.exoplayer2.extractor.jpeg","l":"JpegExtractor"},{"p":"com.google.android.exoplayer2.drm","l":"ExoMediaDrm.KeyRequest"},{"p":"com.google.android.exoplayer2.drm","l":"KeysExpiredException"},{"p":"com.google.android.exoplayer2.drm","l":"ExoMediaDrm.KeyStatus"},{"p":"com.google.android.exoplayer2.text.span","l":"LanguageFeatureSpan"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"LatmReader"},{"p":"com.google.android.exoplayer2.ext.leanback","l":"LeanbackPlayerAdapter"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"LeastRecentlyUsedCacheEvictor"},{"p":"com.google.android.exoplayer2.ext.flac","l":"LibflacAudioRenderer"},{"p":"com.google.android.exoplayer2.ext.av1","l":"Libgav1VideoRenderer"},{"p":"com.google.android.exoplayer2.ext.opus","l":"LibopusAudioRenderer"},{"p":"com.google.android.exoplayer2.util","l":"LibraryLoader"},{"p":"com.google.android.exoplayer2.ext.vp9","l":"LibvpxVideoRenderer"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeExoMediaDrm.LicenseServer"},{"p":"com.google.android.exoplayer2.text","l":"Cue.LineType"},{"p":"com.google.android.exoplayer2","l":"Player.Listener"},{"p":"com.google.android.exoplayer2.analytics","l":"PlaybackSessionManager.Listener"},{"p":"com.google.android.exoplayer2.audio","l":"AudioCapabilitiesReceiver.Listener"},{"p":"com.google.android.exoplayer2.audio","l":"AudioSink.Listener"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadManager.Listener"},{"p":"com.google.android.exoplayer2.scheduler","l":"RequirementsWatcher.Listener"},{"p":"com.google.android.exoplayer2.transformer","l":"Transformer.Listener"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"Cache.Listener"},{"p":"com.google.android.exoplayer2.util","l":"NetworkTypeObserver.Listener"},{"p":"com.google.android.exoplayer2.util","l":"ListenerSet"},{"p":"com.google.android.exoplayer2","l":"MediaItem.LiveConfiguration"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadHelper.LiveContentUnsupportedException"},{"p":"com.google.android.exoplayer2","l":"LivePlaybackSpeedControl"},{"p":"com.google.android.exoplayer2.upstream","l":"Loader.Loadable"},{"p":"com.google.android.exoplayer2","l":"LoadControl"},{"p":"com.google.android.exoplayer2.upstream","l":"Loader"},{"p":"com.google.android.exoplayer2.upstream","l":"LoaderErrorThrower"},{"p":"com.google.android.exoplayer2.upstream","l":"Loader.LoadErrorAction"},{"p":"com.google.android.exoplayer2.upstream","l":"LoadErrorHandlingPolicy"},{"p":"com.google.android.exoplayer2.upstream","l":"LoadErrorHandlingPolicy.LoadErrorInfo"},{"p":"com.google.android.exoplayer2.source","l":"LoadEventInfo"},{"p":"com.google.android.exoplayer2.drm","l":"LocalMediaDrmCallback"},{"p":"com.google.android.exoplayer2.util","l":"Log"},{"p":"com.google.android.exoplayer2.util","l":"LongArray"},{"p":"com.google.android.exoplayer2.source","l":"LoopingMediaSource"},{"p":"com.google.android.exoplayer2.trackselection","l":"MappingTrackSelector.MappedTrackInfo"},{"p":"com.google.android.exoplayer2.trackselection","l":"MappingTrackSelector"},{"p":"com.google.android.exoplayer2.text.span","l":"TextEmphasisSpan.MarkFill"},{"p":"com.google.android.exoplayer2.text.span","l":"TextEmphasisSpan.MarkShape"},{"p":"com.google.android.exoplayer2.source","l":"MaskingMediaPeriod"},{"p":"com.google.android.exoplayer2.source","l":"MaskingMediaSource"},{"p":"com.google.android.exoplayer2.extractor.mkv","l":"MatroskaExtractor"},{"p":"com.google.android.exoplayer2.metadata.mp4","l":"MdtaMetadataEntry"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"MediaSessionConnector.MediaButtonEventHandler"},{"p":"com.google.android.exoplayer2.source.chunk","l":"MediaChunk"},{"p":"com.google.android.exoplayer2.source.chunk","l":"MediaChunkIterator"},{"p":"com.google.android.exoplayer2.util","l":"MediaClock"},{"p":"com.google.android.exoplayer2.mediacodec","l":"MediaCodecAdapter"},{"p":"com.google.android.exoplayer2.audio","l":"MediaCodecAudioRenderer"},{"p":"com.google.android.exoplayer2.mediacodec","l":"MediaCodecDecoderException"},{"p":"com.google.android.exoplayer2.mediacodec","l":"MediaCodecInfo"},{"p":"com.google.android.exoplayer2.mediacodec","l":"MediaCodecRenderer"},{"p":"com.google.android.exoplayer2.mediacodec","l":"MediaCodecSelector"},{"p":"com.google.android.exoplayer2.mediacodec","l":"MediaCodecUtil"},{"p":"com.google.android.exoplayer2.video","l":"MediaCodecVideoDecoderException"},{"p":"com.google.android.exoplayer2.video","l":"MediaCodecVideoRenderer"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerNotificationManager.MediaDescriptionAdapter"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"TimelineQueueEditor.MediaDescriptionConverter"},{"p":"com.google.android.exoplayer2.drm","l":"MediaDrmCallback"},{"p":"com.google.android.exoplayer2.drm","l":"MediaDrmCallbackException"},{"p":"com.google.android.exoplayer2.util","l":"MediaFormatUtil"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"TimelineQueueEditor.MediaIdEqualityChecker"},{"p":"com.google.android.exoplayer2.ext.media2","l":"SessionCallbackBuilder.MediaIdMediaItemProvider"},{"p":"com.google.android.exoplayer2","l":"MediaItem"},{"p":"com.google.android.exoplayer2.ext.cast","l":"MediaItemConverter"},{"p":"com.google.android.exoplayer2.ext.media2","l":"MediaItemConverter"},{"p":"com.google.android.exoplayer2.ext.media2","l":"SessionCallbackBuilder.MediaItemProvider"},{"p":"com.google.android.exoplayer2","l":"Player.MediaItemTransitionReason"},{"p":"com.google.android.exoplayer2.source","l":"MediaLoadData"},{"p":"com.google.android.exoplayer2","l":"MediaMetadata"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"MediaSessionConnector.MediaMetadataProvider"},{"p":"com.google.android.exoplayer2.source.chunk","l":"MediaParserChunkExtractor"},{"p":"com.google.android.exoplayer2.source","l":"MediaParserExtractorAdapter"},{"p":"com.google.android.exoplayer2.source.hls","l":"MediaParserHlsMediaChunkExtractor"},{"p":"com.google.android.exoplayer2.source.mediaparser","l":"MediaParserUtil"},{"p":"com.google.android.exoplayer2.source","l":"MediaPeriod"},{"p":"com.google.android.exoplayer2.testutil","l":"MediaPeriodAsserts"},{"p":"com.google.android.exoplayer2.source","l":"MediaPeriodId"},{"p":"com.google.android.exoplayer2.source","l":"MediaSource.MediaPeriodId"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"MediaSessionConnector"},{"p":"com.google.android.exoplayer2.source","l":"MediaSource"},{"p":"com.google.android.exoplayer2.source","l":"MediaSource.MediaSourceCaller"},{"p":"com.google.android.exoplayer2.source","l":"MediaSourceEventListener"},{"p":"com.google.android.exoplayer2.source","l":"MediaSourceFactory"},{"p":"com.google.android.exoplayer2.testutil","l":"MediaSourceTestRunner"},{"p":"com.google.android.exoplayer2.source","l":"MergingMediaSource"},{"p":"com.google.android.exoplayer2.util","l":"HandlerWrapper.Message"},{"p":"com.google.android.exoplayer2.metadata","l":"Metadata"},{"p":"com.google.android.exoplayer2","l":"ExoPlayer.MetadataComponent"},{"p":"com.google.android.exoplayer2.metadata","l":"MetadataDecoder"},{"p":"com.google.android.exoplayer2.metadata","l":"MetadataDecoderFactory"},{"p":"com.google.android.exoplayer2.metadata","l":"MetadataInputBuffer"},{"p":"com.google.android.exoplayer2.metadata","l":"MetadataOutput"},{"p":"com.google.android.exoplayer2.metadata","l":"MetadataRenderer"},{"p":"com.google.android.exoplayer2","l":"MetadataRetriever"},{"p":"com.google.android.exoplayer2.source.hls","l":"HlsMediaSource.MetadataType"},{"p":"com.google.android.exoplayer2.util","l":"MimeTypes"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","l":"SsManifestParser.MissingFieldException"},{"p":"com.google.android.exoplayer2.drm","l":"DefaultDrmSessionManager.MissingSchemeDataException"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"MlltFrame"},{"p":"com.google.android.exoplayer2.drm","l":"DefaultDrmSessionManager.Mode"},{"p":"com.google.android.exoplayer2.extractor","l":"VorbisUtil.Mode"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"TsExtractor.Mode"},{"p":"com.google.android.exoplayer2.metadata.mp4","l":"MotionPhotoMetadata"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.MoveMediaItem"},{"p":"com.google.android.exoplayer2.extractor.mp3","l":"Mp3Extractor"},{"p":"com.google.android.exoplayer2.extractor.mp4","l":"Mp4Extractor"},{"p":"com.google.android.exoplayer2.text.webvtt","l":"Mp4WebvttDecoder"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"MpegAudioReader"},{"p":"com.google.android.exoplayer2.audio","l":"MpegAudioUtil"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"SegmentBase.MultiSegmentBase"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"Representation.MultiSegmentRepresentation"},{"p":"com.google.android.exoplayer2.util","l":"NalUnitUtil"},{"p":"com.google.android.exoplayer2","l":"C.NetworkType"},{"p":"com.google.android.exoplayer2.util","l":"NetworkTypeObserver"},{"p":"com.google.android.exoplayer2.util","l":"NonNullApi"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"NoOpCacheEvictor"},{"p":"com.google.android.exoplayer2","l":"NoSampleRenderer"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerNotificationManager.NotificationListener"},{"p":"com.google.android.exoplayer2.util","l":"NotificationUtil"},{"p":"com.google.android.exoplayer2.testutil","l":"NoUidTimeline"},{"p":"com.google.android.exoplayer2.drm","l":"OfflineLicenseHelper"},{"p":"com.google.android.exoplayer2.audio","l":"DefaultAudioSink.OffloadMode"},{"p":"com.google.android.exoplayer2.extractor.ogg","l":"OggExtractor"},{"p":"com.google.android.exoplayer2.ext.okhttp","l":"OkHttpDataSource"},{"p":"com.google.android.exoplayer2.ext.okhttp","l":"OkHttpDataSourceFactory"},{"p":"com.google.android.exoplayer2.drm","l":"ExoMediaDrm.OnEventListener"},{"p":"com.google.android.exoplayer2.drm","l":"ExoMediaDrm.OnExpirationUpdateListener"},{"p":"com.google.android.exoplayer2.mediacodec","l":"MediaCodecAdapter.OnFrameRenderedListener"},{"p":"com.google.android.exoplayer2.ui","l":"StyledPlayerControlView.OnFullScreenModeChangedListener"},{"p":"com.google.android.exoplayer2.drm","l":"ExoMediaDrm.OnKeyStatusChangeListener"},{"p":"com.google.android.exoplayer2.ui","l":"TimeBar.OnScrubListener"},{"p":"com.google.android.exoplayer2.ext.cronet","l":"CronetDataSource.OpenException"},{"p":"com.google.android.exoplayer2.ext.opus","l":"OpusDecoder"},{"p":"com.google.android.exoplayer2.ext.opus","l":"OpusDecoderException"},{"p":"com.google.android.exoplayer2.ext.opus","l":"OpusLibrary"},{"p":"com.google.android.exoplayer2.audio","l":"OpusUtil"},{"p":"com.google.android.exoplayer2.trackselection","l":"DefaultTrackSelector.OtherTrackScore"},{"p":"com.google.android.exoplayer2.decoder","l":"OutputBuffer"},{"p":"com.google.android.exoplayer2.source.mediaparser","l":"OutputConsumerAdapterV30"},{"p":"com.google.android.exoplayer2.decoder","l":"OutputBuffer.Owner"},{"p":"com.google.android.exoplayer2.trackselection","l":"DefaultTrackSelector.Parameters"},{"p":"com.google.android.exoplayer2.trackselection","l":"DefaultTrackSelector.ParametersBuilder"},{"p":"com.google.android.exoplayer2.util","l":"ParsableBitArray"},{"p":"com.google.android.exoplayer2.util","l":"ParsableByteArray"},{"p":"com.google.android.exoplayer2.util","l":"ParsableNalUnitBitArray"},{"p":"com.google.android.exoplayer2.upstream","l":"ParsingLoadable.Parser"},{"p":"com.google.android.exoplayer2","l":"ParserException"},{"p":"com.google.android.exoplayer2.upstream","l":"ParsingLoadable"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsMediaPlaylist.Part"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"PassthroughSectionPayloadReader"},{"p":"com.google.android.exoplayer2","l":"C.PcmEncoding"},{"p":"com.google.android.exoplayer2","l":"PercentageRating"},{"p":"com.google.android.exoplayer2","l":"Timeline.Period"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"Period"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"PesReader"},{"p":"com.google.android.exoplayer2.text.pgs","l":"PgsDecoder"},{"p":"com.google.android.exoplayer2.metadata.flac","l":"PictureFrame"},{"p":"com.google.android.exoplayer2.source","l":"MaskingMediaSource.PlaceholderTimeline"},{"p":"com.google.android.exoplayer2.scheduler","l":"PlatformScheduler"},{"p":"com.google.android.exoplayer2.scheduler","l":"PlatformScheduler.PlatformSchedulerService"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"MediaSessionConnector.PlaybackActions"},{"p":"com.google.android.exoplayer2.robolectric","l":"PlaybackOutput"},{"p":"com.google.android.exoplayer2","l":"PlaybackParameters"},{"p":"com.google.android.exoplayer2","l":"PlaybackPreparer"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"MediaSessionConnector.PlaybackPreparer"},{"p":"com.google.android.exoplayer2","l":"MediaItem.PlaybackProperties"},{"p":"com.google.android.exoplayer2.analytics","l":"PlaybackSessionManager"},{"p":"com.google.android.exoplayer2.analytics","l":"PlaybackStats"},{"p":"com.google.android.exoplayer2.analytics","l":"PlaybackStatsListener"},{"p":"com.google.android.exoplayer2","l":"Player.PlaybackSuppressionReason"},{"p":"com.google.android.exoplayer2.device","l":"DeviceInfo.PlaybackType"},{"p":"com.google.android.exoplayer2","l":"Player"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerControlView"},{"p":"com.google.android.exoplayer2.source.dash","l":"PlayerEmsgHandler.PlayerEmsgCallback"},{"p":"com.google.android.exoplayer2.source.dash","l":"PlayerEmsgHandler"},{"p":"com.google.android.exoplayer2","l":"PlayerMessage"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerNotificationManager"},{"p":"com.google.android.exoplayer2.testutil","l":"ActionSchedule.PlayerRunnable"},{"p":"com.google.android.exoplayer2.testutil","l":"ActionSchedule.PlayerTarget"},{"p":"com.google.android.exoplayer2.source.dash","l":"PlayerEmsgHandler.PlayerTrackEmsgHandler"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerView"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsPlaylistTracker.PlaylistEventListener"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsPlaylistTracker.PlaylistResetException"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsPlaylistTracker.PlaylistStuckException"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsMediaPlaylist.PlaylistType"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.PlayUntilPosition"},{"p":"com.google.android.exoplayer2","l":"Player.PlayWhenReadyChangeReason"},{"p":"com.google.android.exoplayer2.text.span","l":"TextAnnotation.Position"},{"p":"com.google.android.exoplayer2.extractor","l":"PositionHolder"},{"p":"com.google.android.exoplayer2","l":"Player.PositionInfo"},{"p":"com.google.android.exoplayer2.ext.media2","l":"SessionCallbackBuilder.PostConnectCallback"},{"p":"com.google.android.exoplayer2.util","l":"NalUnitUtil.PpsData"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.Prepare"},{"p":"com.google.android.exoplayer2.source","l":"MaskingMediaPeriod.PrepareListener"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsPlaylistTracker.PrimaryPlaylistListener"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerNotificationManager.Priority"},{"p":"com.google.android.exoplayer2.upstream","l":"PriorityDataSource"},{"p":"com.google.android.exoplayer2.upstream","l":"PriorityDataSourceFactory"},{"p":"com.google.android.exoplayer2.util","l":"PriorityTaskManager"},{"p":"com.google.android.exoplayer2.util","l":"PriorityTaskManager.PriorityTooLowException"},{"p":"com.google.android.exoplayer2.metadata.scte35","l":"PrivateCommand"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"PrivFrame"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"ProgramInformation"},{"p":"com.google.android.exoplayer2.transformer","l":"ProgressHolder"},{"p":"com.google.android.exoplayer2.offline","l":"ProgressiveDownloader"},{"p":"com.google.android.exoplayer2.source","l":"ProgressiveMediaExtractor"},{"p":"com.google.android.exoplayer2.source","l":"ProgressiveMediaSource"},{"p":"com.google.android.exoplayer2.offline","l":"Downloader.ProgressListener"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheWriter.ProgressListener"},{"p":"com.google.android.exoplayer2.transformer","l":"Transformer.ProgressState"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerControlView.ProgressUpdateListener"},{"p":"com.google.android.exoplayer2.ui","l":"StyledPlayerControlView.ProgressUpdateListener"},{"p":"com.google.android.exoplayer2","l":"C.Projection"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","l":"SsManifest.ProtectionElement"},{"p":"com.google.android.exoplayer2.drm","l":"ExoMediaDrm.Provider"},{"p":"com.google.android.exoplayer2.drm","l":"ExoMediaDrm.ProvisionRequest"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"PsExtractor"},{"p":"com.google.android.exoplayer2.extractor.mp4","l":"PsshAtomUtil"},{"p":"com.google.android.exoplayer2.ui","l":"AdOverlayInfo.Purpose"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"TimelineQueueEditor.QueueDataAdapter"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"MediaSessionConnector.QueueEditor"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"MediaSessionConnector.QueueNavigator"},{"p":"com.google.android.exoplayer2.robolectric","l":"RandomizedMp3Decoder"},{"p":"com.google.android.exoplayer2.trackselection","l":"RandomTrackSelection"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"RangedUri"},{"p":"com.google.android.exoplayer2","l":"Rating"},{"p":"com.google.android.exoplayer2.ext.media2","l":"SessionCallbackBuilder.RatingCallback"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"MediaSessionConnector.RatingCallback"},{"p":"com.google.android.exoplayer2.extractor.rawcc","l":"RawCcExtractor"},{"p":"com.google.android.exoplayer2.upstream","l":"RawResourceDataSource"},{"p":"com.google.android.exoplayer2.upstream","l":"RawResourceDataSource.RawResourceDataSourceException"},{"p":"com.google.android.exoplayer2.source","l":"SampleStream.ReadDataResult"},{"p":"com.google.android.exoplayer2.source","l":"SampleStream.ReadFlags"},{"p":"com.google.android.exoplayer2.extractor","l":"Extractor.ReadResult"},{"p":"com.google.android.exoplayer2.drm","l":"UnsupportedDrmException.Reason"},{"p":"com.google.android.exoplayer2.source","l":"ClippingMediaSource.IllegalClippingException.Reason"},{"p":"com.google.android.exoplayer2.source","l":"MergingMediaSource.IllegalMergeException.Reason"},{"p":"com.google.android.exoplayer2.testutil.truth","l":"SpannedSubject.RelativeSized"},{"p":"com.google.android.exoplayer2.source.chunk","l":"ChunkSampleStream.ReleaseCallback"},{"p":"com.google.android.exoplayer2.upstream","l":"Loader.ReleaseCallback"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.RemoveMediaItem"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.RemoveMediaItems"},{"p":"com.google.android.exoplayer2","l":"Renderer"},{"p":"com.google.android.exoplayer2","l":"RendererCapabilities"},{"p":"com.google.android.exoplayer2","l":"RendererConfiguration"},{"p":"com.google.android.exoplayer2","l":"RenderersFactory"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsMasterPlaylist.Rendition"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsMediaPlaylist.RenditionReport"},{"p":"com.google.android.exoplayer2","l":"Player.RepeatMode"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"RepeatModeActionProvider"},{"p":"com.google.android.exoplayer2.util","l":"RepeatModeUtil"},{"p":"com.google.android.exoplayer2.util","l":"RepeatModeUtil.RepeatToggleModes"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"Representation"},{"p":"com.google.android.exoplayer2.source.dash","l":"DefaultDashChunkSource.RepresentationHolder"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"DashManifestParser.RepresentationInfo"},{"p":"com.google.android.exoplayer2.source.dash","l":"DefaultDashChunkSource.RepresentationSegmentIterator"},{"p":"com.google.android.exoplayer2.upstream","l":"HttpDataSource.RequestProperties"},{"p":"com.google.android.exoplayer2.testutil","l":"CacheAsserts.RequestSet"},{"p":"com.google.android.exoplayer2.drm","l":"ExoMediaDrm.KeyRequest.RequestType"},{"p":"com.google.android.exoplayer2.scheduler","l":"Requirements.RequirementFlags"},{"p":"com.google.android.exoplayer2.scheduler","l":"Requirements"},{"p":"com.google.android.exoplayer2.scheduler","l":"RequirementsWatcher"},{"p":"com.google.android.exoplayer2.ui","l":"AspectRatioFrameLayout.ResizeMode"},{"p":"com.google.android.exoplayer2.upstream","l":"ResolvingDataSource.Resolver"},{"p":"com.google.android.exoplayer2.upstream","l":"ResolvingDataSource"},{"p":"com.google.android.exoplayer2.testutil","l":"WebServerDispatcher.Resource"},{"p":"com.google.android.exoplayer2.util","l":"ReusableBufferedOutputStream"},{"p":"com.google.android.exoplayer2.robolectric","l":"RobolectricUtil"},{"p":"com.google.android.exoplayer2","l":"C.RoleFlags"},{"p":"com.google.android.exoplayer2.ext.rtmp","l":"RtmpDataSource"},{"p":"com.google.android.exoplayer2.ext.rtmp","l":"RtmpDataSourceFactory"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","l":"RtpAc3Reader"},{"p":"com.google.android.exoplayer2.source.rtsp","l":"RtpPacket"},{"p":"com.google.android.exoplayer2.source.rtsp","l":"RtpPayloadFormat"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","l":"RtpPayloadReader"},{"p":"com.google.android.exoplayer2.source.rtsp","l":"RtpUtils"},{"p":"com.google.android.exoplayer2.source.rtsp","l":"RtspMediaSource"},{"p":"com.google.android.exoplayer2.source.rtsp","l":"RtspMediaSource.RtspPlaybackException"},{"p":"com.google.android.exoplayer2.text.span","l":"RubySpan"},{"p":"com.google.android.exoplayer2.testutil.truth","l":"SpannedSubject.RubyText"},{"p":"com.google.android.exoplayer2.util","l":"RunnableFutureTask"},{"p":"com.google.android.exoplayer2.extractor","l":"TrackOutput.SampleDataPart"},{"p":"com.google.android.exoplayer2.extractor","l":"FlacFrameReader.SampleNumberHolder"},{"p":"com.google.android.exoplayer2.source","l":"SampleQueue"},{"p":"com.google.android.exoplayer2.source.hls","l":"SampleQueueMappingException"},{"p":"com.google.android.exoplayer2.source","l":"SampleStream"},{"p":"com.google.android.exoplayer2.scheduler","l":"Scheduler"},{"p":"com.google.android.exoplayer2.ext.workmanager","l":"WorkManagerScheduler.SchedulerWorker"},{"p":"com.google.android.exoplayer2.drm","l":"DrmInitData.SchemeData"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"SectionPayloadReader"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"SectionReader"},{"p":"com.google.android.exoplayer2.util","l":"EGLSurfaceTexture.SecureMode"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.Seek"},{"p":"com.google.android.exoplayer2.extractor","l":"SeekMap"},{"p":"com.google.android.exoplayer2.extractor","l":"BinarySearchSeeker.SeekOperationParams"},{"p":"com.google.android.exoplayer2","l":"SeekParameters"},{"p":"com.google.android.exoplayer2.extractor","l":"SeekPoint"},{"p":"com.google.android.exoplayer2.extractor","l":"SeekMap.SeekPoints"},{"p":"com.google.android.exoplayer2.extractor","l":"FlacStreamMetadata.SeekTable"},{"p":"com.google.android.exoplayer2.extractor","l":"BinarySearchSeeker.SeekTimestampConverter"},{"p":"com.google.android.exoplayer2.metadata.mp4","l":"SlowMotionData.Segment"},{"p":"com.google.android.exoplayer2.offline","l":"SegmentDownloader.Segment"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsMediaPlaylist.Segment"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeDataSet.FakeData.Segment"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"SegmentBase"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsMediaPlaylist.SegmentBase"},{"p":"com.google.android.exoplayer2.offline","l":"SegmentDownloader"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"SegmentBase.SegmentList"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"SegmentBase.SegmentTemplate"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"SegmentBase.SegmentTimelineElement"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"SeiReader"},{"p":"com.google.android.exoplayer2","l":"C.SelectionFlags"},{"p":"com.google.android.exoplayer2.trackselection","l":"DefaultTrackSelector.SelectionOverride"},{"p":"com.google.android.exoplayer2","l":"PlayerMessage.Sender"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.SendMessages"},{"p":"com.google.android.exoplayer2.source","l":"SequenceableLoader"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsMediaPlaylist.ServerControl"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"ServiceDescriptionElement"},{"p":"com.google.android.exoplayer2.ext.cast","l":"SessionAvailabilityListener"},{"p":"com.google.android.exoplayer2.ext.media2","l":"SessionCallbackBuilder"},{"p":"com.google.android.exoplayer2.ext.media2","l":"SessionPlayerConnector"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.SetAudioAttributes"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.SetMediaItems"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.SetMediaItemsResetPosition"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.SetPlaybackParameters"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.SetPlayWhenReady"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.SetRendererDisabled"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.SetRepeatMode"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.SetShuffleModeEnabled"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.SetShuffleOrder"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.SetVideoSurface"},{"p":"com.google.android.exoplayer2.robolectric","l":"ShadowMediaCodecConfig"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerView.ShowBuffering"},{"p":"com.google.android.exoplayer2.ui","l":"StyledPlayerView.ShowBuffering"},{"p":"com.google.android.exoplayer2.source","l":"ShuffleOrder"},{"p":"com.google.android.exoplayer2.source","l":"SilenceMediaSource"},{"p":"com.google.android.exoplayer2.audio","l":"SilenceSkippingAudioProcessor"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"SimpleCache"},{"p":"com.google.android.exoplayer2.decoder","l":"SimpleDecoder"},{"p":"com.google.android.exoplayer2","l":"SimpleExoPlayer"},{"p":"com.google.android.exoplayer2.metadata","l":"SimpleMetadataDecoder"},{"p":"com.google.android.exoplayer2.decoder","l":"SimpleOutputBuffer"},{"p":"com.google.android.exoplayer2.text","l":"SimpleSubtitleDecoder"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeExtractorInput.SimulatedIOException"},{"p":"com.google.android.exoplayer2.testutil","l":"ExtractorAsserts.SimulationConfig"},{"p":"com.google.android.exoplayer2.source.ads","l":"SinglePeriodAdTimeline"},{"p":"com.google.android.exoplayer2.source","l":"SinglePeriodTimeline"},{"p":"com.google.android.exoplayer2.source.chunk","l":"SingleSampleMediaChunk"},{"p":"com.google.android.exoplayer2.source","l":"SingleSampleMediaSource"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"SegmentBase.SingleSegmentBase"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"Representation.SingleSegmentRepresentation"},{"p":"com.google.android.exoplayer2.audio","l":"AudioSink.SinkFormatSupport"},{"p":"com.google.android.exoplayer2.ext.media2","l":"SessionCallbackBuilder.SkipCallback"},{"p":"com.google.android.exoplayer2.util","l":"SlidingPercentile"},{"p":"com.google.android.exoplayer2.metadata.mp4","l":"SlowMotionData"},{"p":"com.google.android.exoplayer2.metadata.mp4","l":"SmtaMetadataEntry"},{"p":"com.google.android.exoplayer2.util","l":"SntpClient"},{"p":"com.google.android.exoplayer2.audio","l":"SonicAudioProcessor"},{"p":"com.google.android.exoplayer2.testutil.truth","l":"SpannedSubject"},{"p":"com.google.android.exoplayer2.text.span","l":"SpanUtil"},{"p":"com.google.android.exoplayer2.video.spherical","l":"SphericalGLSurfaceView"},{"p":"com.google.android.exoplayer2.metadata.scte35","l":"SpliceCommand"},{"p":"com.google.android.exoplayer2.metadata.scte35","l":"SpliceInfoDecoder"},{"p":"com.google.android.exoplayer2.metadata.scte35","l":"SpliceInsertCommand"},{"p":"com.google.android.exoplayer2.metadata.scte35","l":"SpliceNullCommand"},{"p":"com.google.android.exoplayer2.metadata.scte35","l":"SpliceScheduleCommand"},{"p":"com.google.android.exoplayer2.util","l":"NalUnitUtil.SpsData"},{"p":"com.google.android.exoplayer2.text.ssa","l":"SsaDecoder"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","l":"SsChunkSource"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.offline","l":"SsDownloader"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","l":"SsManifest"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","l":"SsManifestParser"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","l":"SsMediaSource"},{"p":"com.google.android.exoplayer2.util","l":"StandaloneMediaClock"},{"p":"com.google.android.exoplayer2","l":"StarRating"},{"p":"com.google.android.exoplayer2.extractor.jpeg","l":"StartOffsetExtractorOutput"},{"p":"com.google.android.exoplayer2","l":"Player.State"},{"p":"com.google.android.exoplayer2","l":"Renderer.State"},{"p":"com.google.android.exoplayer2.drm","l":"DrmSession.State"},{"p":"com.google.android.exoplayer2.offline","l":"Download.State"},{"p":"com.google.android.exoplayer2.upstream","l":"StatsDataSource"},{"p":"com.google.android.exoplayer2","l":"C.StereoMode"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.Stop"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","l":"SsManifest.StreamElement"},{"p":"com.google.android.exoplayer2.offline","l":"StreamKey"},{"p":"com.google.android.exoplayer2","l":"C.StreamType"},{"p":"com.google.android.exoplayer2.audio","l":"Ac3Util.SyncFrameInfo.StreamType"},{"p":"com.google.android.exoplayer2.testutil","l":"StubExoPlayer"},{"p":"com.google.android.exoplayer2.ui","l":"StyledPlayerControlView"},{"p":"com.google.android.exoplayer2.ui","l":"StyledPlayerView"},{"p":"com.google.android.exoplayer2.text.webvtt","l":"WebvttCssStyle.StyleFlags"},{"p":"com.google.android.exoplayer2.text.subrip","l":"SubripDecoder"},{"p":"com.google.android.exoplayer2","l":"MediaItem.Subtitle"},{"p":"com.google.android.exoplayer2.text","l":"Subtitle"},{"p":"com.google.android.exoplayer2.text","l":"SubtitleDecoder"},{"p":"com.google.android.exoplayer2.text","l":"SubtitleDecoderException"},{"p":"com.google.android.exoplayer2.text","l":"SubtitleDecoderFactory"},{"p":"com.google.android.exoplayer2.text","l":"SubtitleInputBuffer"},{"p":"com.google.android.exoplayer2.text","l":"SubtitleOutputBuffer"},{"p":"com.google.android.exoplayer2.ui","l":"SubtitleView"},{"p":"com.google.android.exoplayer2.audio","l":"Ac3Util.SyncFrameInfo"},{"p":"com.google.android.exoplayer2.audio","l":"Ac4Util.SyncFrameInfo"},{"p":"com.google.android.exoplayer2.mediacodec","l":"SynchronousMediaCodecAdapter"},{"p":"com.google.android.exoplayer2.util","l":"SystemClock"},{"p":"com.google.android.exoplayer2","l":"PlayerMessage.Target"},{"p":"com.google.android.exoplayer2.audio","l":"TeeAudioProcessor"},{"p":"com.google.android.exoplayer2.upstream","l":"TeeDataSource"},{"p":"com.google.android.exoplayer2.robolectric","l":"TestDownloadManagerListener"},{"p":"com.google.android.exoplayer2.testutil","l":"TestExoPlayerBuilder"},{"p":"com.google.android.exoplayer2.robolectric","l":"TestPlayerRunHelper"},{"p":"com.google.android.exoplayer2.testutil","l":"DataSourceContractTest.TestResource"},{"p":"com.google.android.exoplayer2.testutil","l":"DummyMainThread.TestRunnable"},{"p":"com.google.android.exoplayer2.testutil","l":"TestUtil"},{"p":"com.google.android.exoplayer2.text.span","l":"TextAnnotation"},{"p":"com.google.android.exoplayer2","l":"ExoPlayer.TextComponent"},{"p":"com.google.android.exoplayer2.text.span","l":"TextEmphasisSpan"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"TextInformationFrame"},{"p":"com.google.android.exoplayer2.text","l":"TextOutput"},{"p":"com.google.android.exoplayer2.text","l":"TextRenderer"},{"p":"com.google.android.exoplayer2.text","l":"Cue.TextSizeType"},{"p":"com.google.android.exoplayer2.trackselection","l":"DefaultTrackSelector.TextTrackScore"},{"p":"com.google.android.exoplayer2.util","l":"EGLSurfaceTexture.TextureImageListener"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.ThrowPlaybackException"},{"p":"com.google.android.exoplayer2","l":"ThumbRating"},{"p":"com.google.android.exoplayer2.ui","l":"TimeBar"},{"p":"com.google.android.exoplayer2.util","l":"TimedValueQueue"},{"p":"com.google.android.exoplayer2","l":"Timeline"},{"p":"com.google.android.exoplayer2.testutil","l":"TimelineAsserts"},{"p":"com.google.android.exoplayer2","l":"Player.TimelineChangeReason"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"TimelineQueueEditor"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"TimelineQueueNavigator"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeTimeline.TimelineWindowDefinition"},{"p":"com.google.android.exoplayer2","l":"ExoTimeoutException.TimeoutOperation"},{"p":"com.google.android.exoplayer2.metadata.scte35","l":"TimeSignalCommand"},{"p":"com.google.android.exoplayer2.util","l":"TimestampAdjuster"},{"p":"com.google.android.exoplayer2.source.hls","l":"TimestampAdjusterProvider"},{"p":"com.google.android.exoplayer2.extractor","l":"BinarySearchSeeker.TimestampSearchResult"},{"p":"com.google.android.exoplayer2.extractor","l":"BinarySearchSeeker.TimestampSeeker"},{"p":"com.google.android.exoplayer2.upstream","l":"TimeToFirstByteEstimator"},{"p":"com.google.android.exoplayer2.util","l":"TraceUtil"},{"p":"com.google.android.exoplayer2.extractor.mp4","l":"Track"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeMediaPeriod.TrackDataFactory"},{"p":"com.google.android.exoplayer2.extractor.mp4","l":"TrackEncryptionBox"},{"p":"com.google.android.exoplayer2.source","l":"TrackGroup"},{"p":"com.google.android.exoplayer2.source","l":"TrackGroupArray"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"TsPayloadReader.TrackIdGenerator"},{"p":"com.google.android.exoplayer2.ui","l":"TrackNameProvider"},{"p":"com.google.android.exoplayer2.extractor","l":"TrackOutput"},{"p":"com.google.android.exoplayer2.source.chunk","l":"ChunkExtractor.TrackOutputProvider"},{"p":"com.google.android.exoplayer2.trackselection","l":"TrackSelection"},{"p":"com.google.android.exoplayer2.trackselection","l":"TrackSelectionArray"},{"p":"com.google.android.exoplayer2.ui","l":"TrackSelectionDialogBuilder"},{"p":"com.google.android.exoplayer2.ui","l":"TrackSelectionView.TrackSelectionListener"},{"p":"com.google.android.exoplayer2.trackselection","l":"TrackSelectionParameters"},{"p":"com.google.android.exoplayer2.trackselection","l":"TrackSelectionUtil"},{"p":"com.google.android.exoplayer2.ui","l":"TrackSelectionView"},{"p":"com.google.android.exoplayer2.trackselection","l":"TrackSelector"},{"p":"com.google.android.exoplayer2.trackselection","l":"TrackSelectorResult"},{"p":"com.google.android.exoplayer2.upstream","l":"TransferListener"},{"p":"com.google.android.exoplayer2.extractor.mp4","l":"Track.Transformation"},{"p":"com.google.android.exoplayer2.transformer","l":"Transformer"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"TsExtractor"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"TsPayloadReader"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"TsUtil"},{"p":"com.google.android.exoplayer2.text.ttml","l":"TtmlDecoder"},{"p":"com.google.android.exoplayer2","l":"RendererCapabilities.TunnelingSupport"},{"p":"com.google.android.exoplayer2.text.tx3g","l":"Tx3gDecoder"},{"p":"com.google.android.exoplayer2","l":"ExoPlaybackException.Type"},{"p":"com.google.android.exoplayer2.source.ads","l":"AdsMediaSource.AdLoadException.Type"},{"p":"com.google.android.exoplayer2.upstream","l":"HttpDataSource.HttpDataSourceException.Type"},{"p":"com.google.android.exoplayer2.util","l":"FileTypes.Type"},{"p":"com.google.android.exoplayer2.testutil.truth","l":"SpannedSubject.Typefaced"},{"p":"com.google.android.exoplayer2.upstream","l":"UdpDataSource"},{"p":"com.google.android.exoplayer2.upstream","l":"UdpDataSource.UdpDataSourceException"},{"p":"com.google.android.exoplayer2.audio","l":"AudioSink.UnexpectedDiscontinuityException"},{"p":"com.google.android.exoplayer2.upstream","l":"Loader.UnexpectedLoaderException"},{"p":"com.google.android.exoplayer2.audio","l":"AudioProcessor.UnhandledAudioFormatException"},{"p":"com.google.android.exoplayer2.util","l":"GlUtil.Uniform"},{"p":"com.google.android.exoplayer2.util","l":"UnknownNull"},{"p":"com.google.android.exoplayer2.source","l":"UnrecognizedInputFormatException"},{"p":"com.google.android.exoplayer2.extractor","l":"SeekMap.Unseekable"},{"p":"com.google.android.exoplayer2.source","l":"ShuffleOrder.UnshuffledShuffleOrder"},{"p":"com.google.android.exoplayer2.drm","l":"UnsupportedDrmException"},{"p":"com.google.android.exoplayer2.drm","l":"UnsupportedMediaCrypto"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadRequest.UnsupportedRequestException"},{"p":"com.google.android.exoplayer2.source","l":"SampleQueue.UpstreamFormatChangedListener"},{"p":"com.google.android.exoplayer2.util","l":"UriUtil"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"UrlLinkFrame"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"UrlTemplate"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"UtcTimingElement"},{"p":"com.google.android.exoplayer2.util","l":"Util"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsMasterPlaylist.Variant"},{"p":"com.google.android.exoplayer2.source.hls","l":"HlsTrackMetadataEntry.VariantInfo"},{"p":"com.google.android.exoplayer2.database","l":"VersionTable"},{"p":"com.google.android.exoplayer2.text","l":"Cue.VerticalType"},{"p":"com.google.android.exoplayer2","l":"ExoPlayer.VideoComponent"},{"p":"com.google.android.exoplayer2.video","l":"VideoDecoderGLSurfaceView"},{"p":"com.google.android.exoplayer2.video","l":"VideoDecoderInputBuffer"},{"p":"com.google.android.exoplayer2.video","l":"VideoDecoderOutputBuffer"},{"p":"com.google.android.exoplayer2.video","l":"VideoDecoderOutputBufferRenderer"},{"p":"com.google.android.exoplayer2.video","l":"VideoFrameMetadataListener"},{"p":"com.google.android.exoplayer2.video","l":"VideoFrameReleaseHelper"},{"p":"com.google.android.exoplayer2.video","l":"VideoListener"},{"p":"com.google.android.exoplayer2","l":"C.VideoOutputMode"},{"p":"com.google.android.exoplayer2.video","l":"VideoRendererEventListener"},{"p":"com.google.android.exoplayer2","l":"C.VideoScalingMode"},{"p":"com.google.android.exoplayer2","l":"Renderer.VideoScalingMode"},{"p":"com.google.android.exoplayer2.video","l":"VideoSize"},{"p":"com.google.android.exoplayer2.video.spherical","l":"SphericalGLSurfaceView.VideoSurfaceListener"},{"p":"com.google.android.exoplayer2.trackselection","l":"DefaultTrackSelector.VideoTrackScore"},{"p":"com.google.android.exoplayer2.ui","l":"SubtitleView.ViewType"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerNotificationManager.Visibility"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerControlView.VisibilityListener"},{"p":"com.google.android.exoplayer2.ui","l":"StyledPlayerControlView.VisibilityListener"},{"p":"com.google.android.exoplayer2.extractor","l":"VorbisBitArray"},{"p":"com.google.android.exoplayer2.metadata.flac","l":"VorbisComment"},{"p":"com.google.android.exoplayer2.extractor","l":"VorbisUtil.VorbisIdHeader"},{"p":"com.google.android.exoplayer2.extractor","l":"VorbisUtil"},{"p":"com.google.android.exoplayer2.ext.vp9","l":"VpxDecoder"},{"p":"com.google.android.exoplayer2.ext.vp9","l":"VpxDecoderException"},{"p":"com.google.android.exoplayer2.ext.vp9","l":"VpxLibrary"},{"p":"com.google.android.exoplayer2.ext.vp9","l":"VpxOutputBuffer"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.WaitForIsLoading"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.WaitForMessage"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.WaitForPendingPlayerCommands"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.WaitForPlaybackState"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.WaitForPlayWhenReady"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.WaitForPositionDiscontinuity"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.WaitForTimelineChanged"},{"p":"com.google.android.exoplayer2","l":"C.WakeMode"},{"p":"com.google.android.exoplayer2","l":"Renderer.WakeupListener"},{"p":"com.google.android.exoplayer2.extractor.wav","l":"WavExtractor"},{"p":"com.google.android.exoplayer2.audio","l":"TeeAudioProcessor.WavFileAudioBufferSink"},{"p":"com.google.android.exoplayer2.audio","l":"WavUtil"},{"p":"com.google.android.exoplayer2.testutil","l":"WebServerDispatcher"},{"p":"com.google.android.exoplayer2.text.webvtt","l":"WebvttCssStyle"},{"p":"com.google.android.exoplayer2.text.webvtt","l":"WebvttCueInfo"},{"p":"com.google.android.exoplayer2.text.webvtt","l":"WebvttCueParser"},{"p":"com.google.android.exoplayer2.text.webvtt","l":"WebvttDecoder"},{"p":"com.google.android.exoplayer2.source.hls","l":"WebvttExtractor"},{"p":"com.google.android.exoplayer2.text.webvtt","l":"WebvttParserUtil"},{"p":"com.google.android.exoplayer2.drm","l":"WidevineUtil"},{"p":"com.google.android.exoplayer2","l":"Timeline.Window"},{"p":"com.google.android.exoplayer2.testutil.truth","l":"SpannedSubject.WithSpanFlags"},{"p":"com.google.android.exoplayer2.ext.workmanager","l":"WorkManagerScheduler"},{"p":"com.google.android.exoplayer2.offline","l":"WritableDownloadIndex"},{"p":"com.google.android.exoplayer2.audio","l":"AudioSink.WriteException"},{"p":"com.google.android.exoplayer2.util","l":"XmlPullParserUtil"}] \ No newline at end of file +typeSearchIndex = [{"p":"com.google.android.exoplayer2.audio","l":"AacUtil.AacAudioObjectType"},{"p":"com.google.android.exoplayer2.audio","l":"AacUtil"},{"p":"com.google.android.exoplayer2.testutil.truth","l":"SpannedSubject.AbsoluteSized"},{"p":"com.google.android.exoplayer2","l":"AbstractConcatenatedTimeline"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"Ac3Extractor"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"Ac3Reader"},{"p":"com.google.android.exoplayer2.audio","l":"Ac3Util"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"Ac4Extractor"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"Ac4Reader"},{"p":"com.google.android.exoplayer2.audio","l":"Ac4Util"},{"p":"com.google.android.exoplayer2.testutil","l":"Action"},{"p":"com.google.android.exoplayer2.offline","l":"ActionFileUpgradeUtil"},{"p":"com.google.android.exoplayer2.testutil","l":"ActionSchedule"},{"p":"com.google.android.exoplayer2.trackselection","l":"AdaptiveTrackSelection.AdaptationCheckpoint"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"AdaptationSet"},{"p":"com.google.android.exoplayer2","l":"RendererCapabilities.AdaptiveSupport"},{"p":"com.google.android.exoplayer2.trackselection","l":"AdaptiveTrackSelection"},{"p":"com.google.android.exoplayer2.trackselection","l":"TrackSelectionUtil.AdaptiveTrackSelectionFactory"},{"p":"com.google.android.exoplayer2.testutil","l":"AdditionalFailureInfo"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.AddMediaItems"},{"p":"com.google.android.exoplayer2.source.ads","l":"AdPlaybackState.AdGroup"},{"p":"com.google.android.exoplayer2.source.ads","l":"AdsMediaSource.AdLoadException"},{"p":"com.google.android.exoplayer2.ui","l":"AdOverlayInfo"},{"p":"com.google.android.exoplayer2.source.ads","l":"AdPlaybackState"},{"p":"com.google.android.exoplayer2","l":"MediaItem.AdsConfiguration"},{"p":"com.google.android.exoplayer2.source.ads","l":"AdsLoader"},{"p":"com.google.android.exoplayer2.source","l":"DefaultMediaSourceFactory.AdsLoaderProvider"},{"p":"com.google.android.exoplayer2.source.ads","l":"AdsMediaSource"},{"p":"com.google.android.exoplayer2.source.ads","l":"AdPlaybackState.AdState"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"AdtsExtractor"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"AdtsReader"},{"p":"com.google.android.exoplayer2.ui","l":"AdViewProvider"},{"p":"com.google.android.exoplayer2.upstream.crypto","l":"AesCipherDataSink"},{"p":"com.google.android.exoplayer2.upstream.crypto","l":"AesCipherDataSource"},{"p":"com.google.android.exoplayer2.upstream.crypto","l":"AesFlushingCipher"},{"p":"com.google.android.exoplayer2.testutil.truth","l":"SpannedSubject.Aligned"},{"l":"All Classes","url":"allclasses-index.html"},{"p":"com.google.android.exoplayer2.upstream","l":"Allocation"},{"p":"com.google.android.exoplayer2.upstream","l":"Allocator"},{"p":"com.google.android.exoplayer2.ext.media2","l":"SessionCallbackBuilder.AllowedCommandProvider"},{"p":"com.google.android.exoplayer2.extractor.amr","l":"AmrExtractor"},{"p":"com.google.android.exoplayer2.analytics","l":"AnalyticsCollector"},{"p":"com.google.android.exoplayer2.analytics","l":"AnalyticsListener"},{"p":"com.google.android.exoplayer2.text","l":"Cue.AnchorType"},{"p":"com.google.android.exoplayer2.testutil.truth","l":"SpannedSubject.AndSpanFlags"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"ApicFrame"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","l":"AppInfoTable"},{"p":"com.google.android.exoplayer2.metadata.dvbsi","l":"AppInfoTableDecoder"},{"p":"com.google.android.exoplayer2.drm","l":"ExoMediaDrm.AppManagedProvider"},{"p":"com.google.android.exoplayer2.ui","l":"AspectRatioFrameLayout"},{"p":"com.google.android.exoplayer2.ui","l":"AspectRatioFrameLayout.AspectRatioListener"},{"p":"com.google.android.exoplayer2.testutil","l":"ExtractorAsserts.AssertionConfig"},{"p":"com.google.android.exoplayer2.util","l":"Assertions"},{"p":"com.google.android.exoplayer2.upstream","l":"AssetDataSource"},{"p":"com.google.android.exoplayer2.upstream","l":"AssetDataSource.AssetDataSourceException"},{"p":"com.google.android.exoplayer2.util","l":"AtomicFile"},{"p":"com.google.android.exoplayer2.util","l":"GlUtil.Attribute"},{"p":"com.google.android.exoplayer2","l":"C.AudioAllowedCapturePolicy"},{"p":"com.google.android.exoplayer2.audio","l":"AudioAttributes"},{"p":"com.google.android.exoplayer2.audio","l":"TeeAudioProcessor.AudioBufferSink"},{"p":"com.google.android.exoplayer2.audio","l":"AudioCapabilities"},{"p":"com.google.android.exoplayer2.audio","l":"AudioCapabilitiesReceiver"},{"p":"com.google.android.exoplayer2","l":"ExoPlayer.AudioComponent"},{"p":"com.google.android.exoplayer2","l":"C.AudioContentType"},{"p":"com.google.android.exoplayer2","l":"C.AudioFlags"},{"p":"com.google.android.exoplayer2","l":"C.AudioFocusGain"},{"p":"com.google.android.exoplayer2.audio","l":"AudioProcessor.AudioFormat"},{"p":"com.google.android.exoplayer2.audio","l":"AudioListener"},{"p":"com.google.android.exoplayer2","l":"ExoPlayer.AudioOffloadListener"},{"p":"com.google.android.exoplayer2.audio","l":"AudioProcessor"},{"p":"com.google.android.exoplayer2.audio","l":"DefaultAudioSink.AudioProcessorChain"},{"p":"com.google.android.exoplayer2.audio","l":"AudioRendererEventListener"},{"p":"com.google.android.exoplayer2.audio","l":"AudioSink"},{"p":"com.google.android.exoplayer2.trackselection","l":"DefaultTrackSelector.AudioTrackScore"},{"p":"com.google.android.exoplayer2","l":"C.AudioUsage"},{"p":"com.google.android.exoplayer2.audio","l":"AuxEffectInfo"},{"p":"com.google.android.exoplayer2.video","l":"AvcConfig"},{"p":"com.google.android.exoplayer2.upstream","l":"BandwidthMeter"},{"p":"com.google.android.exoplayer2.audio","l":"BaseAudioProcessor"},{"p":"com.google.android.exoplayer2.upstream","l":"BaseDataSource"},{"p":"com.google.android.exoplayer2.upstream","l":"HttpDataSource.BaseFactory"},{"p":"com.google.android.exoplayer2.source.chunk","l":"BaseMediaChunk"},{"p":"com.google.android.exoplayer2.source.chunk","l":"BaseMediaChunkIterator"},{"p":"com.google.android.exoplayer2.source.chunk","l":"BaseMediaChunkOutput"},{"p":"com.google.android.exoplayer2.source","l":"BaseMediaSource"},{"p":"com.google.android.exoplayer2","l":"BasePlayer"},{"p":"com.google.android.exoplayer2","l":"BaseRenderer"},{"p":"com.google.android.exoplayer2.trackselection","l":"BaseTrackSelection"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"BaseUrl"},{"p":"com.google.android.exoplayer2.source.dash","l":"BaseUrlExclusionList"},{"p":"com.google.android.exoplayer2.source","l":"BehindLiveWindowException"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"BinaryFrame"},{"p":"com.google.android.exoplayer2.extractor","l":"BinarySearchSeeker"},{"p":"com.google.android.exoplayer2.extractor","l":"BinarySearchSeeker.BinarySearchSeekMap"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerNotificationManager.BitmapCallback"},{"p":"com.google.android.exoplayer2.decoder","l":"Buffer"},{"p":"com.google.android.exoplayer2","l":"C.BufferFlags"},{"p":"com.google.android.exoplayer2.decoder","l":"DecoderInputBuffer.BufferReplacementMode"},{"p":"com.google.android.exoplayer2","l":"DefaultLivePlaybackSpeedControl.Builder"},{"p":"com.google.android.exoplayer2","l":"DefaultLoadControl.Builder"},{"p":"com.google.android.exoplayer2","l":"ExoPlayer.Builder"},{"p":"com.google.android.exoplayer2","l":"Format.Builder"},{"p":"com.google.android.exoplayer2","l":"MediaItem.Builder"},{"p":"com.google.android.exoplayer2","l":"MediaMetadata.Builder"},{"p":"com.google.android.exoplayer2","l":"Player.Commands.Builder"},{"p":"com.google.android.exoplayer2","l":"SimpleExoPlayer.Builder"},{"p":"com.google.android.exoplayer2.audio","l":"AudioAttributes.Builder"},{"p":"com.google.android.exoplayer2.drm","l":"DefaultDrmSessionManager.Builder"},{"p":"com.google.android.exoplayer2.ext.ima","l":"ImaAdsLoader.Builder"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadRequest.Builder"},{"p":"com.google.android.exoplayer2.source.rtsp","l":"RtpPacket.Builder"},{"p":"com.google.android.exoplayer2.testutil","l":"ActionSchedule.Builder"},{"p":"com.google.android.exoplayer2.testutil","l":"DataSourceContractTest.TestResource.Builder"},{"p":"com.google.android.exoplayer2.testutil","l":"ExoPlayerTestRunner.Builder"},{"p":"com.google.android.exoplayer2.testutil","l":"ExtractorAsserts.AssertionConfig.Builder"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeExoMediaDrm.Builder"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeExtractorInput.Builder"},{"p":"com.google.android.exoplayer2.testutil","l":"WebServerDispatcher.Resource.Builder"},{"p":"com.google.android.exoplayer2.text","l":"Cue.Builder"},{"p":"com.google.android.exoplayer2.trackselection","l":"TrackSelectionParameters.Builder"},{"p":"com.google.android.exoplayer2.transformer","l":"Transformer.Builder"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerNotificationManager.Builder"},{"p":"com.google.android.exoplayer2.upstream","l":"DataSpec.Builder"},{"p":"com.google.android.exoplayer2.upstream","l":"DefaultBandwidthMeter.Builder"},{"p":"com.google.android.exoplayer2.util","l":"FlagSet.Builder"},{"p":"com.google.android.exoplayer2","l":"Bundleable"},{"p":"com.google.android.exoplayer2.util","l":"BundleableUtils"},{"p":"com.google.android.exoplayer2.source.chunk","l":"BundledChunkExtractor"},{"p":"com.google.android.exoplayer2.source","l":"BundledExtractorsAdapter"},{"p":"com.google.android.exoplayer2.source.hls","l":"BundledHlsMediaChunkExtractor"},{"p":"com.google.android.exoplayer2","l":"BundleListRetriever"},{"p":"com.google.android.exoplayer2.util","l":"BundleUtil"},{"p":"com.google.android.exoplayer2.upstream","l":"ByteArrayDataSink"},{"p":"com.google.android.exoplayer2.upstream","l":"ByteArrayDataSource"},{"p":"com.google.android.exoplayer2","l":"C"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"Cache"},{"p":"com.google.android.exoplayer2.testutil","l":"CacheAsserts"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheDataSink"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheDataSink.CacheDataSinkException"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheDataSinkFactory"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheDataSource"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheDataSourceFactory"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CachedRegionTracker"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheEvictor"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"Cache.CacheException"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheDataSource.CacheIgnoredReason"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheKeyFactory"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheSpan"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheWriter"},{"p":"com.google.android.exoplayer2.analytics","l":"PlaybackStatsListener.Callback"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadHelper.Callback"},{"p":"com.google.android.exoplayer2.source","l":"MediaPeriod.Callback"},{"p":"com.google.android.exoplayer2.source","l":"SequenceableLoader.Callback"},{"p":"com.google.android.exoplayer2.testutil","l":"ActionSchedule.Callback"},{"p":"com.google.android.exoplayer2.testutil","l":"ActionSchedule.PlayerTarget.Callback"},{"p":"com.google.android.exoplayer2.upstream","l":"Loader.Callback"},{"p":"com.google.android.exoplayer2.video.spherical","l":"CameraMotionListener"},{"p":"com.google.android.exoplayer2.video.spherical","l":"CameraMotionRenderer"},{"p":"com.google.android.exoplayer2","l":"RendererCapabilities.Capabilities"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"MediaSessionConnector.CaptionCallback"},{"p":"com.google.android.exoplayer2.ui","l":"CaptionStyleCompat"},{"p":"com.google.android.exoplayer2.testutil","l":"CapturingAudioSink"},{"p":"com.google.android.exoplayer2.testutil","l":"CapturingRenderersFactory"},{"p":"com.google.android.exoplayer2.ext.cast","l":"CastPlayer"},{"p":"com.google.android.exoplayer2.text.cea","l":"Cea608Decoder"},{"p":"com.google.android.exoplayer2.text.cea","l":"Cea708Decoder"},{"p":"com.google.android.exoplayer2.extractor","l":"CeaUtil"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"ChapterFrame"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"ChapterTocFrame"},{"p":"com.google.android.exoplayer2.source.chunk","l":"Chunk"},{"p":"com.google.android.exoplayer2.source.chunk","l":"ChunkExtractor"},{"p":"com.google.android.exoplayer2.source.chunk","l":"ChunkHolder"},{"p":"com.google.android.exoplayer2.extractor","l":"ChunkIndex"},{"p":"com.google.android.exoplayer2.source.chunk","l":"ChunkSampleStream"},{"p":"com.google.android.exoplayer2.source.chunk","l":"ChunkSource"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.ClearMediaItems"},{"p":"com.google.android.exoplayer2.upstream","l":"HttpDataSource.CleartextNotPermittedException"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.ClearVideoSurface"},{"p":"com.google.android.exoplayer2.source","l":"ClippingMediaPeriod"},{"p":"com.google.android.exoplayer2.source","l":"ClippingMediaSource"},{"p":"com.google.android.exoplayer2","l":"MediaItem.ClippingProperties"},{"p":"com.google.android.exoplayer2.util","l":"Clock"},{"p":"com.google.android.exoplayer2.video","l":"MediaCodecVideoRenderer.CodecMaxValues"},{"p":"com.google.android.exoplayer2.util","l":"CodecSpecificDataUtil"},{"p":"com.google.android.exoplayer2.testutil.truth","l":"SpannedSubject.Colored"},{"p":"com.google.android.exoplayer2.video","l":"ColorInfo"},{"p":"com.google.android.exoplayer2.util","l":"ColorParser"},{"p":"com.google.android.exoplayer2","l":"C.ColorRange"},{"p":"com.google.android.exoplayer2","l":"C.ColorSpace"},{"p":"com.google.android.exoplayer2","l":"C.ColorTransfer"},{"p":"com.google.android.exoplayer2","l":"Player.Command"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"MediaSessionConnector.CommandReceiver"},{"p":"com.google.android.exoplayer2","l":"Player.Commands"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"CommentFrame"},{"p":"com.google.android.exoplayer2.extractor","l":"VorbisUtil.CommentHeader"},{"p":"com.google.android.exoplayer2.metadata.scte35","l":"SpliceInsertCommand.ComponentSplice"},{"p":"com.google.android.exoplayer2.metadata.scte35","l":"SpliceScheduleCommand.ComponentSplice"},{"p":"com.google.android.exoplayer2.source","l":"CompositeMediaSource"},{"p":"com.google.android.exoplayer2.source","l":"CompositeSequenceableLoader"},{"p":"com.google.android.exoplayer2.source","l":"CompositeSequenceableLoaderFactory"},{"p":"com.google.android.exoplayer2.source","l":"ConcatenatingMediaSource"},{"p":"com.google.android.exoplayer2.util","l":"ConditionVariable"},{"p":"com.google.android.exoplayer2.audio","l":"AacUtil.Config"},{"p":"com.google.android.exoplayer2.util","l":"NetworkTypeObserver.Config"},{"p":"com.google.android.exoplayer2.mediacodec","l":"MediaCodecAdapter.Configuration"},{"p":"com.google.android.exoplayer2.audio","l":"AudioSink.ConfigurationException"},{"p":"com.google.android.exoplayer2.extractor","l":"ConstantBitrateSeekMap"},{"p":"com.google.android.exoplayer2.util","l":"Consumer"},{"p":"com.google.android.exoplayer2.source.chunk","l":"ContainerMediaChunk"},{"p":"com.google.android.exoplayer2.upstream","l":"ContentDataSource"},{"p":"com.google.android.exoplayer2.upstream","l":"ContentDataSource.ContentDataSourceException"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"ContentMetadata"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"ContentMetadataMutations"},{"p":"com.google.android.exoplayer2","l":"C.ContentType"},{"p":"com.google.android.exoplayer2","l":"ControlDispatcher"},{"p":"com.google.android.exoplayer2.util","l":"CopyOnWriteMultiset"},{"p":"com.google.android.exoplayer2","l":"Bundleable.Creator"},{"p":"com.google.android.exoplayer2.ext.cronet","l":"CronetDataSource"},{"p":"com.google.android.exoplayer2.ext.cronet","l":"CronetDataSourceFactory"},{"p":"com.google.android.exoplayer2.ext.cronet","l":"CronetEngineWrapper"},{"p":"com.google.android.exoplayer2.ext.cronet","l":"CronetUtil"},{"p":"com.google.android.exoplayer2.extractor","l":"TrackOutput.CryptoData"},{"p":"com.google.android.exoplayer2.decoder","l":"CryptoInfo"},{"p":"com.google.android.exoplayer2","l":"C.CryptoMode"},{"p":"com.google.android.exoplayer2.text","l":"Cue"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"MediaSessionConnector.CustomActionProvider"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerNotificationManager.CustomActionReceiver"},{"p":"com.google.android.exoplayer2.ext.media2","l":"SessionCallbackBuilder.CustomCommandProvider"},{"p":"com.google.android.exoplayer2.source.dash","l":"DashChunkSource"},{"p":"com.google.android.exoplayer2.source.dash.offline","l":"DashDownloader"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"DashManifest"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"DashManifestParser"},{"p":"com.google.android.exoplayer2.source.dash","l":"DashManifestStaleException"},{"p":"com.google.android.exoplayer2.source.dash","l":"DashMediaSource"},{"p":"com.google.android.exoplayer2.source.dash","l":"DashSegmentIndex"},{"p":"com.google.android.exoplayer2.source.dash","l":"DashUtil"},{"p":"com.google.android.exoplayer2.source.dash","l":"DashWrappingSegmentIndex"},{"p":"com.google.android.exoplayer2.database","l":"DatabaseIOException"},{"p":"com.google.android.exoplayer2.database","l":"DatabaseProvider"},{"p":"com.google.android.exoplayer2.source.chunk","l":"DataChunk"},{"p":"com.google.android.exoplayer2.upstream","l":"DataReader"},{"p":"com.google.android.exoplayer2.upstream","l":"DataSchemeDataSource"},{"p":"com.google.android.exoplayer2.upstream","l":"DataSink"},{"p":"com.google.android.exoplayer2.upstream","l":"DataSource"},{"p":"com.google.android.exoplayer2.testutil","l":"DataSourceContractTest"},{"p":"com.google.android.exoplayer2.upstream","l":"DataSourceException"},{"p":"com.google.android.exoplayer2.upstream","l":"DataSourceInputStream"},{"p":"com.google.android.exoplayer2.upstream","l":"DataSpec"},{"p":"com.google.android.exoplayer2","l":"C.DataType"},{"p":"com.google.android.exoplayer2.util","l":"DebugTextViewHelper"},{"p":"com.google.android.exoplayer2.decoder","l":"Decoder"},{"p":"com.google.android.exoplayer2.audio","l":"DecoderAudioRenderer"},{"p":"com.google.android.exoplayer2.decoder","l":"DecoderCounters"},{"p":"com.google.android.exoplayer2.testutil","l":"DecoderCountersUtil"},{"p":"com.google.android.exoplayer2.decoder","l":"DecoderReuseEvaluation.DecoderDiscardReasons"},{"p":"com.google.android.exoplayer2.decoder","l":"DecoderException"},{"p":"com.google.android.exoplayer2.mediacodec","l":"MediaCodecRenderer.DecoderInitializationException"},{"p":"com.google.android.exoplayer2.decoder","l":"DecoderInputBuffer"},{"p":"com.google.android.exoplayer2.mediacodec","l":"MediaCodecUtil.DecoderQueryException"},{"p":"com.google.android.exoplayer2.decoder","l":"DecoderReuseEvaluation"},{"p":"com.google.android.exoplayer2.decoder","l":"DecoderReuseEvaluation.DecoderReuseResult"},{"p":"com.google.android.exoplayer2.video","l":"DecoderVideoRenderer"},{"p":"com.google.android.exoplayer2.drm","l":"DecryptionException"},{"p":"com.google.android.exoplayer2.upstream","l":"DefaultAllocator"},{"p":"com.google.android.exoplayer2.ext.media2","l":"SessionCallbackBuilder.DefaultAllowedCommandProvider"},{"p":"com.google.android.exoplayer2.audio","l":"DefaultAudioSink.DefaultAudioProcessorChain"},{"p":"com.google.android.exoplayer2.audio","l":"DefaultAudioSink"},{"p":"com.google.android.exoplayer2.upstream","l":"DefaultBandwidthMeter"},{"p":"com.google.android.exoplayer2.ext.cast","l":"DefaultCastOptionsProvider"},{"p":"com.google.android.exoplayer2.source","l":"DefaultCompositeSequenceableLoaderFactory"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"DefaultContentMetadata"},{"p":"com.google.android.exoplayer2","l":"DefaultControlDispatcher"},{"p":"com.google.android.exoplayer2.source.dash","l":"DefaultDashChunkSource"},{"p":"com.google.android.exoplayer2.database","l":"DefaultDatabaseProvider"},{"p":"com.google.android.exoplayer2.upstream","l":"DefaultDataSource"},{"p":"com.google.android.exoplayer2.upstream","l":"DefaultDataSourceFactory"},{"p":"com.google.android.exoplayer2.offline","l":"DefaultDownloaderFactory"},{"p":"com.google.android.exoplayer2.offline","l":"DefaultDownloadIndex"},{"p":"com.google.android.exoplayer2.drm","l":"DefaultDrmSessionManager"},{"p":"com.google.android.exoplayer2.drm","l":"DefaultDrmSessionManagerProvider"},{"p":"com.google.android.exoplayer2.extractor","l":"DefaultExtractorInput"},{"p":"com.google.android.exoplayer2.extractor","l":"DefaultExtractorsFactory"},{"p":"com.google.android.exoplayer2.source.hls","l":"DefaultHlsDataSourceFactory"},{"p":"com.google.android.exoplayer2.source.hls","l":"DefaultHlsExtractorFactory"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"DefaultHlsPlaylistParserFactory"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"DefaultHlsPlaylistTracker"},{"p":"com.google.android.exoplayer2.upstream","l":"DefaultHttpDataSource"},{"p":"com.google.android.exoplayer2.upstream","l":"DefaultHttpDataSourceFactory"},{"p":"com.google.android.exoplayer2","l":"DefaultLivePlaybackSpeedControl"},{"p":"com.google.android.exoplayer2","l":"DefaultLoadControl"},{"p":"com.google.android.exoplayer2.upstream","l":"DefaultLoadErrorHandlingPolicy"},{"p":"com.google.android.exoplayer2.ui","l":"DefaultMediaDescriptionAdapter"},{"p":"com.google.android.exoplayer2.ext.cast","l":"DefaultMediaItemConverter"},{"p":"com.google.android.exoplayer2.ext.media2","l":"DefaultMediaItemConverter"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"MediaSessionConnector.DefaultMediaMetadataProvider"},{"p":"com.google.android.exoplayer2.source","l":"DefaultMediaSourceFactory"},{"p":"com.google.android.exoplayer2.analytics","l":"DefaultPlaybackSessionManager"},{"p":"com.google.android.exoplayer2","l":"DefaultRenderersFactory"},{"p":"com.google.android.exoplayer2.testutil","l":"DefaultRenderersFactoryAsserts"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","l":"DefaultRtpPayloadReaderFactory"},{"p":"com.google.android.exoplayer2.extractor","l":"BinarySearchSeeker.DefaultSeekTimestampConverter"},{"p":"com.google.android.exoplayer2.source","l":"ShuffleOrder.DefaultShuffleOrder"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","l":"DefaultSsChunkSource"},{"p":"com.google.android.exoplayer2.ui","l":"DefaultTimeBar"},{"p":"com.google.android.exoplayer2.ui","l":"DefaultTrackNameProvider"},{"p":"com.google.android.exoplayer2.trackselection","l":"DefaultTrackSelector"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"DefaultTsPayloadReaderFactory"},{"p":"com.google.android.exoplayer2.trackselection","l":"ExoTrackSelection.Definition"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsPlaylistParser.DeltaUpdateException"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"Descriptor"},{"p":"com.google.android.exoplayer2","l":"ExoPlayer.DeviceComponent"},{"p":"com.google.android.exoplayer2.device","l":"DeviceInfo"},{"p":"com.google.android.exoplayer2.device","l":"DeviceListener"},{"p":"com.google.android.exoplayer2.ui","l":"TrackSelectionDialogBuilder.DialogCallback"},{"p":"com.google.android.exoplayer2.ext.media2","l":"SessionCallbackBuilder.DisconnectedCallback"},{"p":"com.google.android.exoplayer2","l":"Player.DiscontinuityReason"},{"p":"com.google.android.exoplayer2.video","l":"DolbyVisionConfig"},{"p":"com.google.android.exoplayer2.offline","l":"Download"},{"p":"com.google.android.exoplayer2.testutil","l":"DownloadBuilder"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadCursor"},{"p":"com.google.android.exoplayer2.offline","l":"Downloader"},{"p":"com.google.android.exoplayer2.offline","l":"DownloaderFactory"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadException"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadHelper"},{"p":"com.google.android.exoplayer2.offline","l":"ActionFileUpgradeUtil.DownloadIdProvider"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadIndex"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadManager"},{"p":"com.google.android.exoplayer2.ui","l":"DownloadNotificationHelper"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadProgress"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadRequest"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadService"},{"p":"com.google.android.exoplayer2","l":"MediaItem.DrmConfiguration"},{"p":"com.google.android.exoplayer2.drm","l":"DrmInitData"},{"p":"com.google.android.exoplayer2.drm","l":"DrmSession"},{"p":"com.google.android.exoplayer2.drm","l":"DrmSessionEventListener"},{"p":"com.google.android.exoplayer2.drm","l":"DrmSession.DrmSessionException"},{"p":"com.google.android.exoplayer2.drm","l":"DrmSessionManager"},{"p":"com.google.android.exoplayer2.drm","l":"DrmSessionManagerProvider"},{"p":"com.google.android.exoplayer2.drm","l":"DrmSessionManager.DrmSessionReference"},{"p":"com.google.android.exoplayer2.drm","l":"DrmUtil"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"DtsReader"},{"p":"com.google.android.exoplayer2.audio","l":"DtsUtil"},{"p":"com.google.android.exoplayer2.upstream","l":"LoaderErrorThrower.Dummy"},{"p":"com.google.android.exoplayer2.upstream","l":"DummyDataSource"},{"p":"com.google.android.exoplayer2.drm","l":"DummyExoMediaDrm"},{"p":"com.google.android.exoplayer2.extractor","l":"DummyExtractorOutput"},{"p":"com.google.android.exoplayer2.testutil","l":"DummyMainThread"},{"p":"com.google.android.exoplayer2.video","l":"DummySurface"},{"p":"com.google.android.exoplayer2.extractor","l":"DummyTrackOutput"},{"p":"com.google.android.exoplayer2.testutil","l":"Dumper.Dumpable"},{"p":"com.google.android.exoplayer2.testutil","l":"DumpableFormat"},{"p":"com.google.android.exoplayer2.testutil","l":"Dumper"},{"p":"com.google.android.exoplayer2.testutil","l":"DumpFileAsserts"},{"p":"com.google.android.exoplayer2.text.dvb","l":"DvbDecoder"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"TsPayloadReader.DvbSubtitleInfo"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"DvbSubtitleReader"},{"p":"com.google.android.exoplayer2.extractor.mkv","l":"EbmlProcessor"},{"p":"com.google.android.exoplayer2.ui","l":"CaptionStyleCompat.EdgeType"},{"p":"com.google.android.exoplayer2.util","l":"EGLSurfaceTexture"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"ElementaryStreamReader"},{"p":"com.google.android.exoplayer2.extractor.mkv","l":"EbmlProcessor.ElementType"},{"p":"com.google.android.exoplayer2.source.chunk","l":"ChunkSampleStream.EmbeddedSampleStream"},{"p":"com.google.android.exoplayer2.testutil.truth","l":"SpannedSubject.EmphasizedText"},{"p":"com.google.android.exoplayer2.source","l":"EmptySampleStream"},{"p":"com.google.android.exoplayer2","l":"C.Encoding"},{"p":"com.google.android.exoplayer2.metadata","l":"Metadata.Entry"},{"p":"com.google.android.exoplayer2","l":"PlaybackException.ErrorCode"},{"p":"com.google.android.exoplayer2.util","l":"ErrorMessageProvider"},{"p":"com.google.android.exoplayer2.drm","l":"DrmUtil.ErrorSource"},{"p":"com.google.android.exoplayer2.drm","l":"ErrorStateDrmSession"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"TsPayloadReader.EsInfo"},{"p":"com.google.android.exoplayer2","l":"Player.Event"},{"p":"com.google.android.exoplayer2.metadata.scte35","l":"SpliceScheduleCommand.Event"},{"p":"com.google.android.exoplayer2.util","l":"ListenerSet.Event"},{"p":"com.google.android.exoplayer2.audio","l":"AudioRendererEventListener.EventDispatcher"},{"p":"com.google.android.exoplayer2.drm","l":"DrmSessionEventListener.EventDispatcher"},{"p":"com.google.android.exoplayer2.source","l":"MediaSourceEventListener.EventDispatcher"},{"p":"com.google.android.exoplayer2.upstream","l":"BandwidthMeter.EventListener.EventDispatcher"},{"p":"com.google.android.exoplayer2.video","l":"VideoRendererEventListener.EventDispatcher"},{"p":"com.google.android.exoplayer2.analytics","l":"AnalyticsListener.EventFlags"},{"p":"com.google.android.exoplayer2","l":"Player.EventListener"},{"p":"com.google.android.exoplayer2.source.ads","l":"AdsLoader.EventListener"},{"p":"com.google.android.exoplayer2.upstream","l":"BandwidthMeter.EventListener"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheDataSource.EventListener"},{"p":"com.google.android.exoplayer2.util","l":"EventLogger"},{"p":"com.google.android.exoplayer2.metadata.emsg","l":"EventMessage"},{"p":"com.google.android.exoplayer2.metadata.emsg","l":"EventMessageDecoder"},{"p":"com.google.android.exoplayer2.metadata.emsg","l":"EventMessageEncoder"},{"p":"com.google.android.exoplayer2","l":"Player.Events"},{"p":"com.google.android.exoplayer2.analytics","l":"AnalyticsListener.Events"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"EventStream"},{"p":"com.google.android.exoplayer2.analytics","l":"AnalyticsListener.EventTime"},{"p":"com.google.android.exoplayer2.analytics","l":"PlaybackStats.EventTimeAndException"},{"p":"com.google.android.exoplayer2.analytics","l":"PlaybackStats.EventTimeAndFormat"},{"p":"com.google.android.exoplayer2.analytics","l":"PlaybackStats.EventTimeAndPlaybackState"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.ExecuteRunnable"},{"p":"com.google.android.exoplayer2.database","l":"ExoDatabaseProvider"},{"p":"com.google.android.exoplayer2.testutil","l":"ExoHostedTest"},{"p":"com.google.android.exoplayer2.drm","l":"ExoMediaCrypto"},{"p":"com.google.android.exoplayer2.drm","l":"ExoMediaDrm"},{"p":"com.google.android.exoplayer2","l":"ExoPlaybackException"},{"p":"com.google.android.exoplayer2","l":"ExoPlayer"},{"p":"com.google.android.exoplayer2","l":"ExoPlayerLibraryInfo"},{"p":"com.google.android.exoplayer2.testutil","l":"ExoPlayerTestRunner"},{"p":"com.google.android.exoplayer2","l":"ExoTimeoutException"},{"p":"com.google.android.exoplayer2.trackselection","l":"ExoTrackSelection"},{"p":"com.google.android.exoplayer2","l":"DefaultRenderersFactory.ExtensionRendererMode"},{"p":"com.google.android.exoplayer2.extractor","l":"Extractor"},{"p":"com.google.android.exoplayer2.testutil","l":"ExtractorAsserts"},{"p":"com.google.android.exoplayer2.testutil","l":"ExtractorAsserts.ExtractorFactory"},{"p":"com.google.android.exoplayer2.extractor","l":"ExtractorInput"},{"p":"com.google.android.exoplayer2.extractor","l":"ExtractorOutput"},{"p":"com.google.android.exoplayer2.extractor","l":"ExtractorsFactory"},{"p":"com.google.android.exoplayer2.extractor","l":"ExtractorUtil"},{"p":"com.google.android.exoplayer2.ext.cronet","l":"CronetDataSource.Factory"},{"p":"com.google.android.exoplayer2.ext.okhttp","l":"OkHttpDataSource.Factory"},{"p":"com.google.android.exoplayer2.ext.rtmp","l":"RtmpDataSource.Factory"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"TsPayloadReader.Factory"},{"p":"com.google.android.exoplayer2.mediacodec","l":"MediaCodecAdapter.Factory"},{"p":"com.google.android.exoplayer2.mediacodec","l":"SynchronousMediaCodecAdapter.Factory"},{"p":"com.google.android.exoplayer2.source","l":"ProgressiveMediaExtractor.Factory"},{"p":"com.google.android.exoplayer2.source","l":"ProgressiveMediaSource.Factory"},{"p":"com.google.android.exoplayer2.source","l":"SilenceMediaSource.Factory"},{"p":"com.google.android.exoplayer2.source","l":"SingleSampleMediaSource.Factory"},{"p":"com.google.android.exoplayer2.source.chunk","l":"ChunkExtractor.Factory"},{"p":"com.google.android.exoplayer2.source.dash","l":"DashChunkSource.Factory"},{"p":"com.google.android.exoplayer2.source.dash","l":"DashMediaSource.Factory"},{"p":"com.google.android.exoplayer2.source.dash","l":"DefaultDashChunkSource.Factory"},{"p":"com.google.android.exoplayer2.source.hls","l":"HlsMediaSource.Factory"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsPlaylistTracker.Factory"},{"p":"com.google.android.exoplayer2.source.rtsp","l":"RtspMediaSource.Factory"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","l":"RtpPayloadReader.Factory"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","l":"DefaultSsChunkSource.Factory"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","l":"SsChunkSource.Factory"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","l":"SsMediaSource.Factory"},{"p":"com.google.android.exoplayer2.testutil","l":"FailOnCloseDataSink.Factory"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeAdaptiveDataSet.Factory"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeChunkSource.Factory"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeDataSource.Factory"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeTrackOutput.Factory"},{"p":"com.google.android.exoplayer2.trackselection","l":"AdaptiveTrackSelection.Factory"},{"p":"com.google.android.exoplayer2.trackselection","l":"ExoTrackSelection.Factory"},{"p":"com.google.android.exoplayer2.trackselection","l":"RandomTrackSelection.Factory"},{"p":"com.google.android.exoplayer2.upstream","l":"DataSink.Factory"},{"p":"com.google.android.exoplayer2.upstream","l":"DataSource.Factory"},{"p":"com.google.android.exoplayer2.upstream","l":"DefaultHttpDataSource.Factory"},{"p":"com.google.android.exoplayer2.upstream","l":"FileDataSource.Factory"},{"p":"com.google.android.exoplayer2.upstream","l":"HttpDataSource.Factory"},{"p":"com.google.android.exoplayer2.upstream","l":"ResolvingDataSource.Factory"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheDataSink.Factory"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheDataSource.Factory"},{"p":"com.google.android.exoplayer2.testutil","l":"FailOnCloseDataSink"},{"p":"com.google.android.exoplayer2.offline","l":"Download.FailureReason"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeAdaptiveDataSet"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeAdaptiveMediaPeriod"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeAdaptiveMediaSource"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeAudioRenderer"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeChunkSource"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeClock"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeDataSet.FakeData"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeDataSet"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeDataSource"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeExoMediaDrm"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeExtractorInput"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeExtractorOutput"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeMediaChunk"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeMediaChunkIterator"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeMediaClockRenderer"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeMediaPeriod"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeMediaSource"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeRenderer"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeSampleStream"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeSampleStream.FakeSampleStreamItem"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeShuffleOrder"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeTimeline"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeTrackOutput"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeTrackSelection"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeTrackSelector"},{"p":"com.google.android.exoplayer2.testutil","l":"DataSourceContractTest.FakeTransferListener"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeVideoRenderer"},{"p":"com.google.android.exoplayer2.upstream","l":"LoadErrorHandlingPolicy.FallbackOptions"},{"p":"com.google.android.exoplayer2.upstream","l":"LoadErrorHandlingPolicy.FallbackSelection"},{"p":"com.google.android.exoplayer2.upstream","l":"LoadErrorHandlingPolicy.FallbackType"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","l":"FfmpegAudioRenderer"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","l":"FfmpegDecoderException"},{"p":"com.google.android.exoplayer2.ext.ffmpeg","l":"FfmpegLibrary"},{"p":"com.google.android.exoplayer2","l":"PlaybackException.FieldNumber"},{"p":"com.google.android.exoplayer2.upstream","l":"FileDataSource"},{"p":"com.google.android.exoplayer2.upstream","l":"FileDataSource.FileDataSourceException"},{"p":"com.google.android.exoplayer2.upstream","l":"FileDataSourceFactory"},{"p":"com.google.android.exoplayer2.util","l":"FileTypes"},{"p":"com.google.android.exoplayer2.offline","l":"FilterableManifest"},{"p":"com.google.android.exoplayer2.testutil","l":"MediaPeriodAsserts.FilterableManifestMediaPeriodFactory"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"FilteringHlsPlaylistParserFactory"},{"p":"com.google.android.exoplayer2.offline","l":"FilteringManifestParser"},{"p":"com.google.android.exoplayer2.trackselection","l":"FixedTrackSelection"},{"p":"com.google.android.exoplayer2.util","l":"FlacConstants"},{"p":"com.google.android.exoplayer2.ext.flac","l":"FlacDecoder"},{"p":"com.google.android.exoplayer2.ext.flac","l":"FlacDecoderException"},{"p":"com.google.android.exoplayer2.ext.flac","l":"FlacExtractor"},{"p":"com.google.android.exoplayer2.extractor.flac","l":"FlacExtractor"},{"p":"com.google.android.exoplayer2.extractor","l":"FlacFrameReader"},{"p":"com.google.android.exoplayer2.ext.flac","l":"FlacLibrary"},{"p":"com.google.android.exoplayer2.extractor","l":"FlacMetadataReader"},{"p":"com.google.android.exoplayer2.extractor","l":"FlacSeekTableSeekMap"},{"p":"com.google.android.exoplayer2.extractor","l":"FlacStreamMetadata"},{"p":"com.google.android.exoplayer2.extractor","l":"FlacMetadataReader.FlacStreamMetadataHolder"},{"p":"com.google.android.exoplayer2.ext.flac","l":"FlacExtractor.Flags"},{"p":"com.google.android.exoplayer2.extractor.amr","l":"AmrExtractor.Flags"},{"p":"com.google.android.exoplayer2.extractor.flac","l":"FlacExtractor.Flags"},{"p":"com.google.android.exoplayer2.extractor.mkv","l":"MatroskaExtractor.Flags"},{"p":"com.google.android.exoplayer2.extractor.mp3","l":"Mp3Extractor.Flags"},{"p":"com.google.android.exoplayer2.extractor.mp4","l":"FragmentedMp4Extractor.Flags"},{"p":"com.google.android.exoplayer2.extractor.mp4","l":"Mp4Extractor.Flags"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"AdtsExtractor.Flags"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"DefaultTsPayloadReaderFactory.Flags"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"TsPayloadReader.Flags"},{"p":"com.google.android.exoplayer2.upstream","l":"DataSpec.Flags"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheDataSource.Flags"},{"p":"com.google.android.exoplayer2.util","l":"FlagSet"},{"p":"com.google.android.exoplayer2.extractor.flv","l":"FlvExtractor"},{"p":"com.google.android.exoplayer2","l":"MediaMetadata.FolderType"},{"p":"com.google.android.exoplayer2.text.webvtt","l":"WebvttCssStyle.FontSizeUnit"},{"p":"com.google.android.exoplayer2","l":"Format"},{"p":"com.google.android.exoplayer2","l":"FormatHolder"},{"p":"com.google.android.exoplayer2","l":"C.FormatSupport"},{"p":"com.google.android.exoplayer2","l":"RendererCapabilities.FormatSupport"},{"p":"com.google.android.exoplayer2.audio","l":"ForwardingAudioSink"},{"p":"com.google.android.exoplayer2.extractor","l":"ForwardingExtractorInput"},{"p":"com.google.android.exoplayer2","l":"ForwardingPlayer"},{"p":"com.google.android.exoplayer2.source","l":"ForwardingTimeline"},{"p":"com.google.android.exoplayer2.extractor.mp4","l":"FragmentedMp4Extractor"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"Id3Decoder.FramePredicate"},{"p":"com.google.android.exoplayer2.drm","l":"FrameworkMediaCrypto"},{"p":"com.google.android.exoplayer2.drm","l":"FrameworkMediaDrm"},{"p":"com.google.android.exoplayer2.extractor","l":"GaplessInfoHolder"},{"p":"com.google.android.exoplayer2.ext.av1","l":"Gav1Decoder"},{"p":"com.google.android.exoplayer2.ext.av1","l":"Gav1DecoderException"},{"p":"com.google.android.exoplayer2.ext.av1","l":"Gav1Library"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"GeobFrame"},{"p":"com.google.android.exoplayer2.util","l":"EGLSurfaceTexture.GlException"},{"p":"com.google.android.exoplayer2.util","l":"GlUtil"},{"p":"com.google.android.exoplayer2.ext.gvr","l":"GvrAudioProcessor"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"H262Reader"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"H263Reader"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"H264Reader"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"H265Reader"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeClock.HandlerMessage"},{"p":"com.google.android.exoplayer2.util","l":"HandlerWrapper"},{"p":"com.google.android.exoplayer2.audio","l":"MpegAudioUtil.Header"},{"p":"com.google.android.exoplayer2","l":"HeartRating"},{"p":"com.google.android.exoplayer2.video","l":"HevcConfig"},{"p":"com.google.android.exoplayer2.source.hls","l":"HlsDataSourceFactory"},{"p":"com.google.android.exoplayer2.source.hls.offline","l":"HlsDownloader"},{"p":"com.google.android.exoplayer2.source.hls","l":"HlsExtractorFactory"},{"p":"com.google.android.exoplayer2.source.hls","l":"HlsManifest"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsMasterPlaylist"},{"p":"com.google.android.exoplayer2.source.hls","l":"HlsMediaChunkExtractor"},{"p":"com.google.android.exoplayer2.source.hls","l":"HlsMediaPeriod"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsMediaPlaylist"},{"p":"com.google.android.exoplayer2.source.hls","l":"HlsMediaSource"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsPlaylist"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsPlaylistParser"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsPlaylistParserFactory"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsPlaylistTracker"},{"p":"com.google.android.exoplayer2.source.hls","l":"HlsTrackMetadataEntry"},{"p":"com.google.android.exoplayer2.text.span","l":"HorizontalTextInVerticalContextSpan"},{"p":"com.google.android.exoplayer2.testutil","l":"HostActivity"},{"p":"com.google.android.exoplayer2.testutil","l":"HostActivity.HostedTest"},{"p":"com.google.android.exoplayer2.upstream","l":"HttpDataSource"},{"p":"com.google.android.exoplayer2.upstream","l":"HttpDataSource.HttpDataSourceException"},{"p":"com.google.android.exoplayer2.testutil","l":"HttpDataSourceTestEnv"},{"p":"com.google.android.exoplayer2.drm","l":"HttpMediaDrmCallback"},{"p":"com.google.android.exoplayer2.upstream","l":"DataSpec.HttpMethod"},{"p":"com.google.android.exoplayer2.upstream","l":"HttpUtil"},{"p":"com.google.android.exoplayer2.metadata.icy","l":"IcyDecoder"},{"p":"com.google.android.exoplayer2.metadata.icy","l":"IcyHeaders"},{"p":"com.google.android.exoplayer2.metadata.icy","l":"IcyInfo"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"Id3Decoder"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"Id3Frame"},{"p":"com.google.android.exoplayer2.extractor","l":"Id3Peeker"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"Id3Reader"},{"p":"com.google.android.exoplayer2.source","l":"ClippingMediaSource.IllegalClippingException"},{"p":"com.google.android.exoplayer2.source","l":"MergingMediaSource.IllegalMergeException"},{"p":"com.google.android.exoplayer2","l":"IllegalSeekPositionException"},{"p":"com.google.android.exoplayer2.ext.ima","l":"ImaAdsLoader"},{"p":"com.google.android.exoplayer2.util","l":"NotificationUtil.Importance"},{"p":"com.google.android.exoplayer2.extractor","l":"IndexSeekMap"},{"p":"com.google.android.exoplayer2.util","l":"SntpClient.InitializationCallback"},{"p":"com.google.android.exoplayer2.source.chunk","l":"InitializationChunk"},{"p":"com.google.android.exoplayer2.audio","l":"AudioSink.InitializationException"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeMediaSource.InitialTimeline"},{"p":"com.google.android.exoplayer2.source.mediaparser","l":"InputReaderAdapterV30"},{"p":"com.google.android.exoplayer2.decoder","l":"DecoderInputBuffer.InsufficientCapacityException"},{"p":"com.google.android.exoplayer2.util","l":"IntArrayQueue"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"InternalFrame"},{"p":"com.google.android.exoplayer2.trackselection","l":"TrackSelector.InvalidationListener"},{"p":"com.google.android.exoplayer2.audio","l":"DefaultAudioSink.InvalidAudioTrackTimestampException"},{"p":"com.google.android.exoplayer2.upstream","l":"HttpDataSource.InvalidContentTypeException"},{"p":"com.google.android.exoplayer2.upstream","l":"HttpDataSource.InvalidResponseCodeException"},{"p":"com.google.android.exoplayer2.util","l":"ListenerSet.IterationFinishedEvent"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeAdaptiveDataSet.Iterator"},{"p":"com.google.android.exoplayer2.extractor.jpeg","l":"JpegExtractor"},{"p":"com.google.android.exoplayer2.drm","l":"ExoMediaDrm.KeyRequest"},{"p":"com.google.android.exoplayer2.drm","l":"KeysExpiredException"},{"p":"com.google.android.exoplayer2.drm","l":"ExoMediaDrm.KeyStatus"},{"p":"com.google.android.exoplayer2.text.span","l":"LanguageFeatureSpan"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"LatmReader"},{"p":"com.google.android.exoplayer2.ext.leanback","l":"LeanbackPlayerAdapter"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"LeastRecentlyUsedCacheEvictor"},{"p":"com.google.android.exoplayer2.ext.flac","l":"LibflacAudioRenderer"},{"p":"com.google.android.exoplayer2.ext.av1","l":"Libgav1VideoRenderer"},{"p":"com.google.android.exoplayer2.ext.opus","l":"LibopusAudioRenderer"},{"p":"com.google.android.exoplayer2.util","l":"LibraryLoader"},{"p":"com.google.android.exoplayer2.ext.vp9","l":"LibvpxVideoRenderer"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeExoMediaDrm.LicenseServer"},{"p":"com.google.android.exoplayer2.text","l":"Cue.LineType"},{"p":"com.google.android.exoplayer2","l":"Player.Listener"},{"p":"com.google.android.exoplayer2.analytics","l":"PlaybackSessionManager.Listener"},{"p":"com.google.android.exoplayer2.audio","l":"AudioCapabilitiesReceiver.Listener"},{"p":"com.google.android.exoplayer2.audio","l":"AudioSink.Listener"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadManager.Listener"},{"p":"com.google.android.exoplayer2.scheduler","l":"RequirementsWatcher.Listener"},{"p":"com.google.android.exoplayer2.transformer","l":"Transformer.Listener"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"Cache.Listener"},{"p":"com.google.android.exoplayer2.util","l":"NetworkTypeObserver.Listener"},{"p":"com.google.android.exoplayer2.util","l":"ListenerSet"},{"p":"com.google.android.exoplayer2","l":"MediaItem.LiveConfiguration"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadHelper.LiveContentUnsupportedException"},{"p":"com.google.android.exoplayer2","l":"LivePlaybackSpeedControl"},{"p":"com.google.android.exoplayer2.upstream","l":"Loader.Loadable"},{"p":"com.google.android.exoplayer2","l":"LoadControl"},{"p":"com.google.android.exoplayer2.upstream","l":"Loader"},{"p":"com.google.android.exoplayer2.upstream","l":"LoaderErrorThrower"},{"p":"com.google.android.exoplayer2.upstream","l":"Loader.LoadErrorAction"},{"p":"com.google.android.exoplayer2.upstream","l":"LoadErrorHandlingPolicy"},{"p":"com.google.android.exoplayer2.upstream","l":"LoadErrorHandlingPolicy.LoadErrorInfo"},{"p":"com.google.android.exoplayer2.source","l":"LoadEventInfo"},{"p":"com.google.android.exoplayer2.drm","l":"LocalMediaDrmCallback"},{"p":"com.google.android.exoplayer2.util","l":"Log"},{"p":"com.google.android.exoplayer2.util","l":"LongArray"},{"p":"com.google.android.exoplayer2.source","l":"LoopingMediaSource"},{"p":"com.google.android.exoplayer2.trackselection","l":"MappingTrackSelector.MappedTrackInfo"},{"p":"com.google.android.exoplayer2.trackselection","l":"MappingTrackSelector"},{"p":"com.google.android.exoplayer2.text.span","l":"TextEmphasisSpan.MarkFill"},{"p":"com.google.android.exoplayer2.text.span","l":"TextEmphasisSpan.MarkShape"},{"p":"com.google.android.exoplayer2.source","l":"MaskingMediaPeriod"},{"p":"com.google.android.exoplayer2.source","l":"MaskingMediaSource"},{"p":"com.google.android.exoplayer2.extractor.mkv","l":"MatroskaExtractor"},{"p":"com.google.android.exoplayer2.metadata.mp4","l":"MdtaMetadataEntry"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"MediaSessionConnector.MediaButtonEventHandler"},{"p":"com.google.android.exoplayer2.source.chunk","l":"MediaChunk"},{"p":"com.google.android.exoplayer2.source.chunk","l":"MediaChunkIterator"},{"p":"com.google.android.exoplayer2.util","l":"MediaClock"},{"p":"com.google.android.exoplayer2.mediacodec","l":"MediaCodecAdapter"},{"p":"com.google.android.exoplayer2.audio","l":"MediaCodecAudioRenderer"},{"p":"com.google.android.exoplayer2.mediacodec","l":"MediaCodecDecoderException"},{"p":"com.google.android.exoplayer2.mediacodec","l":"MediaCodecInfo"},{"p":"com.google.android.exoplayer2.mediacodec","l":"MediaCodecRenderer"},{"p":"com.google.android.exoplayer2.mediacodec","l":"MediaCodecSelector"},{"p":"com.google.android.exoplayer2.mediacodec","l":"MediaCodecUtil"},{"p":"com.google.android.exoplayer2.video","l":"MediaCodecVideoDecoderException"},{"p":"com.google.android.exoplayer2.video","l":"MediaCodecVideoRenderer"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerNotificationManager.MediaDescriptionAdapter"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"TimelineQueueEditor.MediaDescriptionConverter"},{"p":"com.google.android.exoplayer2.drm","l":"MediaDrmCallback"},{"p":"com.google.android.exoplayer2.drm","l":"MediaDrmCallbackException"},{"p":"com.google.android.exoplayer2.util","l":"MediaFormatUtil"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"TimelineQueueEditor.MediaIdEqualityChecker"},{"p":"com.google.android.exoplayer2.ext.media2","l":"SessionCallbackBuilder.MediaIdMediaItemProvider"},{"p":"com.google.android.exoplayer2","l":"MediaItem"},{"p":"com.google.android.exoplayer2.ext.cast","l":"MediaItemConverter"},{"p":"com.google.android.exoplayer2.ext.media2","l":"MediaItemConverter"},{"p":"com.google.android.exoplayer2.ext.media2","l":"SessionCallbackBuilder.MediaItemProvider"},{"p":"com.google.android.exoplayer2","l":"Player.MediaItemTransitionReason"},{"p":"com.google.android.exoplayer2.source","l":"MediaLoadData"},{"p":"com.google.android.exoplayer2","l":"MediaMetadata"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"MediaSessionConnector.MediaMetadataProvider"},{"p":"com.google.android.exoplayer2.source.chunk","l":"MediaParserChunkExtractor"},{"p":"com.google.android.exoplayer2.source","l":"MediaParserExtractorAdapter"},{"p":"com.google.android.exoplayer2.source.hls","l":"MediaParserHlsMediaChunkExtractor"},{"p":"com.google.android.exoplayer2.source.mediaparser","l":"MediaParserUtil"},{"p":"com.google.android.exoplayer2.source","l":"MediaPeriod"},{"p":"com.google.android.exoplayer2.testutil","l":"MediaPeriodAsserts"},{"p":"com.google.android.exoplayer2.source","l":"MediaPeriodId"},{"p":"com.google.android.exoplayer2.source","l":"MediaSource.MediaPeriodId"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"MediaSessionConnector"},{"p":"com.google.android.exoplayer2.source","l":"MediaSource"},{"p":"com.google.android.exoplayer2.source","l":"MediaSource.MediaSourceCaller"},{"p":"com.google.android.exoplayer2.source","l":"MediaSourceEventListener"},{"p":"com.google.android.exoplayer2.source","l":"MediaSourceFactory"},{"p":"com.google.android.exoplayer2.testutil","l":"MediaSourceTestRunner"},{"p":"com.google.android.exoplayer2.source","l":"MergingMediaSource"},{"p":"com.google.android.exoplayer2.util","l":"HandlerWrapper.Message"},{"p":"com.google.android.exoplayer2.metadata","l":"Metadata"},{"p":"com.google.android.exoplayer2","l":"ExoPlayer.MetadataComponent"},{"p":"com.google.android.exoplayer2.metadata","l":"MetadataDecoder"},{"p":"com.google.android.exoplayer2.metadata","l":"MetadataDecoderFactory"},{"p":"com.google.android.exoplayer2.metadata","l":"MetadataInputBuffer"},{"p":"com.google.android.exoplayer2.metadata","l":"MetadataOutput"},{"p":"com.google.android.exoplayer2.metadata","l":"MetadataRenderer"},{"p":"com.google.android.exoplayer2","l":"MetadataRetriever"},{"p":"com.google.android.exoplayer2.source.hls","l":"HlsMediaSource.MetadataType"},{"p":"com.google.android.exoplayer2.util","l":"MimeTypes"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","l":"SsManifestParser.MissingFieldException"},{"p":"com.google.android.exoplayer2.drm","l":"DefaultDrmSessionManager.MissingSchemeDataException"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"MlltFrame"},{"p":"com.google.android.exoplayer2.drm","l":"DefaultDrmSessionManager.Mode"},{"p":"com.google.android.exoplayer2.extractor","l":"VorbisUtil.Mode"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"TsExtractor.Mode"},{"p":"com.google.android.exoplayer2.metadata.mp4","l":"MotionPhotoMetadata"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.MoveMediaItem"},{"p":"com.google.android.exoplayer2.extractor.mp3","l":"Mp3Extractor"},{"p":"com.google.android.exoplayer2.extractor.mp4","l":"Mp4Extractor"},{"p":"com.google.android.exoplayer2.text.webvtt","l":"Mp4WebvttDecoder"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"MpegAudioReader"},{"p":"com.google.android.exoplayer2.audio","l":"MpegAudioUtil"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"SegmentBase.MultiSegmentBase"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"Representation.MultiSegmentRepresentation"},{"p":"com.google.android.exoplayer2.util","l":"NalUnitUtil"},{"p":"com.google.android.exoplayer2","l":"C.NetworkType"},{"p":"com.google.android.exoplayer2.util","l":"NetworkTypeObserver"},{"p":"com.google.android.exoplayer2.util","l":"NonNullApi"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"NoOpCacheEvictor"},{"p":"com.google.android.exoplayer2","l":"NoSampleRenderer"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerNotificationManager.NotificationListener"},{"p":"com.google.android.exoplayer2.util","l":"NotificationUtil"},{"p":"com.google.android.exoplayer2.testutil","l":"NoUidTimeline"},{"p":"com.google.android.exoplayer2.drm","l":"OfflineLicenseHelper"},{"p":"com.google.android.exoplayer2.audio","l":"DefaultAudioSink.OffloadMode"},{"p":"com.google.android.exoplayer2.extractor.ogg","l":"OggExtractor"},{"p":"com.google.android.exoplayer2.ext.okhttp","l":"OkHttpDataSource"},{"p":"com.google.android.exoplayer2.ext.okhttp","l":"OkHttpDataSourceFactory"},{"p":"com.google.android.exoplayer2.drm","l":"ExoMediaDrm.OnEventListener"},{"p":"com.google.android.exoplayer2.drm","l":"ExoMediaDrm.OnExpirationUpdateListener"},{"p":"com.google.android.exoplayer2.mediacodec","l":"MediaCodecAdapter.OnFrameRenderedListener"},{"p":"com.google.android.exoplayer2.ui","l":"StyledPlayerControlView.OnFullScreenModeChangedListener"},{"p":"com.google.android.exoplayer2.drm","l":"ExoMediaDrm.OnKeyStatusChangeListener"},{"p":"com.google.android.exoplayer2.ui","l":"TimeBar.OnScrubListener"},{"p":"com.google.android.exoplayer2.ext.cronet","l":"CronetDataSource.OpenException"},{"p":"com.google.android.exoplayer2.ext.opus","l":"OpusDecoder"},{"p":"com.google.android.exoplayer2.ext.opus","l":"OpusDecoderException"},{"p":"com.google.android.exoplayer2.ext.opus","l":"OpusLibrary"},{"p":"com.google.android.exoplayer2.audio","l":"OpusUtil"},{"p":"com.google.android.exoplayer2.trackselection","l":"DefaultTrackSelector.OtherTrackScore"},{"p":"com.google.android.exoplayer2.decoder","l":"OutputBuffer"},{"p":"com.google.android.exoplayer2.source.mediaparser","l":"OutputConsumerAdapterV30"},{"p":"com.google.android.exoplayer2.decoder","l":"OutputBuffer.Owner"},{"p":"com.google.android.exoplayer2.trackselection","l":"DefaultTrackSelector.Parameters"},{"p":"com.google.android.exoplayer2.trackselection","l":"DefaultTrackSelector.ParametersBuilder"},{"p":"com.google.android.exoplayer2.util","l":"ParsableBitArray"},{"p":"com.google.android.exoplayer2.util","l":"ParsableByteArray"},{"p":"com.google.android.exoplayer2.util","l":"ParsableNalUnitBitArray"},{"p":"com.google.android.exoplayer2.upstream","l":"ParsingLoadable.Parser"},{"p":"com.google.android.exoplayer2","l":"ParserException"},{"p":"com.google.android.exoplayer2.upstream","l":"ParsingLoadable"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsMediaPlaylist.Part"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"PassthroughSectionPayloadReader"},{"p":"com.google.android.exoplayer2","l":"C.PcmEncoding"},{"p":"com.google.android.exoplayer2","l":"PercentageRating"},{"p":"com.google.android.exoplayer2","l":"Timeline.Period"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"Period"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"PesReader"},{"p":"com.google.android.exoplayer2.text.pgs","l":"PgsDecoder"},{"p":"com.google.android.exoplayer2.metadata.flac","l":"PictureFrame"},{"p":"com.google.android.exoplayer2","l":"MediaMetadata.PictureType"},{"p":"com.google.android.exoplayer2.source","l":"MaskingMediaSource.PlaceholderTimeline"},{"p":"com.google.android.exoplayer2.scheduler","l":"PlatformScheduler"},{"p":"com.google.android.exoplayer2.scheduler","l":"PlatformScheduler.PlatformSchedulerService"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"MediaSessionConnector.PlaybackActions"},{"p":"com.google.android.exoplayer2","l":"PlaybackException"},{"p":"com.google.android.exoplayer2.robolectric","l":"PlaybackOutput"},{"p":"com.google.android.exoplayer2","l":"PlaybackParameters"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"MediaSessionConnector.PlaybackPreparer"},{"p":"com.google.android.exoplayer2","l":"MediaItem.PlaybackProperties"},{"p":"com.google.android.exoplayer2.analytics","l":"PlaybackSessionManager"},{"p":"com.google.android.exoplayer2.analytics","l":"PlaybackStats"},{"p":"com.google.android.exoplayer2.analytics","l":"PlaybackStatsListener"},{"p":"com.google.android.exoplayer2","l":"Player.PlaybackSuppressionReason"},{"p":"com.google.android.exoplayer2.device","l":"DeviceInfo.PlaybackType"},{"p":"com.google.android.exoplayer2","l":"Player"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerControlView"},{"p":"com.google.android.exoplayer2.source.dash","l":"PlayerEmsgHandler.PlayerEmsgCallback"},{"p":"com.google.android.exoplayer2.source.dash","l":"PlayerEmsgHandler"},{"p":"com.google.android.exoplayer2","l":"PlayerMessage"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerNotificationManager"},{"p":"com.google.android.exoplayer2.testutil","l":"ActionSchedule.PlayerRunnable"},{"p":"com.google.android.exoplayer2.testutil","l":"ActionSchedule.PlayerTarget"},{"p":"com.google.android.exoplayer2.source.dash","l":"PlayerEmsgHandler.PlayerTrackEmsgHandler"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerView"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsPlaylistTracker.PlaylistEventListener"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsPlaylistTracker.PlaylistResetException"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsPlaylistTracker.PlaylistStuckException"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsMediaPlaylist.PlaylistType"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.PlayUntilPosition"},{"p":"com.google.android.exoplayer2","l":"Player.PlayWhenReadyChangeReason"},{"p":"com.google.android.exoplayer2.text.span","l":"TextAnnotation.Position"},{"p":"com.google.android.exoplayer2.extractor","l":"PositionHolder"},{"p":"com.google.android.exoplayer2","l":"Player.PositionInfo"},{"p":"com.google.android.exoplayer2.ext.media2","l":"SessionCallbackBuilder.PostConnectCallback"},{"p":"com.google.android.exoplayer2.util","l":"NalUnitUtil.PpsData"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.Prepare"},{"p":"com.google.android.exoplayer2.source","l":"MaskingMediaPeriod.PrepareListener"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsPlaylistTracker.PrimaryPlaylistListener"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerNotificationManager.Priority"},{"p":"com.google.android.exoplayer2.upstream","l":"PriorityDataSource"},{"p":"com.google.android.exoplayer2.upstream","l":"PriorityDataSourceFactory"},{"p":"com.google.android.exoplayer2.util","l":"PriorityTaskManager"},{"p":"com.google.android.exoplayer2.util","l":"PriorityTaskManager.PriorityTooLowException"},{"p":"com.google.android.exoplayer2.metadata.scte35","l":"PrivateCommand"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"PrivFrame"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"ProgramInformation"},{"p":"com.google.android.exoplayer2.transformer","l":"ProgressHolder"},{"p":"com.google.android.exoplayer2.offline","l":"ProgressiveDownloader"},{"p":"com.google.android.exoplayer2.source","l":"ProgressiveMediaExtractor"},{"p":"com.google.android.exoplayer2.source","l":"ProgressiveMediaSource"},{"p":"com.google.android.exoplayer2.offline","l":"Downloader.ProgressListener"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"CacheWriter.ProgressListener"},{"p":"com.google.android.exoplayer2.transformer","l":"Transformer.ProgressState"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerControlView.ProgressUpdateListener"},{"p":"com.google.android.exoplayer2.ui","l":"StyledPlayerControlView.ProgressUpdateListener"},{"p":"com.google.android.exoplayer2","l":"C.Projection"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","l":"SsManifest.ProtectionElement"},{"p":"com.google.android.exoplayer2.drm","l":"ExoMediaDrm.Provider"},{"p":"com.google.android.exoplayer2.drm","l":"ExoMediaDrm.ProvisionRequest"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"PsExtractor"},{"p":"com.google.android.exoplayer2.extractor.mp4","l":"PsshAtomUtil"},{"p":"com.google.android.exoplayer2.ui","l":"AdOverlayInfo.Purpose"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"TimelineQueueEditor.QueueDataAdapter"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"MediaSessionConnector.QueueEditor"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"MediaSessionConnector.QueueNavigator"},{"p":"com.google.android.exoplayer2.robolectric","l":"RandomizedMp3Decoder"},{"p":"com.google.android.exoplayer2.trackselection","l":"RandomTrackSelection"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"RangedUri"},{"p":"com.google.android.exoplayer2","l":"Rating"},{"p":"com.google.android.exoplayer2.ext.media2","l":"SessionCallbackBuilder.RatingCallback"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"MediaSessionConnector.RatingCallback"},{"p":"com.google.android.exoplayer2.extractor.rawcc","l":"RawCcExtractor"},{"p":"com.google.android.exoplayer2.upstream","l":"RawResourceDataSource"},{"p":"com.google.android.exoplayer2.upstream","l":"RawResourceDataSource.RawResourceDataSourceException"},{"p":"com.google.android.exoplayer2.source","l":"SampleStream.ReadDataResult"},{"p":"com.google.android.exoplayer2.source","l":"SampleStream.ReadFlags"},{"p":"com.google.android.exoplayer2.extractor","l":"Extractor.ReadResult"},{"p":"com.google.android.exoplayer2.drm","l":"UnsupportedDrmException.Reason"},{"p":"com.google.android.exoplayer2.source","l":"ClippingMediaSource.IllegalClippingException.Reason"},{"p":"com.google.android.exoplayer2.source","l":"MergingMediaSource.IllegalMergeException.Reason"},{"p":"com.google.android.exoplayer2.testutil.truth","l":"SpannedSubject.RelativeSized"},{"p":"com.google.android.exoplayer2.source.chunk","l":"ChunkSampleStream.ReleaseCallback"},{"p":"com.google.android.exoplayer2.upstream","l":"Loader.ReleaseCallback"},{"p":"com.google.android.exoplayer2","l":"Timeline.RemotableTimeline"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.RemoveMediaItem"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.RemoveMediaItems"},{"p":"com.google.android.exoplayer2","l":"Renderer"},{"p":"com.google.android.exoplayer2","l":"RendererCapabilities"},{"p":"com.google.android.exoplayer2","l":"RendererConfiguration"},{"p":"com.google.android.exoplayer2","l":"RenderersFactory"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsMasterPlaylist.Rendition"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsMediaPlaylist.RenditionReport"},{"p":"com.google.android.exoplayer2","l":"Player.RepeatMode"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"RepeatModeActionProvider"},{"p":"com.google.android.exoplayer2.util","l":"RepeatModeUtil"},{"p":"com.google.android.exoplayer2.util","l":"RepeatModeUtil.RepeatToggleModes"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"Representation"},{"p":"com.google.android.exoplayer2.source.dash","l":"DefaultDashChunkSource.RepresentationHolder"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"DashManifestParser.RepresentationInfo"},{"p":"com.google.android.exoplayer2.source.dash","l":"DefaultDashChunkSource.RepresentationSegmentIterator"},{"p":"com.google.android.exoplayer2.upstream","l":"HttpDataSource.RequestProperties"},{"p":"com.google.android.exoplayer2.testutil","l":"CacheAsserts.RequestSet"},{"p":"com.google.android.exoplayer2.drm","l":"ExoMediaDrm.KeyRequest.RequestType"},{"p":"com.google.android.exoplayer2.scheduler","l":"Requirements.RequirementFlags"},{"p":"com.google.android.exoplayer2.scheduler","l":"Requirements"},{"p":"com.google.android.exoplayer2.scheduler","l":"RequirementsWatcher"},{"p":"com.google.android.exoplayer2.ui","l":"AspectRatioFrameLayout.ResizeMode"},{"p":"com.google.android.exoplayer2.upstream","l":"ResolvingDataSource.Resolver"},{"p":"com.google.android.exoplayer2.upstream","l":"ResolvingDataSource"},{"p":"com.google.android.exoplayer2.testutil","l":"WebServerDispatcher.Resource"},{"p":"com.google.android.exoplayer2.util","l":"ReusableBufferedOutputStream"},{"p":"com.google.android.exoplayer2.robolectric","l":"RobolectricUtil"},{"p":"com.google.android.exoplayer2","l":"C.RoleFlags"},{"p":"com.google.android.exoplayer2.ext.rtmp","l":"RtmpDataSource"},{"p":"com.google.android.exoplayer2.ext.rtmp","l":"RtmpDataSourceFactory"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","l":"RtpAc3Reader"},{"p":"com.google.android.exoplayer2.source.rtsp","l":"RtpPacket"},{"p":"com.google.android.exoplayer2.source.rtsp","l":"RtpPayloadFormat"},{"p":"com.google.android.exoplayer2.source.rtsp.reader","l":"RtpPayloadReader"},{"p":"com.google.android.exoplayer2.source.rtsp","l":"RtpUtils"},{"p":"com.google.android.exoplayer2.source.rtsp","l":"RtspMediaSource"},{"p":"com.google.android.exoplayer2.source.rtsp","l":"RtspMediaSource.RtspPlaybackException"},{"p":"com.google.android.exoplayer2.text.span","l":"RubySpan"},{"p":"com.google.android.exoplayer2.testutil.truth","l":"SpannedSubject.RubyText"},{"p":"com.google.android.exoplayer2.util","l":"RunnableFutureTask"},{"p":"com.google.android.exoplayer2.extractor","l":"TrackOutput.SampleDataPart"},{"p":"com.google.android.exoplayer2.extractor","l":"FlacFrameReader.SampleNumberHolder"},{"p":"com.google.android.exoplayer2.source","l":"SampleQueue"},{"p":"com.google.android.exoplayer2.source.hls","l":"SampleQueueMappingException"},{"p":"com.google.android.exoplayer2.source","l":"SampleStream"},{"p":"com.google.android.exoplayer2.scheduler","l":"Scheduler"},{"p":"com.google.android.exoplayer2.ext.workmanager","l":"WorkManagerScheduler.SchedulerWorker"},{"p":"com.google.android.exoplayer2.drm","l":"DrmInitData.SchemeData"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"SectionPayloadReader"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"SectionReader"},{"p":"com.google.android.exoplayer2.util","l":"EGLSurfaceTexture.SecureMode"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.Seek"},{"p":"com.google.android.exoplayer2.extractor","l":"SeekMap"},{"p":"com.google.android.exoplayer2.extractor","l":"BinarySearchSeeker.SeekOperationParams"},{"p":"com.google.android.exoplayer2","l":"SeekParameters"},{"p":"com.google.android.exoplayer2.extractor","l":"SeekPoint"},{"p":"com.google.android.exoplayer2.extractor","l":"SeekMap.SeekPoints"},{"p":"com.google.android.exoplayer2.extractor","l":"FlacStreamMetadata.SeekTable"},{"p":"com.google.android.exoplayer2.extractor","l":"BinarySearchSeeker.SeekTimestampConverter"},{"p":"com.google.android.exoplayer2.metadata.mp4","l":"SlowMotionData.Segment"},{"p":"com.google.android.exoplayer2.offline","l":"SegmentDownloader.Segment"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsMediaPlaylist.Segment"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeDataSet.FakeData.Segment"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"SegmentBase"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsMediaPlaylist.SegmentBase"},{"p":"com.google.android.exoplayer2.offline","l":"SegmentDownloader"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"SegmentBase.SegmentList"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"SegmentBase.SegmentTemplate"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"SegmentBase.SegmentTimelineElement"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"SeiReader"},{"p":"com.google.android.exoplayer2","l":"C.SelectionFlags"},{"p":"com.google.android.exoplayer2.trackselection","l":"DefaultTrackSelector.SelectionOverride"},{"p":"com.google.android.exoplayer2","l":"PlayerMessage.Sender"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.SendMessages"},{"p":"com.google.android.exoplayer2.source","l":"SequenceableLoader"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsMediaPlaylist.ServerControl"},{"p":"com.google.android.exoplayer2.source.ads","l":"ServerSideInsertedAdsMediaSource"},{"p":"com.google.android.exoplayer2.source.ads","l":"ServerSideInsertedAdsUtil"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"ServiceDescriptionElement"},{"p":"com.google.android.exoplayer2.ext.cast","l":"SessionAvailabilityListener"},{"p":"com.google.android.exoplayer2.ext.media2","l":"SessionCallbackBuilder"},{"p":"com.google.android.exoplayer2.ext.media2","l":"SessionPlayerConnector"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.SetAudioAttributes"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.SetMediaItems"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.SetMediaItemsResetPosition"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.SetPlaybackParameters"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.SetPlayWhenReady"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.SetRendererDisabled"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.SetRepeatMode"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.SetShuffleModeEnabled"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.SetShuffleOrder"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.SetVideoSurface"},{"p":"com.google.android.exoplayer2.robolectric","l":"ShadowMediaCodecConfig"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerView.ShowBuffering"},{"p":"com.google.android.exoplayer2.ui","l":"StyledPlayerView.ShowBuffering"},{"p":"com.google.android.exoplayer2.source","l":"ShuffleOrder"},{"p":"com.google.android.exoplayer2.source","l":"SilenceMediaSource"},{"p":"com.google.android.exoplayer2.audio","l":"SilenceSkippingAudioProcessor"},{"p":"com.google.android.exoplayer2.upstream.cache","l":"SimpleCache"},{"p":"com.google.android.exoplayer2.decoder","l":"SimpleDecoder"},{"p":"com.google.android.exoplayer2","l":"SimpleExoPlayer"},{"p":"com.google.android.exoplayer2.metadata","l":"SimpleMetadataDecoder"},{"p":"com.google.android.exoplayer2.decoder","l":"SimpleOutputBuffer"},{"p":"com.google.android.exoplayer2.text","l":"SimpleSubtitleDecoder"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeExtractorInput.SimulatedIOException"},{"p":"com.google.android.exoplayer2.testutil","l":"ExtractorAsserts.SimulationConfig"},{"p":"com.google.android.exoplayer2.source.ads","l":"SinglePeriodAdTimeline"},{"p":"com.google.android.exoplayer2.source","l":"SinglePeriodTimeline"},{"p":"com.google.android.exoplayer2.source.chunk","l":"SingleSampleMediaChunk"},{"p":"com.google.android.exoplayer2.source","l":"SingleSampleMediaSource"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"SegmentBase.SingleSegmentBase"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"Representation.SingleSegmentRepresentation"},{"p":"com.google.android.exoplayer2.audio","l":"AudioSink.SinkFormatSupport"},{"p":"com.google.android.exoplayer2.ext.media2","l":"SessionCallbackBuilder.SkipCallback"},{"p":"com.google.android.exoplayer2.util","l":"SlidingPercentile"},{"p":"com.google.android.exoplayer2.metadata.mp4","l":"SlowMotionData"},{"p":"com.google.android.exoplayer2.metadata.mp4","l":"SmtaMetadataEntry"},{"p":"com.google.android.exoplayer2.util","l":"SntpClient"},{"p":"com.google.android.exoplayer2.audio","l":"SonicAudioProcessor"},{"p":"com.google.android.exoplayer2.testutil.truth","l":"SpannedSubject"},{"p":"com.google.android.exoplayer2.text.span","l":"SpanUtil"},{"p":"com.google.android.exoplayer2.video.spherical","l":"SphericalGLSurfaceView"},{"p":"com.google.android.exoplayer2.metadata.scte35","l":"SpliceCommand"},{"p":"com.google.android.exoplayer2.metadata.scte35","l":"SpliceInfoDecoder"},{"p":"com.google.android.exoplayer2.metadata.scte35","l":"SpliceInsertCommand"},{"p":"com.google.android.exoplayer2.metadata.scte35","l":"SpliceNullCommand"},{"p":"com.google.android.exoplayer2.metadata.scte35","l":"SpliceScheduleCommand"},{"p":"com.google.android.exoplayer2.util","l":"NalUnitUtil.SpsData"},{"p":"com.google.android.exoplayer2.text.ssa","l":"SsaDecoder"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","l":"SsChunkSource"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.offline","l":"SsDownloader"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","l":"SsManifest"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","l":"SsManifestParser"},{"p":"com.google.android.exoplayer2.source.smoothstreaming","l":"SsMediaSource"},{"p":"com.google.android.exoplayer2.util","l":"StandaloneMediaClock"},{"p":"com.google.android.exoplayer2","l":"StarRating"},{"p":"com.google.android.exoplayer2.extractor.jpeg","l":"StartOffsetExtractorOutput"},{"p":"com.google.android.exoplayer2","l":"Player.State"},{"p":"com.google.android.exoplayer2","l":"Renderer.State"},{"p":"com.google.android.exoplayer2.drm","l":"DrmSession.State"},{"p":"com.google.android.exoplayer2.offline","l":"Download.State"},{"p":"com.google.android.exoplayer2.upstream","l":"StatsDataSource"},{"p":"com.google.android.exoplayer2","l":"C.StereoMode"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.Stop"},{"p":"com.google.android.exoplayer2.source.smoothstreaming.manifest","l":"SsManifest.StreamElement"},{"p":"com.google.android.exoplayer2.offline","l":"StreamKey"},{"p":"com.google.android.exoplayer2","l":"C.StreamType"},{"p":"com.google.android.exoplayer2.audio","l":"Ac3Util.SyncFrameInfo.StreamType"},{"p":"com.google.android.exoplayer2.testutil","l":"StubExoPlayer"},{"p":"com.google.android.exoplayer2.ui","l":"StyledPlayerControlView"},{"p":"com.google.android.exoplayer2.ui","l":"StyledPlayerView"},{"p":"com.google.android.exoplayer2.text.webvtt","l":"WebvttCssStyle.StyleFlags"},{"p":"com.google.android.exoplayer2.text.subrip","l":"SubripDecoder"},{"p":"com.google.android.exoplayer2","l":"MediaItem.Subtitle"},{"p":"com.google.android.exoplayer2.text","l":"Subtitle"},{"p":"com.google.android.exoplayer2.text","l":"SubtitleDecoder"},{"p":"com.google.android.exoplayer2.text","l":"SubtitleDecoderException"},{"p":"com.google.android.exoplayer2.text","l":"SubtitleDecoderFactory"},{"p":"com.google.android.exoplayer2.text","l":"SubtitleInputBuffer"},{"p":"com.google.android.exoplayer2.text","l":"SubtitleOutputBuffer"},{"p":"com.google.android.exoplayer2.ui","l":"SubtitleView"},{"p":"com.google.android.exoplayer2.audio","l":"Ac3Util.SyncFrameInfo"},{"p":"com.google.android.exoplayer2.audio","l":"Ac4Util.SyncFrameInfo"},{"p":"com.google.android.exoplayer2.mediacodec","l":"SynchronousMediaCodecAdapter"},{"p":"com.google.android.exoplayer2.util","l":"SystemClock"},{"p":"com.google.android.exoplayer2","l":"PlayerMessage.Target"},{"p":"com.google.android.exoplayer2.audio","l":"TeeAudioProcessor"},{"p":"com.google.android.exoplayer2.upstream","l":"TeeDataSource"},{"p":"com.google.android.exoplayer2.robolectric","l":"TestDownloadManagerListener"},{"p":"com.google.android.exoplayer2.testutil","l":"TestExoPlayerBuilder"},{"p":"com.google.android.exoplayer2.robolectric","l":"TestPlayerRunHelper"},{"p":"com.google.android.exoplayer2.testutil","l":"DataSourceContractTest.TestResource"},{"p":"com.google.android.exoplayer2.testutil","l":"DummyMainThread.TestRunnable"},{"p":"com.google.android.exoplayer2.testutil","l":"TestUtil"},{"p":"com.google.android.exoplayer2.text.span","l":"TextAnnotation"},{"p":"com.google.android.exoplayer2","l":"ExoPlayer.TextComponent"},{"p":"com.google.android.exoplayer2.text.span","l":"TextEmphasisSpan"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"TextInformationFrame"},{"p":"com.google.android.exoplayer2.text","l":"TextOutput"},{"p":"com.google.android.exoplayer2.text","l":"TextRenderer"},{"p":"com.google.android.exoplayer2.text","l":"Cue.TextSizeType"},{"p":"com.google.android.exoplayer2.trackselection","l":"DefaultTrackSelector.TextTrackScore"},{"p":"com.google.android.exoplayer2.util","l":"EGLSurfaceTexture.TextureImageListener"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.ThrowPlaybackException"},{"p":"com.google.android.exoplayer2","l":"ThumbRating"},{"p":"com.google.android.exoplayer2.ui","l":"TimeBar"},{"p":"com.google.android.exoplayer2.util","l":"TimedValueQueue"},{"p":"com.google.android.exoplayer2","l":"Timeline"},{"p":"com.google.android.exoplayer2.testutil","l":"TimelineAsserts"},{"p":"com.google.android.exoplayer2","l":"Player.TimelineChangeReason"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"TimelineQueueEditor"},{"p":"com.google.android.exoplayer2.ext.mediasession","l":"TimelineQueueNavigator"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeTimeline.TimelineWindowDefinition"},{"p":"com.google.android.exoplayer2","l":"ExoTimeoutException.TimeoutOperation"},{"p":"com.google.android.exoplayer2.metadata.scte35","l":"TimeSignalCommand"},{"p":"com.google.android.exoplayer2.util","l":"TimestampAdjuster"},{"p":"com.google.android.exoplayer2.source.hls","l":"TimestampAdjusterProvider"},{"p":"com.google.android.exoplayer2.extractor","l":"BinarySearchSeeker.TimestampSearchResult"},{"p":"com.google.android.exoplayer2.extractor","l":"BinarySearchSeeker.TimestampSeeker"},{"p":"com.google.android.exoplayer2.upstream","l":"TimeToFirstByteEstimator"},{"p":"com.google.android.exoplayer2.util","l":"TraceUtil"},{"p":"com.google.android.exoplayer2.extractor.mp4","l":"Track"},{"p":"com.google.android.exoplayer2.testutil","l":"FakeMediaPeriod.TrackDataFactory"},{"p":"com.google.android.exoplayer2.extractor.mp4","l":"TrackEncryptionBox"},{"p":"com.google.android.exoplayer2.source","l":"TrackGroup"},{"p":"com.google.android.exoplayer2.source","l":"TrackGroupArray"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"TsPayloadReader.TrackIdGenerator"},{"p":"com.google.android.exoplayer2.ui","l":"TrackNameProvider"},{"p":"com.google.android.exoplayer2.extractor","l":"TrackOutput"},{"p":"com.google.android.exoplayer2.source.chunk","l":"ChunkExtractor.TrackOutputProvider"},{"p":"com.google.android.exoplayer2.trackselection","l":"TrackSelection"},{"p":"com.google.android.exoplayer2.trackselection","l":"TrackSelectionArray"},{"p":"com.google.android.exoplayer2.ui","l":"TrackSelectionDialogBuilder"},{"p":"com.google.android.exoplayer2.ui","l":"TrackSelectionView.TrackSelectionListener"},{"p":"com.google.android.exoplayer2.trackselection","l":"TrackSelectionParameters"},{"p":"com.google.android.exoplayer2.trackselection","l":"TrackSelectionUtil"},{"p":"com.google.android.exoplayer2.ui","l":"TrackSelectionView"},{"p":"com.google.android.exoplayer2.trackselection","l":"TrackSelector"},{"p":"com.google.android.exoplayer2.trackselection","l":"TrackSelectorResult"},{"p":"com.google.android.exoplayer2.upstream","l":"TransferListener"},{"p":"com.google.android.exoplayer2.extractor.mp4","l":"Track.Transformation"},{"p":"com.google.android.exoplayer2.transformer","l":"Transformer"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"TsExtractor"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"TsPayloadReader"},{"p":"com.google.android.exoplayer2.extractor.ts","l":"TsUtil"},{"p":"com.google.android.exoplayer2.text.ttml","l":"TtmlDecoder"},{"p":"com.google.android.exoplayer2","l":"RendererCapabilities.TunnelingSupport"},{"p":"com.google.android.exoplayer2.text.tx3g","l":"Tx3gDecoder"},{"p":"com.google.android.exoplayer2","l":"ExoPlaybackException.Type"},{"p":"com.google.android.exoplayer2.source.ads","l":"AdsMediaSource.AdLoadException.Type"},{"p":"com.google.android.exoplayer2.upstream","l":"HttpDataSource.HttpDataSourceException.Type"},{"p":"com.google.android.exoplayer2.util","l":"FileTypes.Type"},{"p":"com.google.android.exoplayer2.testutil.truth","l":"SpannedSubject.Typefaced"},{"p":"com.google.android.exoplayer2.upstream","l":"UdpDataSource"},{"p":"com.google.android.exoplayer2.upstream","l":"UdpDataSource.UdpDataSourceException"},{"p":"com.google.android.exoplayer2.audio","l":"AudioSink.UnexpectedDiscontinuityException"},{"p":"com.google.android.exoplayer2.upstream","l":"Loader.UnexpectedLoaderException"},{"p":"com.google.android.exoplayer2.audio","l":"AudioProcessor.UnhandledAudioFormatException"},{"p":"com.google.android.exoplayer2.util","l":"GlUtil.Uniform"},{"p":"com.google.android.exoplayer2.util","l":"UnknownNull"},{"p":"com.google.android.exoplayer2.source","l":"UnrecognizedInputFormatException"},{"p":"com.google.android.exoplayer2.extractor","l":"SeekMap.Unseekable"},{"p":"com.google.android.exoplayer2.source","l":"ShuffleOrder.UnshuffledShuffleOrder"},{"p":"com.google.android.exoplayer2.drm","l":"UnsupportedDrmException"},{"p":"com.google.android.exoplayer2.drm","l":"UnsupportedMediaCrypto"},{"p":"com.google.android.exoplayer2.offline","l":"DownloadRequest.UnsupportedRequestException"},{"p":"com.google.android.exoplayer2.source","l":"SampleQueue.UpstreamFormatChangedListener"},{"p":"com.google.android.exoplayer2.util","l":"UriUtil"},{"p":"com.google.android.exoplayer2.metadata.id3","l":"UrlLinkFrame"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"UrlTemplate"},{"p":"com.google.android.exoplayer2.source.dash.manifest","l":"UtcTimingElement"},{"p":"com.google.android.exoplayer2.util","l":"Util"},{"p":"com.google.android.exoplayer2.source.hls.playlist","l":"HlsMasterPlaylist.Variant"},{"p":"com.google.android.exoplayer2.source.hls","l":"HlsTrackMetadataEntry.VariantInfo"},{"p":"com.google.android.exoplayer2.database","l":"VersionTable"},{"p":"com.google.android.exoplayer2.text","l":"Cue.VerticalType"},{"p":"com.google.android.exoplayer2","l":"ExoPlayer.VideoComponent"},{"p":"com.google.android.exoplayer2.video","l":"VideoDecoderGLSurfaceView"},{"p":"com.google.android.exoplayer2.video","l":"VideoDecoderInputBuffer"},{"p":"com.google.android.exoplayer2.video","l":"VideoDecoderOutputBuffer"},{"p":"com.google.android.exoplayer2.video","l":"VideoDecoderOutputBufferRenderer"},{"p":"com.google.android.exoplayer2.video","l":"VideoFrameMetadataListener"},{"p":"com.google.android.exoplayer2.video","l":"VideoFrameReleaseHelper"},{"p":"com.google.android.exoplayer2.video","l":"VideoListener"},{"p":"com.google.android.exoplayer2","l":"C.VideoOutputMode"},{"p":"com.google.android.exoplayer2.video","l":"VideoRendererEventListener"},{"p":"com.google.android.exoplayer2","l":"C.VideoScalingMode"},{"p":"com.google.android.exoplayer2","l":"Renderer.VideoScalingMode"},{"p":"com.google.android.exoplayer2.video","l":"VideoSize"},{"p":"com.google.android.exoplayer2.video.spherical","l":"SphericalGLSurfaceView.VideoSurfaceListener"},{"p":"com.google.android.exoplayer2.trackselection","l":"DefaultTrackSelector.VideoTrackScore"},{"p":"com.google.android.exoplayer2.ui","l":"SubtitleView.ViewType"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerNotificationManager.Visibility"},{"p":"com.google.android.exoplayer2.ui","l":"PlayerControlView.VisibilityListener"},{"p":"com.google.android.exoplayer2.ui","l":"StyledPlayerControlView.VisibilityListener"},{"p":"com.google.android.exoplayer2.extractor","l":"VorbisBitArray"},{"p":"com.google.android.exoplayer2.metadata.flac","l":"VorbisComment"},{"p":"com.google.android.exoplayer2.extractor","l":"VorbisUtil.VorbisIdHeader"},{"p":"com.google.android.exoplayer2.extractor","l":"VorbisUtil"},{"p":"com.google.android.exoplayer2.ext.vp9","l":"VpxDecoder"},{"p":"com.google.android.exoplayer2.ext.vp9","l":"VpxDecoderException"},{"p":"com.google.android.exoplayer2.ext.vp9","l":"VpxLibrary"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.WaitForIsLoading"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.WaitForMessage"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.WaitForPendingPlayerCommands"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.WaitForPlaybackState"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.WaitForPlayWhenReady"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.WaitForPositionDiscontinuity"},{"p":"com.google.android.exoplayer2.testutil","l":"Action.WaitForTimelineChanged"},{"p":"com.google.android.exoplayer2","l":"C.WakeMode"},{"p":"com.google.android.exoplayer2","l":"Renderer.WakeupListener"},{"p":"com.google.android.exoplayer2.extractor.wav","l":"WavExtractor"},{"p":"com.google.android.exoplayer2.audio","l":"TeeAudioProcessor.WavFileAudioBufferSink"},{"p":"com.google.android.exoplayer2.audio","l":"WavUtil"},{"p":"com.google.android.exoplayer2.testutil","l":"WebServerDispatcher"},{"p":"com.google.android.exoplayer2.text.webvtt","l":"WebvttCssStyle"},{"p":"com.google.android.exoplayer2.text.webvtt","l":"WebvttCueInfo"},{"p":"com.google.android.exoplayer2.text.webvtt","l":"WebvttCueParser"},{"p":"com.google.android.exoplayer2.text.webvtt","l":"WebvttDecoder"},{"p":"com.google.android.exoplayer2.source.hls","l":"WebvttExtractor"},{"p":"com.google.android.exoplayer2.text.webvtt","l":"WebvttParserUtil"},{"p":"com.google.android.exoplayer2.drm","l":"WidevineUtil"},{"p":"com.google.android.exoplayer2","l":"Timeline.Window"},{"p":"com.google.android.exoplayer2.testutil.truth","l":"SpannedSubject.WithSpanFlags"},{"p":"com.google.android.exoplayer2.ext.workmanager","l":"WorkManagerScheduler"},{"p":"com.google.android.exoplayer2.offline","l":"WritableDownloadIndex"},{"p":"com.google.android.exoplayer2.audio","l":"AudioSink.WriteException"},{"p":"com.google.android.exoplayer2.util","l":"XmlPullParserUtil"}] \ No newline at end of file diff --git a/docs/doc/reference/type-search-index.zip b/docs/doc/reference/type-search-index.zip index e905702b74e..b925ec2f1fb 100644 Binary files a/docs/doc/reference/type-search-index.zip and b/docs/doc/reference/type-search-index.zip differ diff --git a/docs/downloading-media.md b/docs/downloading-media.md index 61cf7718158..d696520a2f8 100644 --- a/docs/downloading-media.md +++ b/docs/downloading-media.md @@ -72,7 +72,7 @@ downloadCache = new SimpleCache( databaseProvider); // Create a factory for reading the data from the network. -dataSourceFactory = new DefaultHttpDataSourceFactory(); +dataSourceFactory = new DefaultHttpDataSource.Factory(); // Choose an executor for downloading data. Using Runnable::run will cause each download task to // download data on its own thread. Passing an executor that uses multiple threads will speed up diff --git a/docs/glossary.md b/docs/glossary.md index 3c1ac029d84..0e8b7d404b2 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -203,7 +203,7 @@ and the {% include figure.html url="/images/glossary-exoplayer-architecture.png" index="1" caption="ExoPlayer architecture overview" %} -{% include figure.html url="/images/glossary-renderering-architecture.png" index="1" caption="ExoPlayer rendering overview" %} +{% include figure.html url="/images/glossary-rendering-architecture.png" index="1" caption="ExoPlayer rendering overview" %} ###### BandwidthMeter diff --git a/docs/hello-world.md b/docs/hello-world.md index 2ef28ed3bb2..80dd0028257 100644 --- a/docs/hello-world.md +++ b/docs/hello-world.md @@ -50,6 +50,8 @@ implementation 'com.google.android.exoplayer:exoplayer-ui:2.X.X' ~~~ {: .language-gradle} +When depending on individual modules they must all be the same version. + The available library modules are listed below. Adding a dependency to the full ExoPlayer library is equivalent to adding dependencies on all of the library modules individually. diff --git a/docs/hls.md b/docs/hls.md index 9718306ac76..bc017ae74de 100644 --- a/docs/hls.md +++ b/docs/hls.md @@ -42,7 +42,7 @@ directly to the player instead of a `MediaItem`. ~~~ // Create a data source factory. -DataSource.Factory dataSourceFactory = new DefaultHttpDataSourceFactory(); +DataSource.Factory dataSourceFactory = new DefaultHttpDataSource.Factory(); // Create a HLS media source pointing to a playlist uri. HlsMediaSource hlsMediaSource = new HlsMediaSource.Factory(dataSourceFactory) diff --git a/docs/images/glossary-renderering-architecture.png b/docs/images/glossary-rendering-architecture.png similarity index 100% rename from docs/images/glossary-renderering-architecture.png rename to docs/images/glossary-rendering-architecture.png diff --git a/docs/listening-to-player-events.md b/docs/listening-to-player-events.md index 58dbb7fe75e..de23a32c2b6 100644 --- a/docs/listening-to-player-events.md +++ b/docs/listening-to-player-events.md @@ -67,35 +67,36 @@ public void onIsPlayingChanged(boolean isPlaying) { ### Playback errors ### Errors that cause playback to fail can be received by implementing -`onPlayerError(ExoPlaybackException error)` in a registered +`onPlayerError(PlaybackException error)` in a registered `Player.Listener`. When a failure occurs, this method will be called immediately before the playback state transitions to `Player.STATE_IDLE`. Failed or stopped playbacks can be retried by calling `ExoPlayer.retry`. -[`ExoPlaybackException`][] has a `type` field, as well as corresponding getter -methods that return cause exceptions providing more information about the -failure. The example below shows how to detect when a playback has failed due to -a HTTP networking issue. +Note that some [`Player`][] implementations pass instances of subclasses of +`PlaybackException` to provide additional information about the failure. For +example, [`ExoPlayer`][] passes [`ExoPlaybackException`][] which has `type`, +`rendererIndex` and other ExoPlayer-specific fields. + +The following example shows how to detect when a playback has failed due to an +HTTP networking issue: ~~~ @Override -public void onPlayerError(ExoPlaybackException error) { - if (error.type == ExoPlaybackException.TYPE_SOURCE) { - IOException cause = error.getSourceException(); - if (cause instanceof HttpDataSourceException) { - // An HTTP error occurred. - HttpDataSourceException httpError = (HttpDataSourceException) cause; - // This is the request for which the error occurred. - DataSpec requestDataSpec = httpError.dataSpec; - // It's possible to find out more about the error both by casting and by - // querying the cause. - if (httpError instanceof HttpDataSource.InvalidResponseCodeException) { - // Cast to InvalidResponseCodeException and retrieve the response code, - // message and headers. - } else { - // Try calling httpError.getCause() to retrieve the underlying cause, - // although note that it may be null. - } +public void onPlayerError(PlaybackException error) { + Throwable cause = error.getCause(); + if (cause instanceof HttpDataSourceException) { + // An HTTP error occurred. + HttpDataSourceException httpError = (HttpDataSourceException) cause; + // This is the request for which the error occurred. + DataSpec requestDataSpec = httpError.dataSpec; + // It's possible to find out more about the error both by casting and by + // querying the cause. + if (httpError instanceof HttpDataSource.InvalidResponseCodeException) { + // Cast to InvalidResponseCodeException and retrieve the response code, + // message and headers. + } else { + // Try calling httpError.getCause() to retrieve the underlying cause, + // although note that it may be null. } } } @@ -228,6 +229,8 @@ player [`Player.Listener`]: {{ site.exo_sdk }}/Player.Listener.html [Javadoc]: {{ site.exo_sdk }}/Player.Listener.html [`Individual callbacks vs onEvents`]: #individual-callbacks-vs-onevents +[`Player`]: {{ site.exo_sdk }}/Player.html +[`ExoPlayer`]: {{ site.exo_sdk }}/ExoPlayer.html [`ExoPlaybackException`]: {{ site.exo_sdk }}/ExoPlaybackException.html [log output]: event-logger.html [`Parameters`]: {{ site.exo_sdk }}/trackselection/DefaultTrackSelector.Parameters.html diff --git a/docs/live-streaming.md b/docs/live-streaming.md index 86ead16d517..4756296e2ba 100644 --- a/docs/live-streaming.md +++ b/docs/live-streaming.md @@ -130,19 +130,20 @@ Available configuration values are: If automatic playback speed adjustment is not desired, it can be disabled by setting `minPlaybackSpeed` and `maxPlaybackSpeed` to `1.0f`. -## BehindLiveWindowException ## +## BehindLiveWindowException and ERROR_CODE_BEHIND_LIVE_WINDOW ## The playback position may fall behind the live window, for example if the player is paused or buffering for a long enough period of time. If this happens then -playback will fail and a `BehindLiveWindowException` will be reported via +playback will fail and an exception with error code +`ERROR_CODE_BEHIND_LIVE_WINDOW` will be reported via `Player.Listener.onPlayerError`. Application code may wish to handle such errors by resuming playback at the default position. The [PlayerActivity][] of the demo app exemplifies this approach. ~~~ @Override -public void onPlayerError(ExoPlaybackException e) { - if (isBehindLiveWindow(e)) { +public void onPlayerError(PlaybackException error) { + if (eror.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) { // Re-initialize player at the current live window default position. player.seekToDefaultPosition(); player.prepare(); @@ -150,20 +151,6 @@ public void onPlayerError(ExoPlaybackException e) { // Handle other errors. } } - -private static boolean isBehindLiveWindow(ExoPlaybackException e) { - if (e.type != ExoPlaybackException.TYPE_SOURCE) { - return false; - } - Throwable cause = e.getSourceException(); - while (cause != null) { - if (cause instanceof BehindLiveWindowException) { - return true; - } - cause = cause.getCause(); - } - return false; -} ~~~ {: .language-java} diff --git a/docs/network-stacks.md b/docs/network-stacks.md new file mode 100644 index 00000000000..e0f21971769 --- /dev/null +++ b/docs/network-stacks.md @@ -0,0 +1,176 @@ +--- +title: Network stacks +--- + +ExoPlayer is commonly used for streaming media over the internet. It supports +multiple network stacks for making its underlying network requests. Your choice +of network stack can have a significant impact on streaming performance. + +This page outlines how to configure ExoPlayer to use your network stack of +choice, lists the available options, and provides some guidance on how to choose +a network stack for your application. + +## Configuring ExoPlayer to use a specific network stack ## + +ExoPlayer loads data through `DataSource` components, which it obtains from +`DataSource.Factory` instances that are injected from application code. + +If your application only needs to play http(s) content, selecting a network +stack is as simple as updating any `DataSource.Factory` instances that your +application injects to be instances of the `HttpDataSource.Factory` +that corresponds to the network stack you wish to use. If your application also +needs to play non-http(s) content such as local files, use + +~~~ +new DefaultDataSourceFactory( + ... + /* baseDataSourceFactory= */ new PreferredHttpDataSource.Factory(...)); +~~~ +{: .language-java} + +where `PreferredHttpDataSource.Factory` is the factory corresponding to your +preferred network stack. The `DefaultDataSourceFactory` layer adds in support +for non-http(s) sources such as local files. + +The example below shows how to build a `SimpleExoPlayer` that will use +the Cronet network stack and also support playback of non-http(s) content. + +~~~ +// Given a CronetEngine and Executor, build a CronetDataSource.Factory. +CronetDataSource.Factory cronetDataSourceFactory = + new CronetDataSource.Factory(cronetEngine, executor); + +// Wrap the CronetDataSource.Factory in a DefaultDataSourceFactory, which adds +// in support for requesting data from other sources (e.g., files, resources, +// etc). +DefaultDataSourceFactory dataSourceFactory = + new DefaultDataSourceFactory( + context, + /* baseDataSourceFactory= */ cronetDataSourceFactory); + +// Inject the DefaultDataSourceFactory when creating the player. +SimpleExoPlayer player = + new SimpleExoPlayer.Builder(context) + .setMediaSourceFactory(new DefaultMediaSourceFactory(dataSourceFactory)) + .build(); +~~~ +{: .language-java} + +## Supported network stacks ## + +ExoPlayer provides direct support for Cronet, OkHttp and Android's built-in +network stack. It can also be extended to support any other network stack that +works on Android. + +### Cronet ### + +[Cronet](https://developer.android.com/guide/topics/connectivity/cronet) is the +Chromium network stack made available to Android apps as a library. It takes +advantage of multiple technologies that reduce the latency and increase the +throughput of the network requests that your app needs to work, including those +made by ExoPlayer. It natively supports the HTTP, HTTP/2, and HTTP/3 over QUIC +protocols. Cronet is used by some of the world's biggest streaming applications, +including YouTube. + +ExoPlayer supports Cronet via its +[Cronet extension](https://github.com/google/ExoPlayer/tree/dev-v2/extensions/cronet). +Please see the extension's `README.md` for detailed instructions on how to use +it. Note that the Cronet extension is able to use three underlying Cronet +implementations: + +1. **Google Play Services:** We recommend using this implementation in most + cases, and falling back to Android's built-in network stack + (i.e., `DefaultHttpDataSource`) if Google Play Services is not available. +1. **Cronet Embedded:** May be a good choice if a large percentage of your users + are in markets where Google Play Services is not widely available, or if you + want to control the exact version of the Cronet implementation being used. The + major disadvantage of Cronet Embedded is that it adds approximately 8MB to + your application. +1. **Cronet Fallback:** The fallback implementation of Cronet implements + Cronet's API as a wrapper around Android's built-in network stack. It should + not be used with ExoPlayer, since using Android's built-in network stack + directly (i.e., by using `DefaultHttpDataSource`) is more efficient. + +### OkHttp ### + +[OkHttp](https://square.github.io/okhttp/) is another modern network stack that +is widely used by many popular Android applications. It supports HTTP and +HTTP/2, but does not yet support HTTP/3 over QUIC. + +ExoPlayer supports OkHttp via its +[OkHttp extension](https://github.com/google/ExoPlayer/tree/dev-v2/extensions/okhttp). +Please see the extension's `README.md` for detailed instructions on how to use +it. When using the OkHttp extension, the network stack is embedded within the +application. This is similar to Cronet Embedded, however OkHttp is significantly +smaller, adding under 1MB to your application. + +### Android's built-in network stack ### + +ExoPlayer supports use of Android's built-in network stack with +`DefaultHttpDataSource` and `DefaultHttpDataSource.Factory`, which are part of +the core ExoPlayer library. + +The exact network stack implementation depends on the software running on the +underlying device. On most devices (as of 2021) only HTTP is supported (i.e., +HTTP/2 and HTTP/3 over QUIC are not supported). + +### Other network stacks ### + +It's possible for applications to integrate other network stacks with ExoPlayer. +To do this, implement an `HttpDataSource` that wraps the network stack, +together with a corresponding `HttpDataSource.Factory`. ExoPlayer's Cronet and +OkHttp extensions are good examples of how to do this. + +When integrating with a pure Java network stack, it's a good idea to implement a +`DataSourceContractTest` to check that your `HttpDataSource` implementation +behaves correctly. `OkHttpDataSourceContractTest` in the OkHttp extension is a +good example of how to do this. + +## Choosing a network stack ## + +The table below outlines the pros and cons of the network stacks supported by +ExoPlayer. + +| Network stack | Protocols | APK size impact | Notes | +|:---|:--:|:--:|:---| +| Cronet (Google Play Services) | HTTP
      HTTP/2
      HTTP/3 over QUIC | Small
      (<100KB) | Requires Google Play Services. Cronet version updated automatically | +| Cronet (Embedded) | HTTP
      HTTP/2
      HTTP/3 over QUIC | Large
      (~8MB) | Cronet version controlled by app developer | +| Cronet (Fallback) | HTTP
      (varies by device) | Small
      (<100KB) | Not recommended for ExoPlayer | +| OkHttp | HTTP
      HTTP/2 | Small
      (<1MB) | Requires Kotlin runtime | +| Built-in network stack | HTTP
      (varies by device) | None | Implementation varies by device | + +The HTTP/2 and HTTP/3 over QUIC protocols can significantly improve media +streaming performance. In particular when streaming adaptive media distributed +via a content distribution network (CDN), there are cases for which use of these +protocols can allow CDNs to operate much more efficiently. For this reason, +Cronet's support for both HTTP/2 and HTTP/3 over QUIC (and OkHttp's support for +HTTP/2), is a major benefit compared to using Android's built-in network stack, +provided the servers on which the content is hosted also support these +protocols. + +When considering media streaming in isolation, we recommend use of Cronet +provided by Google Play Services, falling back to `DefaultHttpDataSource` if +Google Play Services is unavailable. This recommendation strikes a good balance +between enabling use of HTTP/2 and HTTP/3 over QUIC on most devices, and +avoiding a significant increase in APK size. There are exceptions to this +recommendation. For cases where Google Play Services is likely to be unavailable +on a significant fraction of devices that will be running your application, +using Cronet Embedded or OkHttp may be more appropriate. Use of the built-in +network stack may be acceptable if APK size is a critical concern, or if media +streaming is only a minor part of your application's functionality. + +Beyond just media, it's normally a good idea to choose a single network stack +for all of the networking performed by your application. This allows resources +(e.g., sockets) to be efficiently pooled and shared between ExoPlayer and other +application components. + +To assist with resource sharing, it's recommended to use a single `CronetEngine` +or `OkHttpClient` instance throughout your application, when using Cronet or +OkHttp respectively. +{:.info} + +Since your application will most likely need to perform networking not related +to media playback, your choice of network stack should ultimately factor in our +recommendations above for media streaming in isolation, the requirements of any +other components that perform networking, and their relative importance to your +application. diff --git a/docs/progressive.md b/docs/progressive.md index 91ef639f1cc..061e9cf5220 100644 --- a/docs/progressive.md +++ b/docs/progressive.md @@ -26,7 +26,7 @@ directly to the player instead of a `MediaItem`. ~~~ // Create a data source factory. -DataSource.Factory dataSourceFactory = new DefaultHttpDataSourceFactory(); +DataSource.Factory dataSourceFactory = new DefaultHttpDataSource.Factory(); // Create a progressive media source pointing to a stream uri. MediaSource mediaSource = new ProgressiveMediaSource.Factory(dataSourceFactory) .createMediaSource(MediaItem.fromUri(progressiveUri)); diff --git a/docs/smoothstreaming.md b/docs/smoothstreaming.md index fb6824cde42..67c04cbd49e 100644 --- a/docs/smoothstreaming.md +++ b/docs/smoothstreaming.md @@ -41,7 +41,7 @@ directly to the player instead of a `MediaItem`. ~~~ // Create a data source factory. -DataSource.Factory dataSourceFactory = new DefaultHttpDataSourceFactory(); +DataSource.Factory dataSourceFactory = new DefaultHttpDataSource.Factory(); // Create a SmoothStreaming media source pointing to a manifest uri. MediaSource mediaSource = new SsMediaSource.Factory(dataSourceFactory) diff --git a/extensions/av1/build.gradle b/extensions/av1/build.gradle index 95a953d1453..d7c6243c3bc 100644 --- a/extensions/av1/build.gradle +++ b/extensions/av1/build.gradle @@ -20,6 +20,7 @@ android { // Debug CMake build type causes video frames to drop, // so native library should always use Release build type. arguments "-DCMAKE_BUILD_TYPE=Release" + arguments "-DBUILD_TESTING=OFF" targets "gav1JNI" } } diff --git a/extensions/av1/src/main/java/com/google/android/exoplayer2/ext/av1/Gav1Decoder.java b/extensions/av1/src/main/java/com/google/android/exoplayer2/ext/av1/Gav1Decoder.java index 08d48e9699e..9e31bd6ef5f 100644 --- a/extensions/av1/src/main/java/com/google/android/exoplayer2/ext/av1/Gav1Decoder.java +++ b/extensions/av1/src/main/java/com/google/android/exoplayer2/ext/av1/Gav1Decoder.java @@ -34,11 +34,9 @@ public final class Gav1Decoder extends SimpleDecoder { - // LINT.IfChange private static final int GAV1_ERROR = 0; private static final int GAV1_OK = 1; private static final int GAV1_DECODE_ONLY = 2; - // LINT.ThenChange(../../../../../../../jni/gav1_jni.cc) private final long gav1DecoderContext; diff --git a/extensions/av1/src/main/jni/gav1_jni.cc b/extensions/av1/src/main/jni/gav1_jni.cc index 6b25798e3fb..d2f6532facd 100644 --- a/extensions/av1/src/main/jni/gav1_jni.cc +++ b/extensions/av1/src/main/jni/gav1_jni.cc @@ -69,22 +69,16 @@ const int kMaxPlanes = 3; // https://developer.android.com/reference/android/graphics/ImageFormat.html#YV12. const int kImageFormatYV12 = 0x32315659; -// LINT.IfChange // Output modes. const int kOutputModeYuv = 0; const int kOutputModeSurfaceYuv = 1; -// LINT.ThenChange(../../../../../library/common/src/main/java/com/google/android/exoplayer2/C.java) -// LINT.IfChange const int kColorSpaceUnknown = 0; -// LINT.ThenChange(../../../../../library/core/src/main/java/com/google/android/exoplayer2/video/VideoDecoderOutputBuffer.java) -// LINT.IfChange // Return codes for jni methods. const int kStatusError = 0; const int kStatusOk = 1; const int kStatusDecodeOnly = 2; -// LINT.ThenChange(../java/com/google/android/exoplayer2/ext/av1/Gav1Decoder.java) // Status codes specific to the JNI wrapper code. enum JniStatusCode { diff --git a/extensions/cast/build.gradle b/extensions/cast/build.gradle index 0efda30b937..49077b8580e 100644 --- a/extensions/cast/build.gradle +++ b/extensions/cast/build.gradle @@ -14,7 +14,7 @@ apply from: "$gradle.ext.exoplayerSettingsDir/common_library_config.gradle" dependencies { - api 'com.google.android.gms:play-services-cast-framework:19.0.0' + api 'com.google.android.gms:play-services-cast-framework:20.0.0' implementation 'androidx.annotation:annotation:' + androidxAnnotationVersion implementation project(modulePrefix + 'library-common') compileOnly 'org.checkerframework:checker-qual:' + checkerframeworkVersion diff --git a/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java b/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java index 60ba2e4a36d..e1e752ea762 100644 --- a/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java +++ b/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.ext.cast; +import static com.google.android.exoplayer2.util.Assertions.checkArgument; import static com.google.android.exoplayer2.util.Util.castNonNull; import static java.lang.Math.min; @@ -27,10 +28,10 @@ import androidx.annotation.VisibleForTesting; import com.google.android.exoplayer2.BasePlayer; import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlayerLibraryInfo; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.MediaMetadata; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Timeline; @@ -92,11 +93,12 @@ public final class CastPlayer extends BasePlayer { COMMAND_PLAY_PAUSE, COMMAND_PREPARE_STOP, COMMAND_SEEK_TO_DEFAULT_POSITION, - COMMAND_SEEK_TO_MEDIA_ITEM, + COMMAND_SEEK_TO_WINDOW, COMMAND_SET_REPEAT_MODE, COMMAND_GET_CURRENT_MEDIA_ITEM, - COMMAND_GET_MEDIA_ITEMS, + COMMAND_GET_TIMELINE, COMMAND_GET_MEDIA_ITEMS_METADATA, + COMMAND_SET_MEDIA_ITEMS_METADATA, COMMAND_CHANGE_MEDIA_ITEMS) .build(); @@ -113,6 +115,8 @@ public final class CastPlayer extends BasePlayer { private final CastContext castContext; private final MediaItemConverter mediaItemConverter; + private final long seekBackIncrementMs; + private final long seekForwardIncrementMs; // TODO: Allow custom implementations of CastTimelineTracker. private final CastTimelineTracker timelineTracker; private final Timeline.Period period; @@ -142,7 +146,13 @@ public final class CastPlayer extends BasePlayer { @Nullable private PositionInfo pendingMediaItemRemovalPosition; /** - * Creates a new cast player that uses a {@link DefaultMediaItemConverter}. + * Creates a new cast player. + * + *

      The returned player uses a {@link DefaultMediaItemConverter} and + * + *

      {@code mediaItemConverter} is set to a {@link DefaultMediaItemConverter}, {@code + * seekBackIncrementMs} is set to {@link C#DEFAULT_SEEK_BACK_INCREMENT_MS} and {@code + * seekForwardIncrementMs} is set to {@link C#DEFAULT_SEEK_FORWARD_INCREMENT_MS}. * * @param castContext The context from which the cast session is obtained. */ @@ -153,12 +163,40 @@ public CastPlayer(CastContext castContext) { /** * Creates a new cast player. * + *

      {@code seekBackIncrementMs} is set to {@link C#DEFAULT_SEEK_BACK_INCREMENT_MS} and {@code + * seekForwardIncrementMs} is set to {@link C#DEFAULT_SEEK_FORWARD_INCREMENT_MS}. + * * @param castContext The context from which the cast session is obtained. * @param mediaItemConverter The {@link MediaItemConverter} to use. */ public CastPlayer(CastContext castContext, MediaItemConverter mediaItemConverter) { + this( + castContext, + mediaItemConverter, + C.DEFAULT_SEEK_BACK_INCREMENT_MS, + C.DEFAULT_SEEK_FORWARD_INCREMENT_MS); + } + + /** + * Creates a new cast player. + * + * @param castContext The context from which the cast session is obtained. + * @param mediaItemConverter The {@link MediaItemConverter} to use. + * @param seekBackIncrementMs The {@link #seekBack()} increment, in milliseconds. + * @param seekForwardIncrementMs The {@link #seekForward()} increment, in milliseconds. + * @throws IllegalArgumentException If {@code seekBackIncrementMs} or {@code + * seekForwardIncrementMs} is non-positive. + */ + public CastPlayer( + CastContext castContext, + MediaItemConverter mediaItemConverter, + long seekBackIncrementMs, + long seekForwardIncrementMs) { + checkArgument(seekBackIncrementMs > 0 && seekForwardIncrementMs > 0); this.castContext = castContext; this.mediaItemConverter = mediaItemConverter; + this.seekBackIncrementMs = seekBackIncrementMs; + this.seekForwardIncrementMs = seekForwardIncrementMs; timelineTracker = new CastTimelineTracker(); period = new Timeline.Period(); statusListener = new StatusListener(); @@ -185,67 +223,6 @@ public CastPlayer(CastContext castContext, MediaItemConverter mediaItemConverter updateInternalStateAndNotifyIfChanged(); } - // Media Queue manipulation methods. - - /** @deprecated Use {@link #setMediaItems(List, int, long)} instead. */ - @Deprecated - @Nullable - public PendingResult loadItem(MediaQueueItem item, long positionMs) { - return setMediaItemsInternal( - new MediaQueueItem[] {item}, /* startWindowIndex= */ 0, positionMs, repeatMode.value); - } - - /** - * @deprecated Use {@link #setMediaItems(List, int, long)} and {@link #setRepeatMode(int)} - * instead. - */ - @Deprecated - @Nullable - public PendingResult loadItems( - MediaQueueItem[] items, int startIndex, long positionMs, @RepeatMode int repeatMode) { - return setMediaItemsInternal(items, startIndex, positionMs, repeatMode); - } - - /** @deprecated Use {@link #addMediaItems(List)} instead. */ - @Deprecated - @Nullable - public PendingResult addItems(MediaQueueItem... items) { - return addMediaItemsInternal(items, MediaQueueItem.INVALID_ITEM_ID); - } - - /** @deprecated Use {@link #addMediaItems(int, List)} instead. */ - @Deprecated - @Nullable - public PendingResult addItems(int periodId, MediaQueueItem... items) { - if (periodId == MediaQueueItem.INVALID_ITEM_ID - || currentTimeline.getIndexOfPeriod(periodId) != C.INDEX_UNSET) { - return addMediaItemsInternal(items, periodId); - } - return null; - } - - /** @deprecated Use {@link #removeMediaItem(int)} instead. */ - @Deprecated - @Nullable - public PendingResult removeItem(int periodId) { - if (currentTimeline.getIndexOfPeriod(periodId) != C.INDEX_UNSET) { - return removeMediaItemsInternal(new int[] {periodId}); - } - return null; - } - - /** @deprecated Use {@link #moveMediaItem(int, int)} instead. */ - @Deprecated - @Nullable - public PendingResult moveItem(int periodId, int newIndex) { - Assertions.checkArgument(newIndex >= 0 && newIndex < currentTimeline.getWindowCount()); - int fromIndex = currentTimeline.getIndexOfPeriod(periodId); - if (fromIndex != C.INDEX_UNSET && fromIndex != newIndex) { - return moveMediaItemsInternal(new int[] {periodId}, fromIndex, newIndex); - } - return null; - } - /** * Returns the item that corresponds to the period with the given id, or null if no media queue or * period with id {@code periodId} exist. @@ -391,7 +368,7 @@ public int getPlaybackSuppressionReason() { @Override @Nullable - public ExoPlaybackException getPlayerError() { + public PlaybackException getPlayerError() { return null; } @@ -471,6 +448,21 @@ public void seekTo(int windowIndex, long positionMs) { listeners.flushEvents(); } + @Override + public long getSeekBackIncrement() { + return seekBackIncrementMs; + } + + @Override + public long getSeekForwardIncrement() { + return seekForwardIncrementMs; + } + + @Override + public int getMaxSeekToPreviousPosition() { + return C.DEFAULT_MAX_SEEK_TO_PREVIOUS_POSITION_MS; + } + @Override public void setPlaybackParameters(PlaybackParameters playbackParameters) { // Unsupported by the RemoteMediaClient API. Do nothing. @@ -549,6 +541,7 @@ public TrackGroupArray getCurrentTrackGroups() { return currentTrackGroups; } + @Deprecated @Override public ImmutableList getCurrentStaticMetadata() { // CastPlayer does not currently support metadata. @@ -561,6 +554,18 @@ public MediaMetadata getMediaMetadata() { return MediaMetadata.EMPTY; } + @Override + public MediaMetadata getPlaylistMetadata() { + // CastPlayer does not currently support metadata. + return MediaMetadata.EMPTY; + } + + /** This method is not supported and does nothing. */ + @Override + public void setPlaylistMetadata(MediaMetadata mediaMetadata) { + // CastPlayer does not currently support metadata. + } + @Override public Timeline getCurrentTimeline() { return currentTimeline; @@ -864,11 +869,8 @@ private boolean updateTimelineAndNotifyIfChanged() { // Call onTimelineChanged. listeners.queueEvent( Player.EVENT_TIMELINE_CHANGED, - listener -> { - listener.onTimelineChanged( - timeline, /* manifest= */ null, Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE); - listener.onTimelineChanged(timeline, Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE); - }); + listener -> + listener.onTimelineChanged(timeline, Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE)); // Call onPositionDiscontinuity if required. Timeline currentTimeline = getCurrentTimeline(); diff --git a/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastTimeline.java b/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastTimeline.java index 1a03b779f60..584690cb300 100644 --- a/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastTimeline.java +++ b/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastTimeline.java @@ -24,16 +24,18 @@ import com.google.android.exoplayer2.Timeline; import java.util.Arrays; -/** - * A {@link Timeline} for Cast media queues. - */ +/** A {@link Timeline} for Cast media queues. */ /* package */ final class CastTimeline extends Timeline { /** Holds {@link Timeline} related data for a Cast media item. */ public static final class ItemData { /** Holds no media information. */ - public static final ItemData EMPTY = new ItemData(); + public static final ItemData EMPTY = + new ItemData( + /* durationUs= */ C.TIME_UNSET, + /* defaultPositionUs= */ C.TIME_UNSET, + /* isLive= */ false); /** The duration of the item in microseconds, or {@link C#TIME_UNSET} if unknown. */ public final long durationUs; @@ -44,13 +46,6 @@ public static final class ItemData { /** Whether the item is live content, or {@code false} if unknown. */ public final boolean isLive; - private ItemData() { - this( - /* durationUs= */ C.TIME_UNSET, - /* defaultPositionUs= */ C.TIME_UNSET, - /* isLive= */ false); - } - /** * Creates an instance. * @@ -190,5 +185,4 @@ public int hashCode() { result = 31 * result + Arrays.hashCode(isLive); return result; } - } diff --git a/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastUtils.java b/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastUtils.java index 4f3f52a5f9d..8ff4e37d43d 100644 --- a/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastUtils.java +++ b/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastUtils.java @@ -22,9 +22,7 @@ import com.google.android.gms.cast.MediaInfo; import com.google.android.gms.cast.MediaTrack; -/** - * Utility methods for ExoPlayer/Cast integration. - */ +/** Utility methods for ExoPlayer/Cast integration. */ /* package */ final class CastUtils { /** The duration returned by {@link MediaInfo#getStreamDuration()} for live streams. */ @@ -103,8 +101,8 @@ public static String getLogString(int statusCode) { } /** - * Creates a {@link Format} instance containing all information contained in the given - * {@link MediaTrack} object. + * Creates a {@link Format} instance containing all information contained in the given {@link + * MediaTrack} object. * * @param mediaTrack The {@link MediaTrack}. * @return The equivalent {@link Format}. @@ -118,5 +116,4 @@ public static Format mediaTrackToFormat(MediaTrack mediaTrack) { } private CastUtils() {} - } diff --git a/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/DefaultCastOptionsProvider.java b/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/DefaultCastOptionsProvider.java index 69702ea2866..4131f7a6410 100644 --- a/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/DefaultCastOptionsProvider.java +++ b/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/DefaultCastOptionsProvider.java @@ -37,6 +37,8 @@ public final class DefaultCastOptionsProvider implements OptionsProvider { @Override public CastOptions getCastOptions(Context context) { return new CastOptions.Builder() + .setResumeSavedSession(false) + .setEnableReconnectionService(false) .setReceiverApplicationId(APP_ID_DEFAULT_RECEIVER_WITH_DRM) .setStopReceiverApplicationWhenEndingSession(true) .build(); @@ -46,5 +48,4 @@ public CastOptions getCastOptions(Context context) { public List getAdditionalSessionProviders(Context context) { return Collections.emptyList(); } - } diff --git a/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/DefaultMediaItemConverter.java b/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/DefaultMediaItemConverter.java index 5fbabb807e1..09bf339f0e2 100644 --- a/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/DefaultMediaItemConverter.java +++ b/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/DefaultMediaItemConverter.java @@ -43,29 +43,29 @@ public final class DefaultMediaItemConverter implements MediaItemConverter { private static final String KEY_REQUEST_HEADERS = "requestHeaders"; @Override - public MediaItem toMediaItem(MediaQueueItem item) { + public MediaItem toMediaItem(MediaQueueItem mediaQueueItem) { // `item` came from `toMediaQueueItem()` so the custom JSON data must be set. - MediaInfo mediaInfo = item.getMedia(); + MediaInfo mediaInfo = mediaQueueItem.getMedia(); Assertions.checkNotNull(mediaInfo); return getMediaItem(Assertions.checkNotNull(mediaInfo.getCustomData())); } @Override - public MediaQueueItem toMediaQueueItem(MediaItem item) { - Assertions.checkNotNull(item.playbackProperties); - if (item.playbackProperties.mimeType == null) { + public MediaQueueItem toMediaQueueItem(MediaItem mediaItem) { + Assertions.checkNotNull(mediaItem.playbackProperties); + if (mediaItem.playbackProperties.mimeType == null) { throw new IllegalArgumentException("The item must specify its mimeType"); } MediaMetadata metadata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE); - if (item.mediaMetadata.title != null) { - metadata.putString(MediaMetadata.KEY_TITLE, item.mediaMetadata.title.toString()); + if (mediaItem.mediaMetadata.title != null) { + metadata.putString(MediaMetadata.KEY_TITLE, mediaItem.mediaMetadata.title.toString()); } MediaInfo mediaInfo = - new MediaInfo.Builder(item.playbackProperties.uri.toString()) + new MediaInfo.Builder(mediaItem.playbackProperties.uri.toString()) .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED) - .setContentType(item.playbackProperties.mimeType) + .setContentType(mediaItem.playbackProperties.mimeType) .setMetadata(metadata) - .setCustomData(getCustomData(item)) + .setCustomData(getCustomData(mediaItem)) .build(); return new MediaQueueItem.Builder(mediaInfo).build(); } diff --git a/extensions/cast/src/test/java/com/google/android/exoplayer2/ext/cast/CastPlayerTest.java b/extensions/cast/src/test/java/com/google/android/exoplayer2/ext/cast/CastPlayerTest.java index 0a687f50b4e..58c6eaf10d4 100644 --- a/extensions/cast/src/test/java/com/google/android/exoplayer2/ext/cast/CastPlayerTest.java +++ b/extensions/cast/src/test/java/com/google/android/exoplayer2/ext/cast/CastPlayerTest.java @@ -20,18 +20,23 @@ import static com.google.android.exoplayer2.Player.COMMAND_GET_AUDIO_ATTRIBUTES; import static com.google.android.exoplayer2.Player.COMMAND_GET_CURRENT_MEDIA_ITEM; import static com.google.android.exoplayer2.Player.COMMAND_GET_DEVICE_VOLUME; -import static com.google.android.exoplayer2.Player.COMMAND_GET_MEDIA_ITEMS; import static com.google.android.exoplayer2.Player.COMMAND_GET_MEDIA_ITEMS_METADATA; import static com.google.android.exoplayer2.Player.COMMAND_GET_TEXT; +import static com.google.android.exoplayer2.Player.COMMAND_GET_TIMELINE; import static com.google.android.exoplayer2.Player.COMMAND_GET_VOLUME; import static com.google.android.exoplayer2.Player.COMMAND_PLAY_PAUSE; import static com.google.android.exoplayer2.Player.COMMAND_PREPARE_STOP; -import static com.google.android.exoplayer2.Player.COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_BACK; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_FORWARD; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_IN_CURRENT_WINDOW; import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_DEFAULT_POSITION; -import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_MEDIA_ITEM; -import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM; -import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_NEXT; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_NEXT_WINDOW; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_PREVIOUS; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_PREVIOUS_WINDOW; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_WINDOW; import static com.google.android.exoplayer2.Player.COMMAND_SET_DEVICE_VOLUME; +import static com.google.android.exoplayer2.Player.COMMAND_SET_MEDIA_ITEMS_METADATA; import static com.google.android.exoplayer2.Player.COMMAND_SET_REPEAT_MODE; import static com.google.android.exoplayer2.Player.COMMAND_SET_SHUFFLE_MODE; import static com.google.android.exoplayer2.Player.COMMAND_SET_SPEED_AND_PITCH; @@ -1099,6 +1104,98 @@ public void autoTransition_notifiesPositionDiscontinuity() { inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt()); } + @Test + @SuppressWarnings("deprecation") // Mocks deprecated method used by the CastPlayer. + public void seekBack_notifiesPositionDiscontinuity() { + when(mockRemoteMediaClient.seek(anyLong())).thenReturn(mockPendingResult); + int[] mediaQueueItemIds = new int[] {1}; + List mediaItems = createMediaItems(mediaQueueItemIds); + int currentItemId = 1; + int[] streamTypes = new int[] {MediaInfo.STREAM_TYPE_BUFFERED}; + long[] durationsMs = new long[] {3 * C.DEFAULT_SEEK_BACK_INCREMENT_MS}; + long positionMs = 2 * C.DEFAULT_SEEK_BACK_INCREMENT_MS; + + castPlayer.addMediaItems(mediaItems); + updateTimeLine( + mediaItems, mediaQueueItemIds, currentItemId, streamTypes, durationsMs, positionMs); + castPlayer.seekBack(); + + Player.PositionInfo oldPosition = + new Player.PositionInfo( + /* windowUid= */ 1, + /* windowIndex= */ 0, + /* periodUid= */ 1, + /* periodIndex= */ 0, + /* positionMs= */ 2 * C.DEFAULT_SEEK_BACK_INCREMENT_MS, + /* contentPositionMs= */ 2 * C.DEFAULT_SEEK_BACK_INCREMENT_MS, + /* adGroupIndex= */ C.INDEX_UNSET, + /* adIndexInAdGroup= */ C.INDEX_UNSET); + Player.PositionInfo newPosition = + new Player.PositionInfo( + /* windowUid= */ 1, + /* windowIndex= */ 0, + /* periodUid= */ 1, + /* periodIndex= */ 0, + /* positionMs= */ C.DEFAULT_SEEK_BACK_INCREMENT_MS, + /* contentPositionMs= */ C.DEFAULT_SEEK_BACK_INCREMENT_MS, + /* adGroupIndex= */ C.INDEX_UNSET, + /* adIndexInAdGroup= */ C.INDEX_UNSET); + InOrder inOrder = Mockito.inOrder(mockListener); + inOrder.verify(mockListener).onPositionDiscontinuity(eq(Player.DISCONTINUITY_REASON_SEEK)); + inOrder + .verify(mockListener) + .onPositionDiscontinuity( + eq(oldPosition), eq(newPosition), eq(Player.DISCONTINUITY_REASON_SEEK)); + inOrder.verify(mockListener, never()).onPositionDiscontinuity(anyInt()); + inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt()); + } + + @Test + @SuppressWarnings("deprecation") // Mocks deprecated method used by the CastPlayer. + public void seekForward_notifiesPositionDiscontinuity() { + when(mockRemoteMediaClient.seek(anyLong())).thenReturn(mockPendingResult); + int[] mediaQueueItemIds = new int[] {1}; + List mediaItems = createMediaItems(mediaQueueItemIds); + int currentItemId = 1; + int[] streamTypes = new int[] {MediaInfo.STREAM_TYPE_BUFFERED}; + long[] durationsMs = new long[] {2 * C.DEFAULT_SEEK_FORWARD_INCREMENT_MS}; + long positionMs = 0; + + castPlayer.addMediaItems(mediaItems); + updateTimeLine( + mediaItems, mediaQueueItemIds, currentItemId, streamTypes, durationsMs, positionMs); + castPlayer.seekForward(); + + Player.PositionInfo oldPosition = + new Player.PositionInfo( + /* windowUid= */ 1, + /* windowIndex= */ 0, + /* periodUid= */ 1, + /* periodIndex= */ 0, + /* positionMs= */ 0, + /* contentPositionMs= */ 0, + /* adGroupIndex= */ C.INDEX_UNSET, + /* adIndexInAdGroup= */ C.INDEX_UNSET); + Player.PositionInfo newPosition = + new Player.PositionInfo( + /* windowUid= */ 1, + /* windowIndex= */ 0, + /* periodUid= */ 1, + /* periodIndex= */ 0, + /* positionMs= */ C.DEFAULT_SEEK_FORWARD_INCREMENT_MS, + /* contentPositionMs= */ C.DEFAULT_SEEK_FORWARD_INCREMENT_MS, + /* adGroupIndex= */ C.INDEX_UNSET, + /* adIndexInAdGroup= */ C.INDEX_UNSET); + InOrder inOrder = Mockito.inOrder(mockListener); + inOrder.verify(mockListener).onPositionDiscontinuity(eq(Player.DISCONTINUITY_REASON_SEEK)); + inOrder + .verify(mockListener) + .onPositionDiscontinuity( + eq(oldPosition), eq(newPosition), eq(Player.DISCONTINUITY_REASON_SEEK)); + inOrder.verify(mockListener, never()).onPositionDiscontinuity(anyInt()); + inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt()); + } + @Test public void isCommandAvailable_isTrueForAvailableCommands() { int[] mediaQueueItemIds = new int[] {1, 2}; @@ -1110,16 +1207,21 @@ public void isCommandAvailable_isTrueForAvailableCommands() { assertThat(castPlayer.isCommandAvailable(COMMAND_PLAY_PAUSE)).isTrue(); assertThat(castPlayer.isCommandAvailable(COMMAND_PREPARE_STOP)).isTrue(); assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_TO_DEFAULT_POSITION)).isTrue(); - assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM)).isTrue(); - assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM)).isTrue(); - assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM)).isFalse(); - assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_TO_MEDIA_ITEM)).isTrue(); + assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_WINDOW)).isTrue(); + assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS_WINDOW)).isFalse(); + assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS)).isTrue(); + assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_TO_NEXT_WINDOW)).isTrue(); + assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_TO_NEXT)).isTrue(); + assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_TO_WINDOW)).isTrue(); + assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_BACK)).isTrue(); + assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_FORWARD)).isTrue(); assertThat(castPlayer.isCommandAvailable(COMMAND_SET_SPEED_AND_PITCH)).isFalse(); assertThat(castPlayer.isCommandAvailable(COMMAND_SET_SHUFFLE_MODE)).isFalse(); assertThat(castPlayer.isCommandAvailable(COMMAND_SET_REPEAT_MODE)).isTrue(); assertThat(castPlayer.isCommandAvailable(COMMAND_GET_CURRENT_MEDIA_ITEM)).isTrue(); - assertThat(castPlayer.isCommandAvailable(COMMAND_GET_MEDIA_ITEMS)).isTrue(); + assertThat(castPlayer.isCommandAvailable(COMMAND_GET_TIMELINE)).isTrue(); assertThat(castPlayer.isCommandAvailable(COMMAND_GET_MEDIA_ITEMS_METADATA)).isTrue(); + assertThat(castPlayer.isCommandAvailable(COMMAND_SET_MEDIA_ITEMS_METADATA)).isTrue(); assertThat(castPlayer.isCommandAvailable(COMMAND_CHANGE_MEDIA_ITEMS)).isTrue(); assertThat(castPlayer.isCommandAvailable(COMMAND_GET_AUDIO_ATTRIBUTES)).isFalse(); assertThat(castPlayer.isCommandAvailable(COMMAND_GET_VOLUME)).isFalse(); @@ -1132,7 +1234,69 @@ public void isCommandAvailable_isTrueForAvailableCommands() { } @Test - public void isCommandAvailable_duringUnseekableItem_isFalseForSeekInCurrent() { + public void isCommandAvailable_duringUnseekableItem_isFalseForSeekInCurrentCommands() { + MediaItem mediaItem = createMediaItem(/* mediaQueueItemId= */ 1); + List mediaItems = ImmutableList.of(mediaItem); + int[] mediaQueueItemIds = new int[] {1}; + int[] streamTypes = new int[] {MediaInfo.STREAM_TYPE_LIVE}; + long[] durationsMs = new long[] {C.TIME_UNSET}; + + castPlayer.addMediaItem(mediaItem); + updateTimeLine( + mediaItems, + mediaQueueItemIds, + /* currentItemId= */ 1, + streamTypes, + durationsMs, + /* positionMs= */ C.TIME_UNSET); + + assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_WINDOW)).isFalse(); + assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_BACK)).isFalse(); + assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_FORWARD)).isFalse(); + } + + @Test + public void isCommandAvailable_duringUnseekableLiveItem_isFalseForSeekToPrevious() { + MediaItem mediaItem = createMediaItem(/* mediaQueueItemId= */ 1); + List mediaItems = ImmutableList.of(mediaItem); + int[] mediaQueueItemIds = new int[] {1}; + int[] streamTypes = new int[] {MediaInfo.STREAM_TYPE_LIVE}; + long[] durationsMs = new long[] {C.TIME_UNSET}; + + castPlayer.addMediaItem(mediaItem); + updateTimeLine( + mediaItems, + mediaQueueItemIds, + /* currentItemId= */ 1, + streamTypes, + durationsMs, + /* positionMs= */ C.TIME_UNSET); + + assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS)).isFalse(); + } + + @Test + public void + isCommandAvailable_duringUnseekableLiveItemWithPreviousWindow_isTrueForSeekToPrevious() { + int[] mediaQueueItemIds = new int[] {1, 2}; + List mediaItems = createMediaItems(mediaQueueItemIds); + int[] streamTypes = new int[] {MediaInfo.STREAM_TYPE_BUFFERED, MediaInfo.STREAM_TYPE_LIVE}; + long[] durationsMs = new long[] {10_000, C.TIME_UNSET}; + + castPlayer.addMediaItems(mediaItems); + updateTimeLine( + mediaItems, + mediaQueueItemIds, + /* currentItemId= */ 2, + streamTypes, + durationsMs, + /* positionMs= */ C.TIME_UNSET); + + assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS)).isTrue(); + } + + @Test + public void isCommandAvailable_duringLiveItem_isTrueForSeekToNext() { MediaItem mediaItem = createMediaItem(/* mediaQueueItemId= */ 1); List mediaItems = ImmutableList.of(mediaItem); int[] mediaQueueItemIds = new int[] {1}; @@ -1148,42 +1312,38 @@ public void isCommandAvailable_duringUnseekableItem_isFalseForSeekInCurrent() { durationsMs, /* positionMs= */ C.TIME_UNSET); - assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM)).isFalse(); + assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_TO_NEXT)).isTrue(); } @Test public void seekTo_nextWindow_notifiesAvailableCommandsChanged() { when(mockRemoteMediaClient.queueJumpToItem(anyInt(), anyLong(), eq(null))) .thenReturn(mockPendingResult); - Player.Commands commandsWithSeekInCurrentAndToNext = - createWithPermanentCommands( - COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); - Player.Commands commandsWithSeekInCurrentAndToPrevious = - createWithPermanentCommands( - COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); - Player.Commands commandsWithSeekAnywhere = - createWithPermanentCommands( - COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, - COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, - COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); + Player.Commands commandsWithSeekToPreviousWindow = + createWithDefaultCommands(COMMAND_SEEK_TO_PREVIOUS_WINDOW); + Player.Commands commandsWithSeekToNextWindow = + createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_WINDOW, COMMAND_SEEK_TO_NEXT); + Player.Commands commandsWithSeekToPreviousAndNextWindow = + createWithDefaultCommands( + COMMAND_SEEK_TO_PREVIOUS_WINDOW, COMMAND_SEEK_TO_NEXT_WINDOW, COMMAND_SEEK_TO_NEXT); int[] mediaQueueItemIds = new int[] {1, 2, 3, 4}; List mediaItems = createMediaItems(mediaQueueItemIds); castPlayer.addMediaItems(mediaItems); updateTimeLine(mediaItems, mediaQueueItemIds, /* currentItemId= */ 1); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekInCurrentAndToNext); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToNextWindow); // Check that there were no other calls to onAvailableCommandsChanged. verify(mockListener).onAvailableCommandsChanged(any()); castPlayer.seekTo(/* windowIndex= */ 1, /* positionMs= */ 0); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekAnywhere); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToPreviousAndNextWindow); verify(mockListener, times(2)).onAvailableCommandsChanged(any()); castPlayer.seekTo(/* windowIndex= */ 2, /* positionMs= */ 0); verify(mockListener, times(2)).onAvailableCommandsChanged(any()); castPlayer.seekTo(/* windowIndex= */ 3, /* positionMs= */ 0); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekInCurrentAndToPrevious); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToPreviousWindow); verify(mockListener, times(3)).onAvailableCommandsChanged(any()); } @@ -1191,35 +1351,31 @@ public void seekTo_nextWindow_notifiesAvailableCommandsChanged() { public void seekTo_previousWindow_notifiesAvailableCommandsChanged() { when(mockRemoteMediaClient.queueJumpToItem(anyInt(), anyLong(), eq(null))) .thenReturn(mockPendingResult); - Player.Commands commandsWithSeekInCurrentAndToNext = - createWithPermanentCommands( - COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); - Player.Commands commandsWithSeekInCurrentAndToPrevious = - createWithPermanentCommands( - COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); - Player.Commands commandsWithSeekAnywhere = - createWithPermanentCommands( - COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, - COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, - COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); + Player.Commands commandsWithSeekToPreviousWindow = + createWithDefaultCommands(COMMAND_SEEK_TO_PREVIOUS_WINDOW); + Player.Commands commandsWithSeekToNextWindow = + createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_WINDOW, COMMAND_SEEK_TO_NEXT); + Player.Commands commandsWithSeekToPreviousAndNextWindow = + createWithDefaultCommands( + COMMAND_SEEK_TO_PREVIOUS_WINDOW, COMMAND_SEEK_TO_NEXT_WINDOW, COMMAND_SEEK_TO_NEXT); int[] mediaQueueItemIds = new int[] {1, 2, 3, 4}; List mediaItems = createMediaItems(mediaQueueItemIds); castPlayer.addMediaItems(mediaItems); updateTimeLine(mediaItems, mediaQueueItemIds, /* currentItemId= */ 4); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekInCurrentAndToPrevious); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToPreviousWindow); // Check that there were no other calls to onAvailableCommandsChanged. verify(mockListener).onAvailableCommandsChanged(any()); castPlayer.seekTo(/* windowIndex= */ 2, /* positionMs= */ 0); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekAnywhere); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToPreviousAndNextWindow); verify(mockListener, times(2)).onAvailableCommandsChanged(any()); castPlayer.seekTo(/* windowIndex= */ 1, /* positionMs= */ 0); verify(mockListener, times(2)).onAvailableCommandsChanged(any()); castPlayer.seekTo(/* windowIndex= */ 0, /* positionMs= */ 0); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekInCurrentAndToNext); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToNextWindow); verify(mockListener, times(3)).onAvailableCommandsChanged(any()); } @@ -1227,14 +1383,13 @@ public void seekTo_previousWindow_notifiesAvailableCommandsChanged() { @SuppressWarnings("deprecation") // Mocks deprecated method used by the CastPlayer. public void seekTo_sameWindow_doesNotNotifyAvailableCommandsChanged() { when(mockRemoteMediaClient.seek(anyLong())).thenReturn(mockPendingResult); - Player.Commands commandsWithSeekInCurrent = - createWithPermanentCommands(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM); + Player.Commands defaultCommands = createWithDefaultCommands(); int[] mediaQueueItemIds = new int[] {1}; List mediaItems = createMediaItems(mediaQueueItemIds); castPlayer.addMediaItems(mediaItems); updateTimeLine(mediaItems, mediaQueueItemIds, /* currentItemId= */ 1); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekInCurrent); + verify(mockListener).onAvailableCommandsChanged(defaultCommands); castPlayer.seekTo(/* windowIndex= */ 0, /* positionMs= */ 200); castPlayer.seekTo(/* windowIndex= */ 0, /* positionMs= */ 100); @@ -1244,11 +1399,9 @@ public void seekTo_sameWindow_doesNotNotifyAvailableCommandsChanged() { @Test public void addMediaItem_atTheEnd_notifiesAvailableCommandsChanged() { - Player.Commands commandsWithSeekInCurrent = - createWithPermanentCommands(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM); - Player.Commands commandsWithSeekInCurrentAndToNext = - createWithPermanentCommands( - COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); + Player.Commands defaultCommands = createWithDefaultCommands(); + Player.Commands commandsWithSeekToNextWindow = + createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_WINDOW, COMMAND_SEEK_TO_NEXT); MediaItem mediaItem1 = createMediaItem(/* mediaQueueItemId= */ 1); MediaItem mediaItem2 = createMediaItem(/* mediaQueueItemId= */ 2); MediaItem mediaItem3 = createMediaItem(/* mediaQueueItemId= */ 3); @@ -1258,7 +1411,7 @@ public void addMediaItem_atTheEnd_notifiesAvailableCommandsChanged() { ImmutableList.of(mediaItem1), /* mediaQueueItemIds= */ new int[] {1}, /* currentItemId= */ 1); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekInCurrent); + verify(mockListener).onAvailableCommandsChanged(defaultCommands); // Check that there were no other calls to onAvailableCommandsChanged. verify(mockListener).onAvailableCommandsChanged(any()); @@ -1267,7 +1420,7 @@ public void addMediaItem_atTheEnd_notifiesAvailableCommandsChanged() { ImmutableList.of(mediaItem1, mediaItem2), /* mediaQueueItemIds= */ new int[] {1, 2}, /* currentItemId= */ 1); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekInCurrentAndToNext); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToNextWindow); verify(mockListener, times(2)).onAvailableCommandsChanged(any()); castPlayer.addMediaItem(mediaItem3); @@ -1280,11 +1433,9 @@ public void addMediaItem_atTheEnd_notifiesAvailableCommandsChanged() { @Test public void addMediaItem_atTheStart_notifiesAvailableCommandsChanged() { - Player.Commands commandsWithSeekInCurrent = - createWithPermanentCommands(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM); - Player.Commands commandsWithSeekInCurrentAndToPrevious = - createWithPermanentCommands( - COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); + Player.Commands defaultCommands = createWithDefaultCommands(); + Player.Commands commandsWithSeekToPreviousWindow = + createWithDefaultCommands(COMMAND_SEEK_TO_PREVIOUS_WINDOW); MediaItem mediaItem1 = createMediaItem(/* mediaQueueItemId= */ 1); MediaItem mediaItem2 = createMediaItem(/* mediaQueueItemId= */ 2); MediaItem mediaItem3 = createMediaItem(/* mediaQueueItemId= */ 3); @@ -1294,7 +1445,7 @@ public void addMediaItem_atTheStart_notifiesAvailableCommandsChanged() { ImmutableList.of(mediaItem1), /* mediaQueueItemIds= */ new int[] {1}, /* currentItemId= */ 1); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekInCurrent); + verify(mockListener).onAvailableCommandsChanged(defaultCommands); // Check that there were no other calls to onAvailableCommandsChanged. verify(mockListener).onAvailableCommandsChanged(any()); @@ -1303,7 +1454,7 @@ public void addMediaItem_atTheStart_notifiesAvailableCommandsChanged() { ImmutableList.of(mediaItem2, mediaItem1), /* mediaQueueItemIds= */ new int[] {2, 1}, /* currentItemId= */ 1); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekInCurrentAndToPrevious); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToPreviousWindow); verify(mockListener, times(2)).onAvailableCommandsChanged(any()); castPlayer.addMediaItem(/* index= */ 0, mediaItem3); @@ -1316,12 +1467,10 @@ public void addMediaItem_atTheStart_notifiesAvailableCommandsChanged() { @Test public void removeMediaItem_atTheEnd_notifiesAvailableCommandsChanged() { - Player.Commands commandsWithoutSeek = createWithPermanentCommands(); - Player.Commands commandsWithSeekInCurrent = - createWithPermanentCommands(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM); - Player.Commands commandsWithSeekInCurrentAndToNext = - createWithPermanentCommands( - COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); + Player.Commands defaultCommands = createWithDefaultCommands(); + Player.Commands commandsWithSeekToNextWindow = + createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_WINDOW, COMMAND_SEEK_TO_NEXT); + Player.Commands emptyTimelineCommands = createWithDefaultCommands(/* isTimelineEmpty= */ true); MediaItem mediaItem1 = createMediaItem(/* mediaQueueItemId= */ 1); MediaItem mediaItem2 = createMediaItem(/* mediaQueueItemId= */ 2); MediaItem mediaItem3 = createMediaItem(/* mediaQueueItemId= */ 3); @@ -1331,7 +1480,7 @@ public void removeMediaItem_atTheEnd_notifiesAvailableCommandsChanged() { ImmutableList.of(mediaItem1, mediaItem2, mediaItem3), /* mediaQueueItemIds= */ new int[] {1, 2, 3}, /* currentItemId= */ 1); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekInCurrentAndToNext); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToNextWindow); // Check that there were no other calls to onAvailableCommandsChanged. verify(mockListener).onAvailableCommandsChanged(any()); @@ -1347,7 +1496,7 @@ public void removeMediaItem_atTheEnd_notifiesAvailableCommandsChanged() { ImmutableList.of(mediaItem1), /* mediaQueueItemIds= */ new int[] {1}, /* currentItemId= */ 1); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekInCurrent); + verify(mockListener).onAvailableCommandsChanged(defaultCommands); verify(mockListener, times(2)).onAvailableCommandsChanged(any()); castPlayer.removeMediaItem(/* index= */ 0); @@ -1355,7 +1504,7 @@ public void removeMediaItem_atTheEnd_notifiesAvailableCommandsChanged() { ImmutableList.of(), /* mediaQueueItemIds= */ new int[0], /* currentItemId= */ C.INDEX_UNSET); - verify(mockListener).onAvailableCommandsChanged(commandsWithoutSeek); + verify(mockListener).onAvailableCommandsChanged(emptyTimelineCommands); verify(mockListener, times(3)).onAvailableCommandsChanged(any()); } @@ -1363,12 +1512,10 @@ public void removeMediaItem_atTheEnd_notifiesAvailableCommandsChanged() { public void removeMediaItem_atTheStart_notifiesAvailableCommandsChanged() { when(mockRemoteMediaClient.queueJumpToItem(anyInt(), anyLong(), eq(null))) .thenReturn(mockPendingResult); - Player.Commands commandsWithoutSeek = createWithPermanentCommands(); - Player.Commands commandsWithSeekInCurrent = - createWithPermanentCommands(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM); - Player.Commands commandsWithSeekInCurrentAndToPrevious = - createWithPermanentCommands( - COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); + Player.Commands defaultCommands = createWithDefaultCommands(); + Player.Commands commandsWithSeekToPreviousWindow = + createWithDefaultCommands(COMMAND_SEEK_TO_PREVIOUS_WINDOW); + Player.Commands emptyTimelineCommands = createWithDefaultCommands(/* isTimelineEmpty= */ true); MediaItem mediaItem1 = createMediaItem(/* mediaQueueItemId= */ 1); MediaItem mediaItem2 = createMediaItem(/* mediaQueueItemId= */ 2); MediaItem mediaItem3 = createMediaItem(/* mediaQueueItemId= */ 3); @@ -1378,7 +1525,7 @@ public void removeMediaItem_atTheStart_notifiesAvailableCommandsChanged() { ImmutableList.of(mediaItem1, mediaItem2, mediaItem3), /* mediaQueueItemIds= */ new int[] {1, 2, 3}, /* currentItemId= */ 3); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekInCurrentAndToPrevious); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToPreviousWindow); // Check that there were no other calls to onAvailableCommandsChanged. verify(mockListener).onAvailableCommandsChanged(any()); @@ -1394,7 +1541,7 @@ public void removeMediaItem_atTheStart_notifiesAvailableCommandsChanged() { ImmutableList.of(mediaItem3), /* mediaQueueItemIds= */ new int[] {3}, /* currentItemId= */ 3); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekInCurrent); + verify(mockListener).onAvailableCommandsChanged(defaultCommands); verify(mockListener, times(2)).onAvailableCommandsChanged(any()); castPlayer.removeMediaItem(/* index= */ 0); @@ -1402,17 +1549,15 @@ public void removeMediaItem_atTheStart_notifiesAvailableCommandsChanged() { ImmutableList.of(), /* mediaQueueItemIds= */ new int[0], /* currentItemId= */ C.INDEX_UNSET); - verify(mockListener).onAvailableCommandsChanged(commandsWithoutSeek); + verify(mockListener).onAvailableCommandsChanged(emptyTimelineCommands); verify(mockListener, times(3)).onAvailableCommandsChanged(any()); } @Test public void removeMediaItem_current_notifiesAvailableCommandsChanged() { - Player.Commands commandsWithSeekInCurrent = - createWithPermanentCommands(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM); - Player.Commands commandsWithSeekInCurrentAndToNext = - createWithPermanentCommands( - COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); + Player.Commands defaultCommands = createWithDefaultCommands(); + Player.Commands commandsWithSeekToNextWindow = + createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_WINDOW, COMMAND_SEEK_TO_NEXT); MediaItem mediaItem1 = createMediaItem(/* mediaQueueItemId= */ 1); MediaItem mediaItem2 = createMediaItem(/* mediaQueueItemId= */ 2); @@ -1421,7 +1566,7 @@ public void removeMediaItem_current_notifiesAvailableCommandsChanged() { ImmutableList.of(mediaItem1, mediaItem2), /* mediaQueueItemIds= */ new int[] {1, 2}, /* currentItemId= */ 1); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekInCurrentAndToNext); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToNextWindow); // Check that there were no other calls to onAvailableCommandsChanged. verify(mockListener).onAvailableCommandsChanged(any()); @@ -1430,7 +1575,7 @@ public void removeMediaItem_current_notifiesAvailableCommandsChanged() { ImmutableList.of(mediaItem2), /* mediaQueueItemIds= */ new int[] {2}, /* currentItemId= */ 2); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekInCurrent); + verify(mockListener).onAvailableCommandsChanged(defaultCommands); verify(mockListener, times(2)).onAvailableCommandsChanged(any()); } @@ -1438,24 +1583,21 @@ public void removeMediaItem_current_notifiesAvailableCommandsChanged() { public void setRepeatMode_all_notifiesAvailableCommandsChanged() { when(mockRemoteMediaClient.queueSetRepeatMode(anyInt(), eq(null))) .thenReturn(mockPendingResult); - Player.Commands commandsWithSeekInCurrent = - createWithPermanentCommands(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM); - Player.Commands commandsWithSeekAnywhere = - createWithPermanentCommands( - COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, - COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, - COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); + Player.Commands defaultCommands = createWithDefaultCommands(); + Player.Commands commandsWithSeekToPreviousAndNextWindow = + createWithDefaultCommands( + COMMAND_SEEK_TO_PREVIOUS_WINDOW, COMMAND_SEEK_TO_NEXT_WINDOW, COMMAND_SEEK_TO_NEXT); int[] mediaQueueItemIds = new int[] {1}; List mediaItems = createMediaItems(mediaQueueItemIds); castPlayer.addMediaItems(mediaItems); updateTimeLine(mediaItems, mediaQueueItemIds, /* currentItemId= */ 1); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekInCurrent); + verify(mockListener).onAvailableCommandsChanged(defaultCommands); // Check that there were no other calls to onAvailableCommandsChanged. verify(mockListener).onAvailableCommandsChanged(any()); castPlayer.setRepeatMode(Player.REPEAT_MODE_ALL); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekAnywhere); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToPreviousAndNextWindow); verify(mockListener, times(2)).onAvailableCommandsChanged(any()); } @@ -1463,14 +1605,13 @@ public void setRepeatMode_all_notifiesAvailableCommandsChanged() { public void setRepeatMode_one_doesNotNotifyAvailableCommandsChanged() { when(mockRemoteMediaClient.queueSetRepeatMode(anyInt(), eq(null))) .thenReturn(mockPendingResult); - Player.Commands commandsWithSeekInCurrent = - createWithPermanentCommands(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM); + Player.Commands defaultCommands = createWithDefaultCommands(); int[] mediaQueueItemIds = new int[] {1}; List mediaItems = createMediaItems(mediaQueueItemIds); castPlayer.addMediaItems(mediaItems); updateTimeLine(mediaItems, mediaQueueItemIds, /* currentItemId= */ 1); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekInCurrent); + verify(mockListener).onAvailableCommandsChanged(defaultCommands); // Check that there were no other calls to onAvailableCommandsChanged. verify(mockListener).onAvailableCommandsChanged(any()); @@ -1565,11 +1706,22 @@ private void updateTimeLine( remoteMediaClientCallback.onStatusUpdated(); } - private static Player.Commands createWithPermanentCommands( - @Player.Command int... additionalCommands) { + private static Player.Commands createWithDefaultCommands( + boolean isTimelineEmpty, @Player.Command int... additionalCommands) { Player.Commands.Builder builder = new Player.Commands.Builder(); builder.addAll(CastPlayer.PERMANENT_AVAILABLE_COMMANDS); + if (!isTimelineEmpty) { + builder.add(COMMAND_SEEK_IN_CURRENT_WINDOW); + builder.add(COMMAND_SEEK_TO_PREVIOUS); + builder.add(COMMAND_SEEK_BACK); + builder.add(COMMAND_SEEK_FORWARD); + } builder.addAll(additionalCommands); return builder.build(); } + + private static Player.Commands createWithDefaultCommands( + @Player.Command int... additionalCommands) { + return createWithDefaultCommands(/* isTimelineEmpty= */ false, additionalCommands); + } } diff --git a/extensions/cronet/README.md b/extensions/cronet/README.md index 112ad26bbab..91248583f81 100644 --- a/extensions/cronet/README.md +++ b/extensions/cronet/README.md @@ -1,9 +1,18 @@ # ExoPlayer Cronet extension # -The Cronet extension is an [HttpDataSource][] implementation using [Cronet][]. +The Cronet extension is an [HttpDataSource][] implementation that uses +[Cronet][]. + +Cronet is the Chromium network stack made available to Android apps as a +library. It takes advantage of multiple technologies that reduce the latency and +increase the throughput of the network requests that your app needs to work, +including those made by ExoPlayer. It natively supports the HTTP, HTTP/2, and +HTTP/3 over QUIC protocols. Cronet is used by some of the world's biggest +streaming applications, including YouTube, and is our recommended network stack +for most use cases. [HttpDataSource]: https://exoplayer.dev/doc/reference/com/google/android/exoplayer2/upstream/HttpDataSource.html -[Cronet]: https://chromium.googlesource.com/chromium/src/+/master/components/cronet?autodive=0%2F%2F +[Cronet]: https://developer.android.com/guide/topics/connectivity/cronet ## Getting the extension ## @@ -20,76 +29,97 @@ Alternatively, you can clone the ExoPlayer repository and depend on the module locally. Instructions for doing this can be found in ExoPlayer's [top level README][]. -Note that by default, the extension will use the Cronet implementation in -Google Play Services. If you prefer, it's also possible to embed the Cronet -implementation directly into your application. See below for more details. - [top level README]: https://github.com/google/ExoPlayer/blob/release-v2/README.md ## Using the extension ## ExoPlayer requests data through `DataSource` instances. These instances are -either instantiated and injected from application code, or obtained from -instances of `DataSource.Factory` that are instantiated and injected from -application code. +obtained from instances of `DataSource.Factory`, which are instantiated and +injected from application code. If your application only needs to play http(s) content, using the Cronet -extension is as simple as updating any `DataSource`s and `DataSource.Factory` -instantiations in your application code to use `CronetDataSource` and -`CronetDataSourceFactory` respectively. If your application also needs to play -non-http(s) content such as local files, use -``` -new DefaultDataSource( - ... - new CronetDataSource(...) /* baseDataSource argument */); -``` -and +extension is as simple as updating `DataSource.Factory` instantiations in your +application code to use `CronetDataSource.Factory`. If your application also +needs to play non-http(s) content such as local files, use: ``` new DefaultDataSourceFactory( ... - new CronetDataSourceFactory(...) /* baseDataSourceFactory argument */); + /* baseDataSourceFactory= */ new CronetDataSource.Factory(...) ); ``` -respectively. -## Choosing between Google Play Services Cronet and Cronet Embedded ## +## Cronet implementations ## -The underlying Cronet implementation is available both via a [Google Play -Services](https://developers.google.com/android/guides/overview) API, and as a -library that can be embedded directly into your application. When you depend on -`com.google.android.exoplayer:extension-cronet:2.X.X`, the library will _not_ be -embedded into your application by default. The extension will attempt to use the -Cronet implementation in Google Play Services. The benefits of this approach -are: +To instantiate a `CronetDataSource.Factory` you'll need a `CronetEngine`. A +`CronetEngine` can be obtained from one of a number of Cronet implementations. +It's recommended that an application should only have a single `CronetEngine` +instance. -* A negligible increase in the size of your application. -* The Cronet implementation is updated automatically by Google Play Services. +### Available implementations ### -If Google Play Services is not available on a device, `CronetDataSourceFactory` -will fall back to creating `DefaultHttpDataSource` instances, or -`HttpDataSource` instances created by a `fallbackFactory` that you can specify. +#### Google Play Services #### -It's also possible to embed the Cronet implementation directly into your -application. To do this, add an additional gradle dependency to the Cronet -Embedded library: +By default, ExoPlayer's Cronet extension depends on +`com.google.android.gms:play-services-cronet`, which loads an implementation of +Cronet from Google Play Services. When Google Play Services is available, +this approach is beneficial because: -```gradle -implementation 'com.google.android.exoplayer:extension-cronet:2.X.X' -implementation 'org.chromium.net:cronet-embedded:XX.XXXX.XXX' -``` +* The increase in application size is negligible. +* The implementation is updated automatically by Google Play Services. + +The disadvantage of this approach is that the implementation is not usable on +devices that do not have Google Play Services. Unless your application also +includes one of the alternative Cronet implementations described below, you will +not be able to instantiate a `CronetEngine` in this case. Your application code +should handle this by falling back to use `DefaultHttpDataSource` instead. -where `XX.XXXX.XXX` is the version of the library that you wish to use. The -extension will automatically detect and use the library. Embedding will add -approximately 8MB to your application, however it may be suitable if: +#### Cronet Embedded #### -* Your application is likely to be used in markets where Google Play Services is +Cronet Embedded bundles a full Cronet implementation directly into your +application. To use it, add an additional dependency on +`org.chromium.net:cronet-embedded`. Cronet Embedded adds approximately 8MB to +your application, and so we do not recommend it for most use cases. That said, +use of Cronet Embedded may be appropriate if: + +* A large percentage of your users are in markets where Google Play Services is not widely available. * You want to control the exact version of the Cronet implementation being used. -If you do embed the library, you can specify which implementation should -be preferred if the Google Play Services implementation is also available. This -is controlled by a `preferGMSCoreCronet` parameter, which can be passed to the -`CronetEngineWrapper` constructor (GMS Core is another name for Google Play -Services). +#### Cronet Fallback #### + +There's also a fallback implementation of Cronet, which uses Android's default +network stack under the hood. It can be used by adding a dependency on +`org.chromium.net:cronet-fallback`. This implementation should _not_ be used +with ExoPlayer, since it's more efficient to use `DefaultHttpDataSource` +directly in this case. + +When using Cronet Fallback for other networking in your application, use the +more advanced approach to instantiating a `CronetEngine` described below so that +you know when your application's `CronetEngine` has been obtained from the +fallback implementation. In this case, avoid using it with ExoPlayer and use +`DefaultHttpDataSource` instead. + +### CronetEngine instantiation ### + +Cronet's [Send a simple request][] page documents the simplest way of building a +`CronetEngine`, which is suitable if your application is only using the +Google Play Services implementation of Cronet. + +For cases where your application also includes one of the other Cronet +implementations, you can use `CronetProvider.getAllProviders` to list the +available implementations. Providers can be identified by name: + +* `CronetProviderInstaller.PROVIDER_NAME`: Google Play Services implementation. +* `CronetProvider.PROVIDER_NAME_APP_PACKAGED`: Embedded implementation. +* `CronetProvider.PROVIDER_NAME_FALLBACK`: Fallback implementation. + +This makes it possible to iterate through the providers in your own order of +preference, trying to build a `CronetEngine` from each in turn using +`CronetProvider.createBuilder()` until one has been successfully created. This +approach also allows you to determine when the `CronetEngine` has been obtained +from Cronet Fallback, in which case you can avoid using it for ExoPlayer whilst +still using it for other networking performed by your application. + +[Send a simple request]: https://developer.android.com/guide/topics/connectivity/cronet/start ## Links ## diff --git a/extensions/cronet/build.gradle b/extensions/cronet/build.gradle index d9b2c78507b..9a11adbd150 100644 --- a/extensions/cronet/build.gradle +++ b/extensions/cronet/build.gradle @@ -20,7 +20,7 @@ android { } dependencies { - api "com.google.android.gms:play-services-cronet:17.0.0" + api "com.google.android.gms:play-services-cronet:17.0.1" implementation project(modulePrefix + 'library-common') implementation 'androidx.annotation:annotation:' + androidxAnnotationVersion compileOnly 'org.checkerframework:checker-qual:' + checkerframeworkVersion @@ -31,10 +31,10 @@ dependencies { androidTestImplementation 'com.linkedin.dexmaker:dexmaker-mockito:' + dexmakerVersion // Instrumentation tests assume that an app-packaged version of cronet is // available. - androidTestImplementation 'org.chromium.net:cronet-embedded:72.3626.96' + androidTestImplementation 'org.chromium.net:cronet-embedded:76.3809.111' androidTestImplementation project(modulePrefix + 'testutils') testImplementation project(modulePrefix + 'testutils') - testImplementation 'com.squareup.okhttp3:mockwebserver:' + mockWebServerVersion + testImplementation 'com.squareup.okhttp3:mockwebserver:' + okhttpVersion testImplementation 'org.robolectric:robolectric:' + robolectricVersion } diff --git a/extensions/cronet/src/androidTest/java/com/google/android/exoplayer2/ext/cronet/CronetDataSourceContractTest.java b/extensions/cronet/src/androidTest/java/com/google/android/exoplayer2/ext/cronet/CronetDataSourceContractTest.java index 967c894c397..71f46621d9e 100644 --- a/extensions/cronet/src/androidTest/java/com/google/android/exoplayer2/ext/cronet/CronetDataSourceContractTest.java +++ b/extensions/cronet/src/androidTest/java/com/google/android/exoplayer2/ext/cronet/CronetDataSourceContractTest.java @@ -18,16 +18,16 @@ import static com.google.common.truth.Truth.assertThat; import android.net.Uri; +import androidx.annotation.Nullable; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.testutil.DataSourceContractTest; import com.google.android.exoplayer2.testutil.HttpDataSourceTestEnv; import com.google.android.exoplayer2.upstream.DataSource; -import com.google.android.exoplayer2.upstream.HttpDataSource; import com.google.common.collect.ImmutableList; -import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import org.chromium.net.CronetEngine; import org.junit.After; import org.junit.Rule; import org.junit.runner.RunWith; @@ -46,16 +46,14 @@ public void tearDown() { @Override protected DataSource createDataSource() { - CronetEngineWrapper cronetEngineWrapper = - new CronetEngineWrapper( + @Nullable + CronetEngine cronetEngine = + CronetUtil.buildCronetEngine( ApplicationProvider.getApplicationContext(), /* userAgent= */ "test-agent", /* preferGMSCoreCronet= */ false); - assertThat(cronetEngineWrapper.getCronetEngineSource()) - .isEqualTo(CronetEngineWrapper.SOURCE_NATIVE); - return new CronetDataSource.Factory(cronetEngineWrapper, executorService) - .setFallbackFactory(new InvalidDataSourceFactory()) - .createDataSource(); + assertThat(cronetEngine).isNotNull(); + return new CronetDataSource.Factory(cronetEngine, executorService).createDataSource(); } @Override @@ -67,26 +65,4 @@ protected ImmutableList getTestResources() { protected Uri getNotFoundUri() { return Uri.parse(httpDataSourceTestEnv.getNonexistentUrl()); } - - /** - * An {@link HttpDataSource.Factory} that throws {@link UnsupportedOperationException} on every - * interaction. - */ - private static class InvalidDataSourceFactory implements HttpDataSource.Factory { - @Override - public HttpDataSource createDataSource() { - throw new UnsupportedOperationException(); - } - - @Override - public HttpDataSource.RequestProperties getDefaultRequestProperties() { - throw new UnsupportedOperationException(); - } - - @Override - public HttpDataSource.Factory setDefaultRequestProperties( - Map defaultRequestProperties) { - throw new UnsupportedOperationException(); - } - } } diff --git a/extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/ByteArrayUploadDataProvider.java b/extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/ByteArrayUploadDataProvider.java index e70538d7bec..5c5528ed829 100644 --- a/extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/ByteArrayUploadDataProvider.java +++ b/extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/ByteArrayUploadDataProvider.java @@ -22,9 +22,7 @@ import org.chromium.net.UploadDataProvider; import org.chromium.net.UploadDataSink; -/** - * A {@link UploadDataProvider} implementation that provides data from a {@code byte[]}. - */ +/** A {@link UploadDataProvider} implementation that provides data from a {@code byte[]}. */ /* package */ final class ByteArrayUploadDataProvider extends UploadDataProvider { private final byte[] data; @@ -53,5 +51,4 @@ public void rewind(UploadDataSink uploadDataSink) throws IOException { position = 0; uploadDataSink.onRewindSucceeded(); } - } diff --git a/extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetDataSource.java b/extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetDataSource.java index 9b73387fc18..483df638b31 100644 --- a/extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetDataSource.java +++ b/extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetDataSource.java @@ -17,12 +17,14 @@ import static com.google.android.exoplayer2.upstream.HttpUtil.buildRangeRequestHeader; import static com.google.android.exoplayer2.util.Util.castNonNull; +import static org.chromium.net.UrlRequest.Builder.REQUEST_PRIORITY_MEDIUM; import android.net.Uri; import android.text.TextUtils; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlayerLibraryInfo; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.upstream.BaseDataSource; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSourceException; @@ -74,19 +76,46 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource { /** {@link DataSource.Factory} for {@link CronetDataSource} instances. */ public static final class Factory implements HttpDataSource.Factory { - private final CronetEngineWrapper cronetEngineWrapper; + // TODO: Remove @Nullable annotation when CronetEngineWrapper is deleted. + @Nullable private final CronetEngine cronetEngine; private final Executor executor; private final RequestProperties defaultRequestProperties; - private final DefaultHttpDataSource.Factory internalFallbackFactory; + // TODO: Remove when CronetEngineWrapper is deleted. + @Nullable private final DefaultHttpDataSource.Factory internalFallbackFactory; + // TODO: Remove when CronetEngineWrapper is deleted. @Nullable private HttpDataSource.Factory fallbackFactory; @Nullable private Predicate contentTypePredicate; @Nullable private TransferListener transferListener; @Nullable private String userAgent; + private int requestPriority; private int connectTimeoutMs; private int readTimeoutMs; private boolean resetTimeoutOnRedirects; private boolean handleSetCookieRequests; + private boolean keepPostFor302Redirects; + + /** + * Creates an instance. + * + * @param cronetEngine A {@link CronetEngine} to make the requests. This should not be + * a fallback instance obtained from {@code JavaCronetProvider}. It's more efficient to use + * {@link DefaultHttpDataSource} instead in this case. + * @param executor The {@link java.util.concurrent.Executor} that will handle responses. This + * may be a direct executor (i.e. executes tasks on the calling thread) in order to avoid a + * thread hop from Cronet's internal network thread to the response handling thread. + * However, to avoid slowing down overall network performance, care must be taken to make + * sure response handling is a fast operation when using a direct executor. + */ + public Factory(CronetEngine cronetEngine, Executor executor) { + this.cronetEngine = Assertions.checkNotNull(cronetEngine); + this.executor = executor; + defaultRequestProperties = new RequestProperties(); + internalFallbackFactory = null; + requestPriority = REQUEST_PRIORITY_MEDIUM; + connectTimeoutMs = DEFAULT_CONNECT_TIMEOUT_MILLIS; + readTimeoutMs = DEFAULT_READ_TIMEOUT_MILLIS; + } /** * Creates an instance. @@ -97,9 +126,13 @@ public static final class Factory implements HttpDataSource.Factory { * thread hop from Cronet's internal network thread to the response handling thread. * However, to avoid slowing down overall network performance, care must be taken to make * sure response handling is a fast operation when using a direct executor. + * @deprecated Use {@link #Factory(CronetEngine, Executor)} with an instantiated {@link + * CronetEngine}, or {@link DefaultHttpDataSource} for cases where {@link + * CronetEngineWrapper#getCronetEngine()} would have returned {@code null}. */ + @Deprecated public Factory(CronetEngineWrapper cronetEngineWrapper, Executor executor) { - this.cronetEngineWrapper = cronetEngineWrapper; + this.cronetEngine = cronetEngineWrapper.getCronetEngine(); this.executor = executor; defaultRequestProperties = new RequestProperties(); internalFallbackFactory = new DefaultHttpDataSource.Factory(); @@ -117,7 +150,9 @@ public final RequestProperties getDefaultRequestProperties() { @Override public final Factory setDefaultRequestProperties(Map defaultRequestProperties) { this.defaultRequestProperties.clearAndSet(defaultRequestProperties); - internalFallbackFactory.setDefaultRequestProperties(defaultRequestProperties); + if (internalFallbackFactory != null) { + internalFallbackFactory.setDefaultRequestProperties(defaultRequestProperties); + } return this; } @@ -133,7 +168,24 @@ public final Factory setDefaultRequestProperties(Map defaultRequ */ public Factory setUserAgent(@Nullable String userAgent) { this.userAgent = userAgent; - internalFallbackFactory.setUserAgent(userAgent); + if (internalFallbackFactory != null) { + internalFallbackFactory.setUserAgent(userAgent); + } + return this; + } + + /** + * Sets the priority of requests made by {@link CronetDataSource} instances created by this + * factory. + * + *

      The default is {@link UrlRequest.Builder#REQUEST_PRIORITY_MEDIUM}. + * + * @param requestPriority The request priority, which should be one of Cronet's {@code + * UrlRequest.Builder#REQUEST_PRIORITY_*} constants. + * @return This factory. + */ + public Factory setRequestPriority(int requestPriority) { + this.requestPriority = requestPriority; return this; } @@ -147,7 +199,9 @@ public Factory setUserAgent(@Nullable String userAgent) { */ public Factory setConnectionTimeoutMs(int connectTimeoutMs) { this.connectTimeoutMs = connectTimeoutMs; - internalFallbackFactory.setConnectTimeoutMs(connectTimeoutMs); + if (internalFallbackFactory != null) { + internalFallbackFactory.setConnectTimeoutMs(connectTimeoutMs); + } return this; } @@ -189,7 +243,9 @@ public Factory setHandleSetCookieRequests(boolean handleSetCookieRequests) { */ public Factory setReadTimeoutMs(int readTimeoutMs) { this.readTimeoutMs = readTimeoutMs; - internalFallbackFactory.setReadTimeoutMs(readTimeoutMs); + if (internalFallbackFactory != null) { + internalFallbackFactory.setReadTimeoutMs(readTimeoutMs); + } return this; } @@ -205,7 +261,21 @@ public Factory setReadTimeoutMs(int readTimeoutMs) { */ public Factory setContentTypePredicate(@Nullable Predicate contentTypePredicate) { this.contentTypePredicate = contentTypePredicate; - internalFallbackFactory.setContentTypePredicate(contentTypePredicate); + if (internalFallbackFactory != null) { + internalFallbackFactory.setContentTypePredicate(contentTypePredicate); + } + return this; + } + + /** + * Sets whether we should keep the POST method and body when we have HTTP 302 redirects for a + * POST request. + */ + public Factory setKeepPostFor302Redirects(boolean keepPostFor302Redirects) { + this.keepPostFor302Redirects = keepPostFor302Redirects; + if (internalFallbackFactory != null) { + internalFallbackFactory.setKeepPostFor302Redirects(keepPostFor302Redirects); + } return this; } @@ -221,7 +291,9 @@ public Factory setContentTypePredicate(@Nullable Predicate contentTypePr */ public Factory setTransferListener(@Nullable TransferListener transferListener) { this.transferListener = transferListener; - internalFallbackFactory.setTransferListener(transferListener); + if (internalFallbackFactory != null) { + internalFallbackFactory.setTransferListener(transferListener); + } return this; } @@ -233,7 +305,10 @@ public Factory setTransferListener(@Nullable TransferListener transferListener) * * @param fallbackFactory The fallback factory that will be used. * @return This factory. + * @deprecated Do not use {@link CronetDataSource} or its factory in cases where a suitable + * {@link CronetEngine} is not available. Use the fallback factory directly in such cases. */ + @Deprecated public Factory setFallbackFactory(@Nullable HttpDataSource.Factory fallbackFactory) { this.fallbackFactory = fallbackFactory; return this; @@ -241,23 +316,24 @@ public Factory setFallbackFactory(@Nullable HttpDataSource.Factory fallbackFacto @Override public HttpDataSource createDataSource() { - @Nullable CronetEngine cronetEngine = cronetEngineWrapper.getCronetEngine(); if (cronetEngine == null) { return (fallbackFactory != null) ? fallbackFactory.createDataSource() - : internalFallbackFactory.createDataSource(); + : Assertions.checkNotNull(internalFallbackFactory).createDataSource(); } CronetDataSource dataSource = new CronetDataSource( cronetEngine, executor, + requestPriority, connectTimeoutMs, readTimeoutMs, resetTimeoutOnRedirects, handleSetCookieRequests, userAgent, defaultRequestProperties, - contentTypePredicate); + contentTypePredicate, + keepPostFor302Redirects); if (transferListener != null) { dataSource.addTransferListener(transferListener); } @@ -265,9 +341,7 @@ public HttpDataSource createDataSource() { } } - /** - * Thrown when an error is encountered when trying to open a {@link CronetDataSource}. - */ + /** Thrown when an error is encountered when trying to open a {@link CronetDataSource}. */ public static final class OpenException extends HttpDataSourceException { /** @@ -276,13 +350,41 @@ public static final class OpenException extends HttpDataSourceException { */ public final int cronetConnectionStatus; + /** @deprecated Use {@link #OpenException(IOException, DataSpec, int, int)}. */ + @Deprecated public OpenException(IOException cause, DataSpec dataSpec, int cronetConnectionStatus) { - super(cause, dataSpec, TYPE_OPEN); + super(cause, dataSpec, PlaybackException.ERROR_CODE_IO_UNSPECIFIED, TYPE_OPEN); this.cronetConnectionStatus = cronetConnectionStatus; } + public OpenException( + IOException cause, + DataSpec dataSpec, + @PlaybackException.ErrorCode int errorCode, + int cronetConnectionStatus) { + super(cause, dataSpec, errorCode, TYPE_OPEN); + this.cronetConnectionStatus = cronetConnectionStatus; + } + + /** @deprecated Use {@link #OpenException(String, DataSpec, int, int)}. */ + @Deprecated public OpenException(String errorMessage, DataSpec dataSpec, int cronetConnectionStatus) { - super(errorMessage, dataSpec, TYPE_OPEN); + super(errorMessage, dataSpec, PlaybackException.ERROR_CODE_IO_UNSPECIFIED, TYPE_OPEN); + this.cronetConnectionStatus = cronetConnectionStatus; + } + + public OpenException( + String errorMessage, + DataSpec dataSpec, + @PlaybackException.ErrorCode int errorCode, + int cronetConnectionStatus) { + super(errorMessage, dataSpec, errorCode, TYPE_OPEN); + this.cronetConnectionStatus = cronetConnectionStatus; + } + + public OpenException( + DataSpec dataSpec, @PlaybackException.ErrorCode int errorCode, int cronetConnectionStatus) { + super(dataSpec, errorCode, TYPE_OPEN); this.cronetConnectionStatus = cronetConnectionStatus; } } @@ -299,6 +401,7 @@ public OpenException(String errorMessage, DataSpec dataSpec, int cronetConnectio private final CronetEngine cronetEngine; private final Executor executor; + private final int requestPriority; private final int connectTimeoutMs; private final int readTimeoutMs; private final boolean resetTimeoutOnRedirects; @@ -310,6 +413,7 @@ public OpenException(String errorMessage, DataSpec dataSpec, int cronetConnectio private final Clock clock; @Nullable private Predicate contentTypePredicate; + private final boolean keepPostFor302Redirects; // Accessed by the calling thread only. private boolean opened; @@ -358,13 +462,15 @@ public CronetDataSource( this( cronetEngine, executor, + REQUEST_PRIORITY_MEDIUM, connectTimeoutMs, readTimeoutMs, resetTimeoutOnRedirects, /* handleSetCookieRequests= */ false, /* userAgent= */ null, defaultRequestProperties, - /* contentTypePredicate= */ null); + /* contentTypePredicate= */ null, + /* keepPostFor302Redirects */ false); } /** @deprecated Use {@link CronetDataSource.Factory} instead. */ @@ -380,13 +486,15 @@ public CronetDataSource( this( cronetEngine, executor, + REQUEST_PRIORITY_MEDIUM, connectTimeoutMs, readTimeoutMs, resetTimeoutOnRedirects, handleSetCookieRequests, /* userAgent= */ null, defaultRequestProperties, - /* contentTypePredicate= */ null); + /* contentTypePredicate= */ null, + /* keepPostFor302Redirects */ false); } /** @deprecated Use {@link CronetDataSource.Factory} instead. */ @@ -442,28 +550,33 @@ public CronetDataSource( this( cronetEngine, executor, + REQUEST_PRIORITY_MEDIUM, connectTimeoutMs, readTimeoutMs, resetTimeoutOnRedirects, handleSetCookieRequests, /* userAgent= */ null, defaultRequestProperties, - contentTypePredicate); + contentTypePredicate, + /* keepPostFor302Redirects */ false); } - private CronetDataSource( + protected CronetDataSource( CronetEngine cronetEngine, Executor executor, + int requestPriority, int connectTimeoutMs, int readTimeoutMs, boolean resetTimeoutOnRedirects, boolean handleSetCookieRequests, @Nullable String userAgent, @Nullable RequestProperties defaultRequestProperties, - @Nullable Predicate contentTypePredicate) { + @Nullable Predicate contentTypePredicate, + boolean keepPostFor302Redirects) { super(/* isNetwork= */ true); this.cronetEngine = Assertions.checkNotNull(cronetEngine); this.executor = Assertions.checkNotNull(executor); + this.requestPriority = requestPriority; this.connectTimeoutMs = connectTimeoutMs; this.readTimeoutMs = readTimeoutMs; this.resetTimeoutOnRedirects = resetTimeoutOnRedirects; @@ -471,6 +584,7 @@ private CronetDataSource( this.userAgent = userAgent; this.defaultRequestProperties = defaultRequestProperties; this.contentTypePredicate = contentTypePredicate; + this.keepPostFor302Redirects = keepPostFor302Redirects; clock = Clock.DEFAULT; urlRequestCallback = new UrlRequestCallback(); requestProperties = new RequestProperties(); @@ -537,7 +651,12 @@ public long open(DataSpec dataSpec) throws HttpDataSourceException { urlRequest = buildRequestBuilder(dataSpec).build(); currentUrlRequest = urlRequest; } catch (IOException e) { - throw new OpenException(e, dataSpec, Status.IDLE); + if (e instanceof HttpDataSourceException) { + throw (HttpDataSourceException) e; + } else { + throw new OpenException( + e, dataSpec, PlaybackException.ERROR_CODE_IO_UNSPECIFIED, Status.IDLE); + } } urlRequest.start(); @@ -550,14 +669,29 @@ public long open(DataSpec dataSpec) throws HttpDataSourceException { if (message != null && Ascii.toLowerCase(message).contains("err_cleartext_not_permitted")) { throw new CleartextNotPermittedException(connectionOpenException, dataSpec); } - throw new OpenException(connectionOpenException, dataSpec, getStatus(urlRequest)); + throw new OpenException( + connectionOpenException, + dataSpec, + PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED, + getStatus(urlRequest)); } else if (!connectionOpened) { // The timeout was reached before the connection was opened. - throw new OpenException(new SocketTimeoutException(), dataSpec, getStatus(urlRequest)); + throw new OpenException( + new SocketTimeoutException(), + dataSpec, + PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT, + getStatus(urlRequest)); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); - throw new OpenException(new InterruptedIOException(), dataSpec, Status.INVALID); + // An interruption means the operation is being cancelled, in which case this exception should + // not cause the player to fail. If it does, it likely means that the owner of the operation + // is failing to swallow the interruption, which makes us enter an invalid state. + throw new OpenException( + new InterruptedIOException(), + dataSpec, + PlaybackException.ERROR_CODE_FAILED_RUNTIME_CHECK, + Status.INVALID); } // Check for a valid response code. @@ -582,17 +716,18 @@ public long open(DataSpec dataSpec) throws HttpDataSourceException { responseBody = Util.EMPTY_BYTE_ARRAY; } - InvalidResponseCodeException exception = - new InvalidResponseCodeException( - responseCode, - responseInfo.getHttpStatusText(), - responseHeaders, - dataSpec, - responseBody); - if (responseCode == 416) { - exception.initCause(new DataSourceException(DataSourceException.POSITION_OUT_OF_RANGE)); - } - throw exception; + @Nullable + IOException cause = + responseCode == 416 + ? new DataSourceException(PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE) + : null; + throw new InvalidResponseCodeException( + responseCode, + responseInfo.getHttpStatusText(), + cause, + responseHeaders, + dataSpec, + responseBody); } // Check for a valid content type. @@ -630,22 +765,15 @@ public long open(DataSpec dataSpec) throws HttpDataSourceException { opened = true; transferStarted(dataSpec); - try { - if (!skipFully(bytesToSkip)) { - throw new DataSourceException(DataSourceException.POSITION_OUT_OF_RANGE); - } - } catch (IOException e) { - throw new OpenException(e, dataSpec, Status.READING_RESPONSE); - } - + skipFully(bytesToSkip, dataSpec); return bytesRemaining; } @Override - public int read(byte[] buffer, int offset, int readLength) throws HttpDataSourceException { + public int read(byte[] buffer, int offset, int length) throws HttpDataSourceException { Assertions.checkState(opened); - if (readLength == 0) { + if (length == 0) { return 0; } else if (bytesRemaining == 0) { return C.RESULT_END_OF_INPUT; @@ -656,12 +784,8 @@ public int read(byte[] buffer, int offset, int readLength) throws HttpDataSource // Fill readBuffer with more data from Cronet. operation.close(); readBuffer.clear(); - try { - readInternal(readBuffer); - } catch (IOException e) { - throw new HttpDataSourceException( - e, castNonNull(currentDataSpec), HttpDataSourceException.TYPE_READ); - } + + readInternal(readBuffer, castNonNull(currentDataSpec)); if (finished) { bytesRemaining = 0; @@ -680,7 +804,7 @@ public int read(byte[] buffer, int offset, int readLength) throws HttpDataSource Longs.min( bytesRemaining != C.LENGTH_UNSET ? bytesRemaining : Long.MAX_VALUE, readBuffer.remaining(), - readLength); + length); readBuffer.get(buffer, offset, bytesRead); @@ -743,12 +867,7 @@ public int read(ByteBuffer buffer) throws HttpDataSourceException { // Fill buffer with more data from Cronet. operation.close(); - try { - readInternal(buffer); - } catch (IOException e) { - throw new HttpDataSourceException( - e, castNonNull(currentDataSpec), HttpDataSourceException.TYPE_READ); - } + readInternal(buffer, castNonNull(currentDataSpec)); if (finished) { bytesRemaining = 0; @@ -800,6 +919,7 @@ protected UrlRequest.Builder buildRequestBuilder(DataSpec dataSpec) throws IOExc UrlRequest.Builder requestBuilder = cronetEngine .newUrlRequestBuilder(dataSpec.uri.toString(), urlRequestCallback, executor) + .setPriority(requestPriority) .allowDirectExecutor(); // Set the headers. @@ -817,7 +937,11 @@ protected UrlRequest.Builder buildRequestBuilder(DataSpec dataSpec) throws IOExc } if (dataSpec.httpBody != null && !requestHeaders.containsKey(HttpHeaders.CONTENT_TYPE)) { - throw new IOException("HTTP request with non-empty body must set Content-Type"); + throw new OpenException( + "HTTP request with non-empty body must set Content-Type", + dataSpec, + PlaybackException.ERROR_CODE_FAILED_RUNTIME_CHECK, + Status.IDLE); } @Nullable String rangeHeader = buildRangeRequestHeader(dataSpec.position, dataSpec.length); @@ -861,37 +985,58 @@ private void resetConnectTimeout() { /** * Attempts to skip the specified number of bytes in full. * + *

      The methods throws an {@link OpenException} with {@link OpenException#reason} set to {@link + * PlaybackException#ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE} when the data ended before the + * specified number of bytes were skipped. + * * @param bytesToSkip The number of bytes to skip. - * @throws InterruptedIOException If the thread is interrupted during the operation. - * @throws IOException If an error occurs reading from the source. - * @return Whether the bytes were skipped in full. If {@code false} then the data ended before the - * specified number of bytes were skipped. Always {@code true} if {@code bytesToSkip == 0}. + * @param dataSpec The {@link DataSpec}. + * @throws HttpDataSourceException If the thread is interrupted during the operation, or an error + * occurs reading from the source; or when the data ended before the specified number of bytes + * were skipped. */ - private boolean skipFully(long bytesToSkip) throws IOException { + private void skipFully(long bytesToSkip, DataSpec dataSpec) throws HttpDataSourceException { if (bytesToSkip == 0) { - return true; + return; } ByteBuffer readBuffer = getOrCreateReadBuffer(); - while (bytesToSkip > 0) { - // Fill readBuffer with more data from Cronet. - operation.close(); - readBuffer.clear(); - readInternal(readBuffer); - if (Thread.currentThread().isInterrupted()) { - throw new InterruptedIOException(); + + try { + while (bytesToSkip > 0) { + // Fill readBuffer with more data from Cronet. + operation.close(); + readBuffer.clear(); + readInternal(readBuffer, dataSpec); + if (Thread.currentThread().isInterrupted()) { + throw new InterruptedIOException(); + } + if (finished) { + throw new OpenException( + dataSpec, + PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE, + Status.READING_RESPONSE); + } else { + // The operation didn't time out, fail or finish, and therefore data must have been read. + readBuffer.flip(); + Assertions.checkState(readBuffer.hasRemaining()); + int bytesSkipped = (int) Math.min(readBuffer.remaining(), bytesToSkip); + readBuffer.position(readBuffer.position() + bytesSkipped); + bytesToSkip -= bytesSkipped; + } } - if (finished) { - return false; + } catch (IOException e) { + if (e instanceof HttpDataSourceException) { + throw (HttpDataSourceException) e; } else { - // The operation didn't time out, fail or finish, and therefore data must have been read. - readBuffer.flip(); - Assertions.checkState(readBuffer.hasRemaining()); - int bytesSkipped = (int) Math.min(readBuffer.remaining(), bytesToSkip); - readBuffer.position(readBuffer.position() + bytesSkipped); - bytesToSkip -= bytesSkipped; + throw new OpenException( + e, + dataSpec, + e instanceof SocketTimeoutException + ? PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT + : PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED, + Status.READING_RESPONSE); } } - return true; } /** @@ -906,7 +1051,7 @@ private byte[] readResponseBody() throws IOException { while (!finished) { operation.close(); readBuffer.clear(); - readInternal(readBuffer); + readInternal(readBuffer, castNonNull(currentDataSpec)); readBuffer.flip(); if (readBuffer.remaining() > 0) { int existingResponseBodyEnd = responseBody.length; @@ -923,10 +1068,10 @@ private byte[] readResponseBody() throws IOException { * the current {@code readBuffer} object so that it is not reused in the future. * * @param buffer The ByteBuffer into which the read data is stored. Must be a direct ByteBuffer. - * @throws IOException If an error occurs reading from the source. + * @throws HttpDataSourceException If an error occurs reading from the source. */ @SuppressWarnings("ReferenceEquality") - private void readInternal(ByteBuffer buffer) throws IOException { + private void readInternal(ByteBuffer buffer, DataSpec dataSpec) throws HttpDataSourceException { castNonNull(currentUrlRequest).read(buffer); try { if (!operation.block(readTimeoutMs)) { @@ -939,18 +1084,28 @@ private void readInternal(ByteBuffer buffer) throws IOException { readBuffer = null; } Thread.currentThread().interrupt(); - throw new InterruptedIOException(); + exception = new InterruptedIOException(); } catch (SocketTimeoutException e) { // The operation is ongoing so replace buffer to avoid it being written to by this // operation during a subsequent request. if (buffer == readBuffer) { readBuffer = null; } - throw e; + exception = + new HttpDataSourceException( + e, + dataSpec, + PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT, + HttpDataSourceException.TYPE_READ); } if (exception != null) { - throw exception; + if (exception instanceof HttpDataSourceException) { + throw (HttpDataSourceException) exception; + } else { + throw HttpDataSourceException.createForIOException( + exception, dataSpec, HttpDataSourceException.TYPE_READ); + } } } @@ -971,11 +1126,15 @@ private static boolean isCompressed(UrlResponseInfo info) { return false; } - private static String parseCookies(List setCookieHeaders) { + @Nullable + private static String parseCookies(@Nullable List setCookieHeaders) { + if (setCookieHeaders == null || setCookieHeaders.isEmpty()) { + return null; + } return TextUtils.join(";", setCookieHeaders); } - private static void attachCookies(UrlRequest.Builder requestBuilder, String cookies) { + private static void attachCookies(UrlRequest.Builder requestBuilder, @Nullable String cookies) { if (TextUtils.isEmpty(cookies)) { return; } @@ -985,13 +1144,14 @@ private static void attachCookies(UrlRequest.Builder requestBuilder, String cook private static int getStatus(UrlRequest request) throws InterruptedException { final ConditionVariable conditionVariable = new ConditionVariable(); final int[] statusHolder = new int[1]; - request.getStatus(new UrlRequest.StatusListener() { - @Override - public void onStatus(int status) { - statusHolder[0] = status; - conditionVariable.open(); - } - }); + request.getStatus( + new UrlRequest.StatusListener() { + @Override + public void onStatus(int status) { + statusHolder[0] = status; + conditionVariable.open(); + } + }); conditionVariable.block(); return statusHolder[0]; } @@ -1023,14 +1183,15 @@ public synchronized void onRedirectReceived( } UrlRequest urlRequest = Assertions.checkNotNull(currentUrlRequest); DataSpec dataSpec = Assertions.checkNotNull(currentDataSpec); + int responseCode = info.getHttpStatusCode(); if (dataSpec.httpMethod == DataSpec.HTTP_METHOD_POST) { - int responseCode = info.getHttpStatusCode(); // The industry standard is to disregard POST redirects when the status code is 307 or 308. if (responseCode == 307 || responseCode == 308) { exception = new InvalidResponseCodeException( responseCode, info.getHttpStatusText(), + /* cause= */ null, info.getAllHeaders(), dataSpec, /* responseBody= */ Util.EMPTY_BYTE_ARRAY); @@ -1042,22 +1203,30 @@ public synchronized void onRedirectReceived( resetConnectTimeout(); } - if (!handleSetCookieRequests) { + boolean shouldKeepPost = + keepPostFor302Redirects + && dataSpec.httpMethod == DataSpec.HTTP_METHOD_POST + && responseCode == 302; + + // request.followRedirect() transforms a POST request into a GET request, so if we want to + // keep it as a POST we need to fall through to the manual redirect logic below. + if (!shouldKeepPost && !handleSetCookieRequests) { request.followRedirect(); return; } - @Nullable List setCookieHeaders = info.getAllHeaders().get(HttpHeaders.SET_COOKIE); - if (setCookieHeaders == null || setCookieHeaders.isEmpty()) { + @Nullable + String cookieHeadersValue = parseCookies(info.getAllHeaders().get(HttpHeaders.SET_COOKIE)); + if (!shouldKeepPost && TextUtils.isEmpty(cookieHeadersValue)) { request.followRedirect(); return; } urlRequest.cancel(); DataSpec redirectUrlDataSpec; - if (dataSpec.httpMethod == DataSpec.HTTP_METHOD_POST) { + if (!shouldKeepPost && dataSpec.httpMethod == DataSpec.HTTP_METHOD_POST) { // For POST redirects that aren't 307 or 308, the redirect is followed but request is - // transformed into a GET. + // transformed into a GET unless shouldKeepPost is true. redirectUrlDataSpec = dataSpec .buildUpon() @@ -1075,7 +1244,6 @@ public synchronized void onRedirectReceived( exception = e; return; } - String cookieHeadersValue = parseCookies(setCookieHeaders); attachCookies(requestBuilder, cookieHeadersValue); currentUrlRequest = requestBuilder.build(); currentUrlRequest.start(); diff --git a/extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetDataSourceFactory.java b/extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetDataSourceFactory.java index a446fcc299c..f10d556f4c2 100644 --- a/extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetDataSourceFactory.java +++ b/extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetDataSourceFactory.java @@ -27,15 +27,11 @@ @Deprecated public final class CronetDataSourceFactory extends BaseFactory { - /** - * The default connection timeout, in milliseconds. - */ + /** The default connection timeout, in milliseconds. */ public static final int DEFAULT_CONNECT_TIMEOUT_MILLIS = CronetDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS; - /** - * The default read timeout, in milliseconds. - */ + /** The default read timeout, in milliseconds. */ public static final int DEFAULT_READ_TIMEOUT_MILLIS = CronetDataSource.DEFAULT_READ_TIMEOUT_MILLIS; @@ -338,8 +334,8 @@ public CronetDataSourceFactory( } @Override - protected HttpDataSource createDataSourceInternal(HttpDataSource.RequestProperties - defaultRequestProperties) { + protected HttpDataSource createDataSourceInternal( + HttpDataSource.RequestProperties defaultRequestProperties) { @Nullable CronetEngine cronetEngine = cronetEngineWrapper.getCronetEngine(); if (cronetEngine == null) { return fallbackFactory.createDataSource(); @@ -357,5 +353,4 @@ protected HttpDataSource createDataSourceInternal(HttpDataSource.RequestProperti } return dataSource; } - } diff --git a/extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetEngineWrapper.java b/extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetEngineWrapper.java index de292006ecb..8851ac2efe8 100644 --- a/extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetEngineWrapper.java +++ b/extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetEngineWrapper.java @@ -15,60 +15,24 @@ */ package com.google.android.exoplayer2.ext.cronet; -import static java.lang.Math.min; - import android.content.Context; -import androidx.annotation.IntDef; import androidx.annotation.Nullable; -import com.google.android.exoplayer2.util.Log; -import com.google.android.exoplayer2.util.Util; -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; import org.chromium.net.CronetEngine; import org.chromium.net.CronetProvider; -/** A wrapper class for a {@link CronetEngine}. */ +/** + * A wrapper class for a {@link CronetEngine}. + * + * @deprecated Use {@link CronetEngine} directly. See the Android developer + * guide to learn how to instantiate a {@link CronetEngine} for use by your application. You + * can also use {@link CronetUtil#buildCronetEngine} to build a {@link CronetEngine} suitable + * for use by ExoPlayer. + */ +@Deprecated public final class CronetEngineWrapper { - private static final String TAG = "CronetEngineWrapper"; - @Nullable private final CronetEngine cronetEngine; - @CronetEngineSource private final int cronetEngineSource; - - /** - * Source of {@link CronetEngine}. One of {@link #SOURCE_NATIVE}, {@link #SOURCE_GMS}, {@link - * #SOURCE_UNKNOWN}, {@link #SOURCE_USER_PROVIDED} or {@link #SOURCE_UNAVAILABLE}. - */ - @Documented - @Retention(RetentionPolicy.SOURCE) - @IntDef({SOURCE_NATIVE, SOURCE_GMS, SOURCE_UNKNOWN, SOURCE_USER_PROVIDED, SOURCE_UNAVAILABLE}) - public @interface CronetEngineSource {} - /** - * Natively bundled Cronet implementation. - */ - public static final int SOURCE_NATIVE = 0; - /** - * Cronet implementation from GMSCore. - */ - public static final int SOURCE_GMS = 1; - /** - * Other (unknown) Cronet implementation. - */ - public static final int SOURCE_UNKNOWN = 2; - /** - * User-provided Cronet engine. - */ - public static final int SOURCE_USER_PROVIDED = 3; - /** - * No Cronet implementation available. Fallback Http provider is used if possible. - */ - public static final int SOURCE_UNAVAILABLE = 4; /** * Creates a wrapper for a {@link CronetEngine} built using the most suitable {@link @@ -89,53 +53,12 @@ public CronetEngineWrapper(Context context) { * @param context A context. * @param userAgent A default user agent, or {@code null} to use a default user agent of the * {@link CronetEngine}. - * @param preferGMSCoreCronet Whether Cronet from GMSCore should be preferred over natively - * bundled Cronet if both are available. + * @param preferGooglePlayServices Whether Cronet from Google Play Services should be preferred + * over Cronet Embedded, if both are available. */ public CronetEngineWrapper( - Context context, @Nullable String userAgent, boolean preferGMSCoreCronet) { - CronetEngine cronetEngine = null; - @CronetEngineSource int cronetEngineSource = SOURCE_UNAVAILABLE; - List cronetProviders = new ArrayList<>(CronetProvider.getAllProviders(context)); - // Remove disabled and fallback Cronet providers from list - for (int i = cronetProviders.size() - 1; i >= 0; i--) { - if (!cronetProviders.get(i).isEnabled() - || CronetProvider.PROVIDER_NAME_FALLBACK.equals(cronetProviders.get(i).getName())) { - cronetProviders.remove(i); - } - } - // Sort remaining providers by type and version. - CronetProviderComparator providerComparator = new CronetProviderComparator(preferGMSCoreCronet); - Collections.sort(cronetProviders, providerComparator); - for (int i = 0; i < cronetProviders.size() && cronetEngine == null; i++) { - String providerName = cronetProviders.get(i).getName(); - try { - CronetEngine.Builder cronetEngineBuilder = cronetProviders.get(i).createBuilder(); - if (userAgent != null) { - cronetEngineBuilder.setUserAgent(userAgent); - } - cronetEngine = cronetEngineBuilder.build(); - if (providerComparator.isNativeProvider(providerName)) { - cronetEngineSource = SOURCE_NATIVE; - } else if (providerComparator.isGMSCoreProvider(providerName)) { - cronetEngineSource = SOURCE_GMS; - } else { - cronetEngineSource = SOURCE_UNKNOWN; - } - Log.d(TAG, "CronetEngine built using " + providerName); - } catch (SecurityException e) { - Log.w(TAG, "Failed to build CronetEngine. Please check if current process has " - + "android.permission.ACCESS_NETWORK_STATE."); - } catch (UnsatisfiedLinkError e) { - Log.w(TAG, "Failed to link Cronet binaries. Please check if native Cronet binaries are " - + "bundled into your app."); - } - } - if (cronetEngine == null) { - Log.w(TAG, "Cronet not available. Using fallback provider."); - } - this.cronetEngine = cronetEngine; - this.cronetEngineSource = cronetEngineSource; + Context context, @Nullable String userAgent, boolean preferGooglePlayServices) { + cronetEngine = CronetUtil.buildCronetEngine(context, userAgent, preferGooglePlayServices); } /** @@ -145,17 +68,6 @@ public CronetEngineWrapper( */ public CronetEngineWrapper(CronetEngine cronetEngine) { this.cronetEngine = cronetEngine; - this.cronetEngineSource = SOURCE_USER_PROVIDED; - } - - /** - * Returns the source of the wrapped {@link CronetEngine}. - * - * @return A {@link CronetEngineSource} value. - */ - @CronetEngineSource - public int getCronetEngineSource() { - return cronetEngineSource; } /** @@ -167,91 +79,4 @@ public int getCronetEngineSource() { /* package */ CronetEngine getCronetEngine() { return cronetEngine; } - - private static class CronetProviderComparator implements Comparator { - - @Nullable private final String gmsCoreCronetName; - private final boolean preferGMSCoreCronet; - - // Multi-catch can only be used for API 19+ in this case. - // Field#get(null) is blocked by the null-checker, but is safe because the field is static. - @SuppressWarnings({"UseMultiCatch", "nullness:argument.type.incompatible"}) - public CronetProviderComparator(boolean preferGMSCoreCronet) { - // GMSCore CronetProvider classes are only available in some configurations. - // Thus, we use reflection to copy static name. - String gmsCoreVersionString = null; - try { - Class cronetProviderInstallerClass = - Class.forName("com.google.android.gms.net.CronetProviderInstaller"); - Field providerNameField = cronetProviderInstallerClass.getDeclaredField("PROVIDER_NAME"); - gmsCoreVersionString = (String) providerNameField.get(null); - } catch (ClassNotFoundException e) { - // GMSCore CronetProvider not available. - } catch (NoSuchFieldException e) { - // GMSCore CronetProvider not available. - } catch (IllegalAccessException e) { - // GMSCore CronetProvider not available. - } - gmsCoreCronetName = gmsCoreVersionString; - this.preferGMSCoreCronet = preferGMSCoreCronet; - } - - @Override - public int compare(CronetProvider providerLeft, CronetProvider providerRight) { - int typePreferenceLeft = evaluateCronetProviderType(providerLeft.getName()); - int typePreferenceRight = evaluateCronetProviderType(providerRight.getName()); - if (typePreferenceLeft != typePreferenceRight) { - return typePreferenceLeft - typePreferenceRight; - } - return -compareVersionStrings(providerLeft.getVersion(), providerRight.getVersion()); - } - - public boolean isNativeProvider(String providerName) { - return CronetProvider.PROVIDER_NAME_APP_PACKAGED.equals(providerName); - } - - public boolean isGMSCoreProvider(String providerName) { - return gmsCoreCronetName != null && gmsCoreCronetName.equals(providerName); - } - - /** - * Convert Cronet provider name into a sortable preference value. - * Smaller values are preferred. - */ - private int evaluateCronetProviderType(String providerName) { - if (isNativeProvider(providerName)) { - return 1; - } - if (isGMSCoreProvider(providerName)) { - return preferGMSCoreCronet ? 0 : 2; - } - // Unknown provider type. - return -1; - } - - /** - * Compares version strings of format "12.123.35.23". - */ - private static int compareVersionStrings(String versionLeft, String versionRight) { - if (versionLeft == null || versionRight == null) { - return 0; - } - String[] versionStringsLeft = Util.split(versionLeft, "\\."); - String[] versionStringsRight = Util.split(versionRight, "\\."); - int minLength = min(versionStringsLeft.length, versionStringsRight.length); - for (int i = 0; i < minLength; i++) { - if (!versionStringsLeft[i].equals(versionStringsRight[i])) { - try { - int versionIntLeft = Integer.parseInt(versionStringsLeft[i]); - int versionIntRight = Integer.parseInt(versionStringsRight[i]); - return versionIntLeft - versionIntRight; - } catch (NumberFormatException e) { - return 0; - } - } - } - return 0; - } - } - } diff --git a/extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetUtil.java b/extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetUtil.java new file mode 100644 index 00000000000..b448c67e2d2 --- /dev/null +++ b/extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetUtil.java @@ -0,0 +1,163 @@ +/* + * 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 com.google.android.exoplayer2.ext.cronet; + +import static java.lang.Math.min; + +import android.content.Context; +import androidx.annotation.Nullable; +import com.google.android.exoplayer2.upstream.DefaultHttpDataSource; +import com.google.android.exoplayer2.util.Log; +import com.google.android.exoplayer2.util.Util; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import org.chromium.net.CronetEngine; +import org.chromium.net.CronetProvider; + +/** Cronet utility methods. */ +public final class CronetUtil { + + private static final String TAG = "CronetUtil"; + + /** + * Builds a {@link CronetEngine} suitable for use with ExoPlayer. When choosing a {@link + * CronetProvider Cronet provider} to build the {@link CronetEngine}, disabled providers are not + * considered. Neither are fallback providers, since it's more efficient to use {@link + * DefaultHttpDataSource} than it is to use {@link CronetDataSource} with a fallback {@link + * CronetEngine}. + * + *

      Note that it's recommended for applications to create only one instance of {@link + * CronetEngine}, so if your application already has an instance for performing other networking, + * then that instance should be used and calling this method is unnecessary. See the Android developer + * guide to learn more about using Cronet for network operations. + * + * @param context A context. + * @param userAgent A default user agent, or {@code null} to use a default user agent of the + * {@link CronetEngine}. + * @param preferGooglePlayServices Whether Cronet from Google Play Services should be preferred + * over Cronet Embedded, if both are available. + * @return The {@link CronetEngine}, or {@code null} if no suitable engine could be built. + */ + @Nullable + public static CronetEngine buildCronetEngine( + Context context, @Nullable String userAgent, boolean preferGooglePlayServices) { + List cronetProviders = new ArrayList<>(CronetProvider.getAllProviders(context)); + // Remove disabled and fallback Cronet providers from list. + for (int i = cronetProviders.size() - 1; i >= 0; i--) { + if (!cronetProviders.get(i).isEnabled() + || CronetProvider.PROVIDER_NAME_FALLBACK.equals(cronetProviders.get(i).getName())) { + cronetProviders.remove(i); + } + } + // Sort remaining providers by type and version. + CronetProviderComparator providerComparator = + new CronetProviderComparator(preferGooglePlayServices); + Collections.sort(cronetProviders, providerComparator); + for (int i = 0; i < cronetProviders.size(); i++) { + String providerName = cronetProviders.get(i).getName(); + try { + CronetEngine.Builder cronetEngineBuilder = cronetProviders.get(i).createBuilder(); + if (userAgent != null) { + cronetEngineBuilder.setUserAgent(userAgent); + } + CronetEngine cronetEngine = cronetEngineBuilder.build(); + Log.d(TAG, "CronetEngine built using " + providerName); + return cronetEngine; + } catch (SecurityException e) { + Log.w( + TAG, + "Failed to build CronetEngine. Please check that the process has " + + "android.permission.ACCESS_NETWORK_STATE."); + } catch (UnsatisfiedLinkError e) { + Log.w( + TAG, + "Failed to link Cronet binaries. Please check that native Cronet binaries are" + + "bundled into your app."); + } + } + Log.w(TAG, "CronetEngine could not be built."); + return null; + } + + private CronetUtil() {} + + private static class CronetProviderComparator implements Comparator { + + /* + * Copy of com.google.android.gms.net.CronetProviderInstaller.PROVIDER_NAME. We have our own + * copy because GMSCore CronetProvider classes are unavailable in some (internal to Google) + * build configurations. + */ + private static final String GOOGLE_PLAY_SERVICES_PROVIDER_NAME = + "Google-Play-Services-Cronet-Provider"; + + private final boolean preferGooglePlayServices; + + public CronetProviderComparator(boolean preferGooglePlayServices) { + this.preferGooglePlayServices = preferGooglePlayServices; + } + + @Override + public int compare(CronetProvider providerLeft, CronetProvider providerRight) { + int providerComparison = getPriority(providerLeft) - getPriority(providerRight); + if (providerComparison != 0) { + return providerComparison; + } + return -compareVersionStrings(providerLeft.getVersion(), providerRight.getVersion()); + } + + /** + * Returns the priority score for a Cronet provider, where a smaller score indicates higher + * priority. + */ + private int getPriority(CronetProvider provider) { + String providerName = provider.getName(); + if (CronetProvider.PROVIDER_NAME_APP_PACKAGED.equals(providerName)) { + return 1; + } else if (GOOGLE_PLAY_SERVICES_PROVIDER_NAME.equals(providerName)) { + return preferGooglePlayServices ? 0 : 2; + } else { + return 3; + } + } + + /** Compares version strings of format "12.123.35.23". */ + private static int compareVersionStrings( + @Nullable String versionLeft, @Nullable String versionRight) { + if (versionLeft == null || versionRight == null) { + return 0; + } + String[] versionStringsLeft = Util.split(versionLeft, "\\."); + String[] versionStringsRight = Util.split(versionRight, "\\."); + int minLength = min(versionStringsLeft.length, versionStringsRight.length); + for (int i = 0; i < minLength; i++) { + if (!versionStringsLeft[i].equals(versionStringsRight[i])) { + try { + int versionIntLeft = Integer.parseInt(versionStringsLeft[i]); + int versionIntRight = Integer.parseInt(versionStringsRight[i]); + return versionIntLeft - versionIntRight; + } catch (NumberFormatException e) { + return 0; + } + } + } + return 0; + } + } +} diff --git a/extensions/cronet/src/test/java/com/google/android/exoplayer2/ext/cronet/CronetDataSourceTest.java b/extensions/cronet/src/test/java/com/google/android/exoplayer2/ext/cronet/CronetDataSourceTest.java index 5255163f8ee..e2e278ad009 100644 --- a/extensions/cronet/src/test/java/com/google/android/exoplayer2/ext/cronet/CronetDataSourceTest.java +++ b/extensions/cronet/src/test/java/com/google/android/exoplayer2/ext/cronet/CronetDataSourceTest.java @@ -18,8 +18,10 @@ import static com.google.common.truth.Truth.assertThat; import static java.lang.Math.min; import static java.util.concurrent.TimeUnit.SECONDS; +import static org.chromium.net.NetworkException.ERROR_HOSTNAME_NOT_RESOLVED; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; @@ -33,7 +35,6 @@ import android.net.Uri; import android.os.ConditionVariable; import android.os.SystemClock; -import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.upstream.DataSpec; @@ -71,6 +72,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatchers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -98,7 +100,6 @@ public final class CronetDataSourceTest { @Mock private UrlRequest.Builder mockUrlRequestBuilder; @Mock private UrlRequest mockUrlRequest; @Mock private TransferListener mockTransferListener; - @Mock private NetworkException mockNetworkException; @Mock private CronetEngine mockCronetEngine; private ExecutorService executorService; @@ -116,7 +117,7 @@ public void setUp() { executorService = Executors.newSingleThreadExecutor(); dataSourceUnderTest = (CronetDataSource) - new CronetDataSource.Factory(new CronetEngineWrapper(mockCronetEngine), executorService) + new CronetDataSource.Factory(mockCronetEngine, executorService) .setConnectionTimeoutMs(TEST_CONNECT_TIMEOUT_MS) .setReadTimeoutMs(TEST_READ_TIMEOUT_MS) .setResetTimeoutOnRedirects(true) @@ -126,6 +127,7 @@ public void setUp() { when(mockCronetEngine.newUrlRequestBuilder( anyString(), any(UrlRequest.Callback.class), any(Executor.class))) .thenReturn(mockUrlRequestBuilder); + when(mockUrlRequestBuilder.setPriority(anyInt())).thenReturn(mockUrlRequestBuilder); when(mockUrlRequestBuilder.allowDirectExecutor()).thenReturn(mockUrlRequestBuilder); when(mockUrlRequestBuilder.build()).thenReturn(mockUrlRequest); mockStatusResponse(); @@ -240,7 +242,11 @@ public void callbackFromPreviousRequest() throws HttpDataSourceException { invocation -> { // Invoke the callback for the previous request. dataSourceUnderTest.urlRequestCallback.onFailed( - mockUrlRequest, testUrlResponseInfo, mockNetworkException); + mockUrlRequest, + testUrlResponseInfo, + createNetworkException( + /* errorCode= */ Integer.MAX_VALUE, + /* cause= */ new IllegalArgumentException())); dataSourceUnderTest.urlRequestCallback.onResponseStarted( mockUrlRequest2, testUrlResponseInfo); return null; @@ -334,7 +340,8 @@ public void requestOpenGzippedCompressedReturnsDataSpecLength() throws HttpDataS @Test public void requestOpenFail() { - mockResponseStartFailure(); + mockResponseStartFailure( + /* errorCode= */ Integer.MAX_VALUE, /* cause= */ new IllegalArgumentException()); try { dataSourceUnderTest.open(testDataSpec); @@ -370,9 +377,8 @@ public void open_ifBodyIsSetWithoutContentTypeHeader_fails() { @Test public void requestOpenFailDueToDnsFailure() { - mockResponseStartFailure(); - when(mockNetworkException.getErrorCode()) - .thenReturn(NetworkException.ERROR_HOSTNAME_NOT_RESOLVED); + mockResponseStartFailure( + /* errorCode= */ ERROR_HOSTNAME_NOT_RESOLVED, /* cause= */ new UnknownHostException()); try { dataSourceUnderTest.open(testDataSpec); @@ -1151,7 +1157,7 @@ public void run() { @Test public void redirectParseAndAttachCookie_dataSourceDoesNotHandleSetCookie_followsRedirect() throws HttpDataSourceException { - mockSingleRedirectSuccess(); + mockSingleRedirectSuccess(/*responseCode=*/ 300); mockFollowRedirectSuccess(); testResponseHeader.put("Set-Cookie", "testcookie=testcookie; Path=/video"); @@ -1167,7 +1173,7 @@ public void redirectParseAndAttachCookie_dataSourceDoesNotHandleSetCookie_follow throws HttpDataSourceException { dataSourceUnderTest = (CronetDataSource) - new CronetDataSource.Factory(new CronetEngineWrapper(mockCronetEngine), executorService) + new CronetDataSource.Factory(mockCronetEngine, executorService) .setConnectionTimeoutMs(TEST_CONNECT_TIMEOUT_MS) .setReadTimeoutMs(TEST_READ_TIMEOUT_MS) .setResetTimeoutOnRedirects(true) @@ -1176,7 +1182,7 @@ public void redirectParseAndAttachCookie_dataSourceDoesNotHandleSetCookie_follow dataSourceUnderTest.addTransferListener(mockTransferListener); dataSourceUnderTest.setRequestProperty("Content-Type", TEST_CONTENT_TYPE); - mockSingleRedirectSuccess(); + mockSingleRedirectSuccess(/*responseCode=*/ 300); testResponseHeader.put("Set-Cookie", "testcookie=testcookie; Path=/video"); @@ -1195,7 +1201,7 @@ public void redirectParseAndAttachCookie_dataSourceDoesNotHandleSetCookie_follow testDataSpec = new DataSpec(Uri.parse(TEST_URL), 1000, 5000); dataSourceUnderTest = (CronetDataSource) - new CronetDataSource.Factory(new CronetEngineWrapper(mockCronetEngine), executorService) + new CronetDataSource.Factory(mockCronetEngine, executorService) .setConnectionTimeoutMs(TEST_CONNECT_TIMEOUT_MS) .setReadTimeoutMs(TEST_READ_TIMEOUT_MS) .setResetTimeoutOnRedirects(true) @@ -1204,7 +1210,7 @@ public void redirectParseAndAttachCookie_dataSourceDoesNotHandleSetCookie_follow dataSourceUnderTest.addTransferListener(mockTransferListener); dataSourceUnderTest.setRequestProperty("Content-Type", TEST_CONTENT_TYPE); - mockSingleRedirectSuccess(); + mockSingleRedirectSuccess(/*responseCode=*/ 300); mockReadSuccess(0, 1000); testResponseHeader.put("Set-Cookie", "testcookie=testcookie; Path=/video"); @@ -1219,7 +1225,7 @@ public void redirectParseAndAttachCookie_dataSourceDoesNotHandleSetCookie_follow @Test public void redirectNoSetCookieFollowsRedirect() throws HttpDataSourceException { - mockSingleRedirectSuccess(); + mockSingleRedirectSuccess(/*responseCode=*/ 300); mockFollowRedirectSuccess(); dataSourceUnderTest.open(testDataSpec); @@ -1232,14 +1238,14 @@ public void redirectNoSetCookieFollowsRedirect_dataSourceHandlesSetCookie() throws HttpDataSourceException { dataSourceUnderTest = (CronetDataSource) - new CronetDataSource.Factory(new CronetEngineWrapper(mockCronetEngine), executorService) + new CronetDataSource.Factory(mockCronetEngine, executorService) .setConnectionTimeoutMs(TEST_CONNECT_TIMEOUT_MS) .setReadTimeoutMs(TEST_READ_TIMEOUT_MS) .setResetTimeoutOnRedirects(true) .setHandleSetCookieRequests(true) .createDataSource(); dataSourceUnderTest.addTransferListener(mockTransferListener); - mockSingleRedirectSuccess(); + mockSingleRedirectSuccess(/*responseCode=*/ 300); mockFollowRedirectSuccess(); dataSourceUnderTest.open(testDataSpec); @@ -1247,6 +1253,66 @@ public void redirectNoSetCookieFollowsRedirect_dataSourceHandlesSetCookie() verify(mockUrlRequest).followRedirect(); } + @Test + public void redirectPostFollowRedirect() throws HttpDataSourceException { + mockSingleRedirectSuccess(/*responseCode=*/ 302); + mockFollowRedirectSuccess(); + dataSourceUnderTest.setRequestProperty("Content-Type", TEST_CONTENT_TYPE); + + dataSourceUnderTest.open(testPostDataSpec); + + verify(mockUrlRequest).followRedirect(); + } + + @Test + public void redirect302ChangesPostToGet() throws HttpDataSourceException { + dataSourceUnderTest = + (CronetDataSource) + new CronetDataSource.Factory(mockCronetEngine, executorService) + .setConnectionTimeoutMs(TEST_CONNECT_TIMEOUT_MS) + .setReadTimeoutMs(TEST_READ_TIMEOUT_MS) + .setResetTimeoutOnRedirects(true) + .setKeepPostFor302Redirects(false) + .setHandleSetCookieRequests(true) + .createDataSource(); + mockSingleRedirectSuccess(/*responseCode=*/ 302); + dataSourceUnderTest.setRequestProperty("Content-Type", TEST_CONTENT_TYPE); + testResponseHeader.put("Set-Cookie", "testcookie=testcookie; Path=/video"); + + dataSourceUnderTest.open(testPostDataSpec); + + verify(mockUrlRequest, never()).followRedirect(); + ArgumentCaptor methodCaptor = ArgumentCaptor.forClass(String.class); + verify(mockUrlRequestBuilder, times(2)).setHttpMethod(methodCaptor.capture()); + assertThat(methodCaptor.getAllValues()).containsExactly("POST", "GET").inOrder(); + } + + @Test + public void redirectKeeps302Post() throws HttpDataSourceException { + dataSourceUnderTest = + (CronetDataSource) + new CronetDataSource.Factory(mockCronetEngine, executorService) + .setConnectionTimeoutMs(TEST_CONNECT_TIMEOUT_MS) + .setReadTimeoutMs(TEST_READ_TIMEOUT_MS) + .setResetTimeoutOnRedirects(true) + .setKeepPostFor302Redirects(true) + .createDataSource(); + mockSingleRedirectSuccess(/*responseCode=*/ 302); + dataSourceUnderTest.setRequestProperty("Content-Type", TEST_CONTENT_TYPE); + + dataSourceUnderTest.open(testPostDataSpec); + + verify(mockUrlRequest, never()).followRedirect(); + ArgumentCaptor methodCaptor = ArgumentCaptor.forClass(String.class); + verify(mockUrlRequestBuilder, times(2)).setHttpMethod(methodCaptor.capture()); + assertThat(methodCaptor.getAllValues()).containsExactly("POST", "POST").inOrder(); + ArgumentCaptor postBodyCaptor = + ArgumentCaptor.forClass(ByteArrayUploadDataProvider.class); + verify(mockUrlRequestBuilder, times(2)).setUploadDataProvider(postBodyCaptor.capture(), any()); + assertThat(postBodyCaptor.getAllValues().get(0).getLength()).isEqualTo(TEST_POST_BODY.length); + assertThat(postBodyCaptor.getAllValues().get(1).getLength()).isEqualTo(TEST_POST_BODY.length); + } + @Test public void exceptionFromTransferListener() throws HttpDataSourceException { mockResponseStartSuccess(); @@ -1383,6 +1449,7 @@ public void allowDirectExecutor() throws HttpDataSourceException { verify(mockUrlRequestBuilder).allowDirectExecutor(); } + @SuppressWarnings("deprecation") // Tests deprecated fallback functionality. @Test public void factorySetFallbackHttpDataSourceFactory_cronetNotAvailable_usesFallbackFactory() throws HttpDataSourceException, InterruptedException { @@ -1403,10 +1470,11 @@ public void factorySetFallbackHttpDataSourceFactory_cronetNotAvailable_usesFallb assertThat(headers.get("user-agent")).isEqualTo("customFallbackFactoryUserAgent"); } + @SuppressWarnings("deprecation") // Tests deprecated fallback functionality. @Test public void factory_noFallbackFactoryCronetNotAvailable_delegateTransferListenerToInternalFallbackFactory() - throws HttpDataSourceException, InterruptedException { + throws HttpDataSourceException { MockWebServer mockWebServer = new MockWebServer(); mockWebServer.enqueue(new MockResponse()); CronetEngineWrapper cronetEngineWrapper = new CronetEngineWrapper((CronetEngine) null); @@ -1425,14 +1493,14 @@ public void factorySetFallbackHttpDataSourceFactory_cronetNotAvailable_usesFallb .onTransferStart(eq(dataSourceUnderTest), eq(dataSpec), /* isNetwork= */ eq(true)); } + @SuppressWarnings("deprecation") // Tests deprecated fallback functionality. @Test public void factory_noFallbackFactoryCronetNotAvailable_delegateDefaultRequestPropertiesToInternalFallbackFactory() throws HttpDataSourceException, InterruptedException { MockWebServer mockWebServer = new MockWebServer(); mockWebServer.enqueue(new MockResponse()); - CronetEngineWrapper cronetEngineWrapper = - new CronetEngineWrapper(ApplicationProvider.getApplicationContext()); + CronetEngineWrapper cronetEngineWrapper = new CronetEngineWrapper((CronetEngine) null); Map defaultRequestProperties = new HashMap<>(); defaultRequestProperties.put("0", "defaultRequestProperty0"); HttpDataSource dataSourceUnderTest = @@ -1448,6 +1516,7 @@ public void factorySetFallbackHttpDataSourceFactory_cronetNotAvailable_usesFallb assertThat(dataSourceUnderTest).isInstanceOf(DefaultHttpDataSource.class); } + @SuppressWarnings("deprecation") // Tests deprecated fallback functionality. @Test public void factory_noFallbackFactoryCronetNotAvailable_delegateDefaultRequestPropertiesToInternalFallbackFactoryAfterCreation() @@ -1512,14 +1581,14 @@ private void mockResponseStartRedirect() { .start(); } - private void mockSingleRedirectSuccess() { + private void mockSingleRedirectSuccess(int responseCode) { doAnswer( invocation -> { if (!redirectCalled) { redirectCalled = true; dataSourceUnderTest.urlRequestCallback.onRedirectReceived( mockUrlRequest, - createUrlResponseInfoWithUrl("http://example.com/video", 300), + createUrlResponseInfoWithUrl("http://example.com/video", responseCode), "http://example.com/video/redirect"); } else { dataSourceUnderTest.urlRequestCallback.onResponseStarted( @@ -1542,13 +1611,13 @@ private void mockFollowRedirectSuccess() { .followRedirect(); } - private void mockResponseStartFailure() { + private void mockResponseStartFailure(int errorCode, Throwable cause) { doAnswer( invocation -> { dataSourceUnderTest.urlRequestCallback.onFailed( mockUrlRequest, createUrlResponseInfo(500), // statusCode - mockNetworkException); + createNetworkException(errorCode, cause)); return null; }) .when(mockUrlRequest) @@ -1583,7 +1652,9 @@ private void mockReadFailure() { dataSourceUnderTest.urlRequestCallback.onFailed( mockUrlRequest, createUrlResponseInfo(500), // statusCode - mockNetworkException); + createNetworkException( + /* errorCode= */ Integer.MAX_VALUE, + /* cause= */ new IllegalArgumentException())); return null; }) .when(mockUrlRequest) @@ -1661,4 +1732,23 @@ private static void setSystemClockInMsAndTriggerPendingMessages(long nowMs) { SystemClock.setCurrentTimeMillis(nowMs); ShadowLooper.idleMainLooper(); } + + private static NetworkException createNetworkException(int errorCode, Throwable cause) { + return new NetworkException("", cause) { + @Override + public int getErrorCode() { + return errorCode; + } + + @Override + public int getCronetInternalErrorCode() { + return errorCode; + } + + @Override + public boolean immediatelyRetryable() { + return false; + } + }; + } } diff --git a/extensions/ffmpeg/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioDecoder.java b/extensions/ffmpeg/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioDecoder.java index eac96a9a31b..1feeffeef90 100644 --- a/extensions/ffmpeg/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioDecoder.java +++ b/extensions/ffmpeg/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioDecoder.java @@ -36,10 +36,8 @@ private static final int OUTPUT_BUFFER_SIZE_16BIT = 65536; private static final int OUTPUT_BUFFER_SIZE_32BIT = OUTPUT_BUFFER_SIZE_16BIT * 2; - // LINT.IfChange private static final int AUDIO_DECODER_ERROR_INVALID_DATA = -1; private static final int AUDIO_DECODER_ERROR_OTHER = -2; - // LINT.ThenChange(../../../../../../../jni/ffmpeg_jni.cc) private final String codecName; @Nullable private final byte[] extraData; diff --git a/extensions/ffmpeg/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioRenderer.java b/extensions/ffmpeg/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioRenderer.java index 878476d1a1a..3991f53a38c 100644 --- a/extensions/ffmpeg/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioRenderer.java +++ b/extensions/ffmpeg/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioRenderer.java @@ -79,10 +79,7 @@ public FfmpegAudioRenderer( @Nullable Handler eventHandler, @Nullable AudioRendererEventListener eventListener, AudioSink audioSink) { - super( - eventHandler, - eventListener, - audioSink); + super(eventHandler, eventListener, audioSink); } @Override diff --git a/extensions/ffmpeg/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegLibrary.java b/extensions/ffmpeg/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegLibrary.java index 798c936e2e3..abd184b59e3 100644 --- a/extensions/ffmpeg/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegLibrary.java +++ b/extensions/ffmpeg/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegLibrary.java @@ -50,9 +50,7 @@ public static void setLibraries(String... libraries) { LOADER.setLibraries(libraries); } - /** - * Returns whether the underlying library is available, loading it if necessary. - */ + /** Returns whether the underlying library is available, loading it if necessary. */ public static boolean isAvailable() { return LOADER.isAvailable(); } diff --git a/extensions/ffmpeg/src/main/jni/ffmpeg_jni.cc b/extensions/ffmpeg/src/main/jni/ffmpeg_jni.cc index 7738e5c2d52..947d535c7d3 100644 --- a/extensions/ffmpeg/src/main/jni/ffmpeg_jni.cc +++ b/extensions/ffmpeg/src/main/jni/ffmpeg_jni.cc @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include #include #include -#include extern "C" { #ifdef __cplusplus @@ -33,8 +33,8 @@ extern "C" { } #define LOG_TAG "ffmpeg_jni" -#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, \ - __VA_ARGS__)) +#define LOGE(...) \ + ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) #define LIBRARY_FUNC(RETURN_TYPE, NAME, ...) \ extern "C" { \ @@ -63,15 +63,13 @@ static const AVSampleFormat OUTPUT_FORMAT_PCM_16BIT = AV_SAMPLE_FMT_S16; // Output format corresponding to AudioFormat.ENCODING_PCM_FLOAT. static const AVSampleFormat OUTPUT_FORMAT_PCM_FLOAT = AV_SAMPLE_FMT_FLT; -// LINT.IfChange static const int AUDIO_DECODER_ERROR_INVALID_DATA = -1; static const int AUDIO_DECODER_ERROR_OTHER = -2; -// LINT.ThenChange(../java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioDecoder.java) /** * Returns the AVCodec with the specified name, or NULL if it is not available. */ -AVCodec *getCodecByName(JNIEnv* env, jstring codecName); +AVCodec *getCodecByName(JNIEnv *env, jstring codecName); /** * Allocates and opens a new AVCodecContext for the specified codec, passing the @@ -102,7 +100,7 @@ void releaseContext(AVCodecContext *context); jint JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv *env; - if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { + if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { return -1; } avcodec_register_all(); @@ -151,13 +149,13 @@ AUDIO_DECODER_FUNC(jint, ffmpegDecode, jlong context, jobject inputData, LOGE("Invalid output buffer length: %d", outputSize); return -1; } - uint8_t *inputBuffer = (uint8_t *) env->GetDirectBufferAddress(inputData); - uint8_t *outputBuffer = (uint8_t *) env->GetDirectBufferAddress(outputData); + uint8_t *inputBuffer = (uint8_t *)env->GetDirectBufferAddress(inputData); + uint8_t *outputBuffer = (uint8_t *)env->GetDirectBufferAddress(outputData); AVPacket packet; av_init_packet(&packet); packet.data = inputBuffer; packet.size = inputSize; - return decodePacket((AVCodecContext *) context, &packet, outputBuffer, + return decodePacket((AVCodecContext *)context, &packet, outputBuffer, outputSize); } @@ -166,7 +164,7 @@ AUDIO_DECODER_FUNC(jint, ffmpegGetChannelCount, jlong context) { LOGE("Context must be non-NULL."); return -1; } - return ((AVCodecContext *) context)->channels; + return ((AVCodecContext *)context)->channels; } AUDIO_DECODER_FUNC(jint, ffmpegGetSampleRate, jlong context) { @@ -174,11 +172,11 @@ AUDIO_DECODER_FUNC(jint, ffmpegGetSampleRate, jlong context) { LOGE("Context must be non-NULL."); return -1; } - return ((AVCodecContext *) context)->sample_rate; + return ((AVCodecContext *)context)->sample_rate; } AUDIO_DECODER_FUNC(jlong, ffmpegReset, jlong jContext, jbyteArray extraData) { - AVCodecContext *context = (AVCodecContext *) jContext; + AVCodecContext *context = (AVCodecContext *)jContext; if (!context) { LOGE("Tried to reset without a context."); return 0L; @@ -202,16 +200,16 @@ AUDIO_DECODER_FUNC(jlong, ffmpegReset, jlong jContext, jbyteArray extraData) { } avcodec_flush_buffers(context); - return (jlong) context; + return (jlong)context; } AUDIO_DECODER_FUNC(void, ffmpegRelease, jlong context) { if (context) { - releaseContext((AVCodecContext *) context); + releaseContext((AVCodecContext *)context); } } -AVCodec *getCodecByName(JNIEnv* env, jstring codecName) { +AVCodec *getCodecByName(JNIEnv *env, jstring codecName) { if (!codecName) { return NULL; } @@ -235,13 +233,13 @@ AVCodecContext *createContext(JNIEnv *env, AVCodec *codec, jbyteArray extraData, jsize size = env->GetArrayLength(extraData); context->extradata_size = size; context->extradata = - (uint8_t *) av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE); + (uint8_t *)av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE); if (!context->extradata) { LOGE("Failed to allocate extradata."); releaseContext(context); return NULL; } - env->GetByteArrayRegion(extraData, 0, size, (jbyte *) context->extradata); + env->GetByteArrayRegion(extraData, 0, size, (jbyte *)context->extradata); } if (context->codec_id == AV_CODEC_ID_PCM_MULAW || context->codec_id == AV_CODEC_ID_PCM_ALAW) { @@ -301,14 +299,14 @@ int decodePacket(AVCodecContext *context, AVPacket *packet, resampleContext = (SwrContext *)context->opaque; } else { resampleContext = swr_alloc(); - av_opt_set_int(resampleContext, "in_channel_layout", channelLayout, 0); + av_opt_set_int(resampleContext, "in_channel_layout", channelLayout, 0); av_opt_set_int(resampleContext, "out_channel_layout", channelLayout, 0); av_opt_set_int(resampleContext, "in_sample_rate", sampleRate, 0); av_opt_set_int(resampleContext, "out_sample_rate", sampleRate, 0); av_opt_set_int(resampleContext, "in_sample_fmt", sampleFormat, 0); // The output format is always the requested format. av_opt_set_int(resampleContext, "out_sample_fmt", - context->request_sample_fmt, 0); + context->request_sample_fmt, 0); result = swr_init(resampleContext); if (result < 0) { logError("swr_init", result); @@ -347,7 +345,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet, } void logError(const char *functionName, int errorNumber) { - char *buffer = (char *) malloc(ERROR_STRING_BUFFER_LENGTH * sizeof(char)); + char *buffer = (char *)malloc(ERROR_STRING_BUFFER_LENGTH * sizeof(char)); av_strerror(errorNumber, buffer, ERROR_STRING_BUFFER_LENGTH); LOGE("Error in %s: %s", functionName, buffer); free(buffer); @@ -364,4 +362,3 @@ void releaseContext(AVCodecContext *context) { } avcodec_free_context(&context); } - diff --git a/extensions/flac/src/androidTest/java/com/google/android/exoplayer2/ext/flac/FlacPlaybackTest.java b/extensions/flac/src/androidTest/java/com/google/android/exoplayer2/ext/flac/FlacPlaybackTest.java index a52f8088b36..c2cfc4547d5 100644 --- a/extensions/flac/src/androidTest/java/com/google/android/exoplayer2/ext/flac/FlacPlaybackTest.java +++ b/extensions/flac/src/androidTest/java/com/google/android/exoplayer2/ext/flac/FlacPlaybackTest.java @@ -23,8 +23,8 @@ import androidx.annotation.Nullable; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; -import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.RenderersFactory; @@ -96,7 +96,7 @@ private static class TestPlaybackRunnable implements Player.Listener, Runnable { private final AudioSink audioSink; @Nullable private SimpleExoPlayer player; - @Nullable private ExoPlaybackException playbackException; + @Nullable private PlaybackException playbackException; public TestPlaybackRunnable(Uri uri, Context context, AudioSink audioSink) { this.uri = uri; @@ -129,7 +129,7 @@ public void run() { } @Override - public void onPlayerError(ExoPlaybackException error) { + public void onPlayerError(PlaybackException error) { playbackException = error; } diff --git a/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacDecoderJni.java b/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacDecoderJni.java index af4e5710249..c4e5e4e7105 100644 --- a/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacDecoderJni.java +++ b/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacDecoderJni.java @@ -28,9 +28,7 @@ import java.io.IOException; import java.nio.ByteBuffer; -/** - * JNI wrapper for the libflac Flac decoder. - */ +/** JNI wrapper for the libflac Flac decoder. */ /* package */ final class FlacDecoderJni { /** Exception to be thrown if {@link #decodeSample(ByteBuffer)} fails to decode a frame. */ @@ -150,7 +148,8 @@ public int read(ByteBuffer target) throws IOException { public FlacStreamMetadata decodeStreamMetadata() throws IOException { FlacStreamMetadata streamMetadata = flacDecodeMetadata(nativeDecoderContext); if (streamMetadata == null) { - throw new ParserException("Failed to decode stream metadata"); + throw ParserException.createForMalformedContainer( + "Failed to decode stream metadata", /* cause= */ null); } return streamMetadata; } @@ -196,9 +195,7 @@ public void decodeSample(ByteBuffer output) throws IOException, FlacFrameDecodeE } } - /** - * Returns the position of the next data to be decoded, or -1 in case of error. - */ + /** Returns the position of the next data to be decoded, or -1 in case of error. */ public long getDecodePosition() { return flacGetDecodePosition(nativeDecoderContext); } @@ -303,5 +300,4 @@ private int readFromExtractorInput( private native void flacReset(long context, long newPosition); private native void flacRelease(long context); - } diff --git a/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java b/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java index 99e74d64bb4..715489ccde9 100644 --- a/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java +++ b/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java @@ -51,7 +51,6 @@ public final class FlacExtractor implements Extractor { /** Factory that returns one extractor which is a {@link FlacExtractor}. */ public static final ExtractorsFactory FACTORY = () -> new Extractor[] {new FlacExtractor()}; - // LINT.IfChange /* * Flags in the two FLAC extractors should be kept in sync. If we ever change this then * DefaultExtractorsFactory will need modifying, because it currently assumes this is the case. @@ -73,7 +72,6 @@ public final class FlacExtractor implements Extractor { */ public static final int FLAG_DISABLE_ID3_METADATA = com.google.android.exoplayer2.extractor.flac.FlacExtractor.FLAG_DISABLE_ID3_METADATA; - // LINT.ThenChange(../../../../../../../../../../extractor/src/main/java/com/google/android/exoplayer2/extractor/flac/FlacExtractor.java) private final ParsableByteArray outputBuffer; private final boolean id3MetadataDisabled; @@ -179,7 +177,7 @@ public void release() { } @EnsuresNonNull({"decoderJni", "extractorOutput", "trackOutput"}) // Ensures initialized. - @SuppressWarnings({"contracts.postcondition.not.satisfied"}) + @SuppressWarnings("nullness:contracts.postcondition") private FlacDecoderJni initDecoderJni(ExtractorInput input) { FlacDecoderJni decoderJni = Assertions.checkNotNull(this.decoderJni); decoderJni.setData(input); @@ -188,7 +186,7 @@ private FlacDecoderJni initDecoderJni(ExtractorInput input) { @RequiresNonNull({"decoderJni", "extractorOutput", "trackOutput"}) // Requires initialized. @EnsuresNonNull({"streamMetadata", "outputFrameHolder"}) // Ensures stream metadata decoded. - @SuppressWarnings({"contracts.postcondition.not.satisfied"}) + @SuppressWarnings("nullness:contracts.postcondition") private void decodeStreamMetadata(ExtractorInput input) throws IOException { if (streamMetadataDecoded) { return; diff --git a/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacLibrary.java b/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacLibrary.java index 8a2b14d3662..6ce93ef56d5 100644 --- a/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacLibrary.java +++ b/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacLibrary.java @@ -40,11 +40,8 @@ public static void setLibraries(String... libraries) { LOADER.setLibraries(libraries); } - /** - * Returns whether the underlying library is available, loading it if necessary. - */ + /** Returns whether the underlying library is available, loading it if necessary. */ public static boolean isAvailable() { return LOADER.isAvailable(); } - } diff --git a/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/LibflacAudioRenderer.java b/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/LibflacAudioRenderer.java index 4fea5ffa53a..7b74d3bfd75 100644 --- a/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/LibflacAudioRenderer.java +++ b/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/LibflacAudioRenderer.java @@ -67,10 +67,7 @@ public LibflacAudioRenderer( @Nullable Handler eventHandler, @Nullable AudioRendererEventListener eventListener, AudioSink audioSink) { - super( - eventHandler, - eventListener, - audioSink); + super(eventHandler, eventListener, audioSink); } @Override diff --git a/extensions/flac/src/main/jni/flac_jni.cc b/extensions/flac/src/main/jni/flac_jni.cc index 50db06f436a..c41bb98ef00 100644 --- a/extensions/flac/src/main/jni/flac_jni.cc +++ b/extensions/flac/src/main/jni/flac_jni.cc @@ -29,13 +29,13 @@ #define ALOGV(...) \ ((void)__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) -#define DECODER_FUNC(RETURN_TYPE, NAME, ...) \ - extern "C" { \ - JNIEXPORT RETURN_TYPE \ +#define DECODER_FUNC(RETURN_TYPE, NAME, ...) \ + extern "C" { \ + JNIEXPORT RETURN_TYPE \ Java_com_google_android_exoplayer2_ext_flac_FlacDecoderJni_##NAME( \ - JNIEnv *env, jobject thiz, ##__VA_ARGS__); \ - } \ - JNIEXPORT RETURN_TYPE \ + JNIEnv *env, jobject thiz, ##__VA_ARGS__); \ + } \ + JNIEXPORT RETURN_TYPE \ Java_com_google_android_exoplayer2_ext_flac_FlacDecoderJni_##NAME( \ JNIEnv *env, jobject thiz, ##__VA_ARGS__) diff --git a/extensions/flac/src/main/jni/flac_parser.cc b/extensions/flac/src/main/jni/flac_parser.cc index c368647420f..c932b3515e1 100644 --- a/extensions/flac/src/main/jni/flac_parser.cc +++ b/extensions/flac/src/main/jni/flac_parser.cc @@ -16,9 +16,8 @@ #include "include/flac_parser.h" -#include - #include +#include #include #include @@ -431,7 +430,7 @@ bool FLACParser::getSeekPositions(int64_t timeUs, targetSampleNumber = totalSamples - 1; } - FLAC__StreamMetadata_SeekPoint* points = mSeekTable->points; + FLAC__StreamMetadata_SeekPoint *points = mSeekTable->points; unsigned length = mSeekTable->num_points; for (unsigned i = length; i != 0; i--) { diff --git a/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/GvrAudioProcessor.java b/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/GvrAudioProcessor.java index 041ca09db4e..0fc6f54285f 100644 --- a/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/GvrAudioProcessor.java +++ b/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/GvrAudioProcessor.java @@ -64,8 +64,8 @@ public GvrAudioProcessor() { } /** - * Updates the listener head orientation. May be called on any thread. See - * {@code GvrAudioSurround.updateNativeOrientation}. + * Updates the listener head orientation. May be called on any thread. See {@code + * GvrAudioSurround.updateNativeOrientation}. * * @param w The w component of the quaternion. * @param x The x component of the quaternion. @@ -113,8 +113,9 @@ public synchronized AudioFormat configure(AudioFormat inputAudioFormat) throw new UnhandledAudioFormatException(inputAudioFormat); } if (buffer == EMPTY_BUFFER) { - buffer = ByteBuffer.allocateDirect(FRAMES_PER_OUTPUT_BUFFER * OUTPUT_FRAME_SIZE) - .order(ByteOrder.nativeOrder()); + buffer = + ByteBuffer.allocateDirect(FRAMES_PER_OUTPUT_BUFFER * OUTPUT_FRAME_SIZE) + .order(ByteOrder.nativeOrder()); } pendingInputAudioFormat = inputAudioFormat; return new AudioFormat(inputAudioFormat.sampleRate, OUTPUT_CHANNEL_COUNT, C.ENCODING_PCM_16BIT); @@ -126,11 +127,12 @@ public boolean isActive() { } @Override - public void queueInput(ByteBuffer input) { - int position = input.position(); + public void queueInput(ByteBuffer inputBuffer) { + int position = inputBuffer.position(); Assertions.checkNotNull(gvrAudioSurround); - int readBytes = gvrAudioSurround.addInput(input, position, input.limit() - position); - input.position(position + readBytes); + int readBytes = + gvrAudioSurround.addInput(inputBuffer, position, inputBuffer.limit() - position); + inputBuffer.position(position + readBytes); } @Override @@ -192,5 +194,4 @@ private void maybeReleaseGvrAudioSurround() { gvrAudioSurround = null; } } - } diff --git a/extensions/ima/build.gradle b/extensions/ima/build.gradle index 80fcab95871..ad46882f7c3 100644 --- a/extensions/ima/build.gradle +++ b/extensions/ima/build.gradle @@ -25,10 +25,10 @@ android { } dependencies { - api 'com.google.ads.interactivemedia.v3:interactivemedia:3.23.0' + api 'com.google.ads.interactivemedia.v3:interactivemedia:3.24.0' implementation project(modulePrefix + 'library-core') implementation 'androidx.annotation:annotation:' + androidxAnnotationVersion - implementation 'com.google.android.gms:play-services-ads-identifier:17.0.0' + implementation 'com.google.android.gms:play-services-ads-identifier:17.0.1' compileOnly 'org.checkerframework:checker-qual:' + checkerframeworkVersion compileOnly 'org.jetbrains.kotlin:kotlin-annotations-jvm:' + kotlinAnnotationsVersion androidTestImplementation project(modulePrefix + 'testutils') diff --git a/extensions/ima/src/androidTest/java/com/google/android/exoplayer2/ext/ima/ImaPlaybackTest.java b/extensions/ima/src/androidTest/java/com/google/android/exoplayer2/ext/ima/ImaPlaybackTest.java index 6ddc3172740..d2f70d5e1bf 100644 --- a/extensions/ima/src/androidTest/java/com/google/android/exoplayer2/ext/ima/ImaPlaybackTest.java +++ b/extensions/ima/src/androidTest/java/com/google/android/exoplayer2/ext/ima/ImaPlaybackTest.java @@ -233,9 +233,7 @@ public void onPositionDiscontinuity( @Override protected MediaSource buildSource( - HostActivity host, - DrmSessionManager drmSessionManager, - FrameLayout overlayFrameLayout) { + HostActivity host, DrmSessionManager drmSessionManager, FrameLayout overlayFrameLayout) { Context context = host.getApplicationContext(); DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(context); MediaSource contentMediaSource = diff --git a/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/AdTagLoader.java b/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/AdTagLoader.java index 6690fa95ec4..0e8b2461000 100644 --- a/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/AdTagLoader.java +++ b/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/AdTagLoader.java @@ -51,8 +51,8 @@ import com.google.ads.interactivemedia.v3.api.player.VideoAdPlayer; import com.google.ads.interactivemedia.v3.api.player.VideoProgressUpdate; import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlayerLibraryInfo; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.source.ads.AdPlaybackState; @@ -161,7 +161,7 @@ /** Whether IMA has sent an ad event to pause content since the last resume content event. */ private boolean imaPausedContent; /** The current ad playback state. */ - private @ImaAdState int imaAdState; + @ImaAdState private int imaAdState; /** The current ad media info, or {@code null} if in state {@link #IMA_AD_STATE_NONE}. */ @Nullable private AdMediaInfo imaAdMediaInfo; /** The current ad info, or {@code null} if in state {@link #IMA_AD_STATE_NONE}. */ @@ -211,7 +211,7 @@ private long waitingForPreloadElapsedRealtimeMs; /** Creates a new ad tag loader, starting the ad request if the ad tag is valid. */ - @SuppressWarnings({"methodref.receiver.bound.invalid", "method.invocation.invalid"}) + @SuppressWarnings({"nullness:methodref.receiver.bound", "nullness:method.invocation"}) public AdTagLoader( Context context, ImaUtil.Configuration configuration, @@ -447,7 +447,7 @@ public void handlePrepareError(int adGroupIndex, int adIndexInAdGroup, IOExcepti } } - // Player.EventListener implementation. + // Player.Listener implementation. @Override public void onTimelineChanged(Timeline timeline, @Player.TimelineChangeReason int reason) { @@ -514,7 +514,7 @@ public void onPlayWhenReadyChanged( } @Override - public void onPlayerError(ExoPlaybackException error) { + public void onPlayerError(PlaybackException error) { if (imaAdState != IMA_AD_STATE_NONE) { AdMediaInfo adMediaInfo = checkNotNull(imaAdMediaInfo); for (int i = 0; i < adCallbacks.size(); i++) { @@ -602,17 +602,16 @@ private AdsRenderingSettings setupAdsRendering(long contentPositionMs, long cont } // Skip ads based on the start position as required. - long[] adGroupTimesUs = adPlaybackState.adGroupTimesUs; int adGroupForPositionIndex = adPlaybackState.getAdGroupIndexForPositionUs( C.msToUs(contentPositionMs), C.msToUs(contentDurationMs)); if (adGroupForPositionIndex != C.INDEX_UNSET) { boolean playAdWhenStartingPlayback = - configuration.playAdBeforeStartPosition - || adGroupTimesUs[adGroupForPositionIndex] == C.msToUs(contentPositionMs); + adPlaybackState.getAdGroup(adGroupForPositionIndex).timeUs == C.msToUs(contentPositionMs) + || configuration.playAdBeforeStartPosition; if (!playAdWhenStartingPlayback) { adGroupForPositionIndex++; - } else if (hasMidrollAdGroups(adGroupTimesUs)) { + } else if (hasMidrollAdGroups(adPlaybackState)) { // Provide the player's initial position to trigger loading and playing the ad. If there are // no midrolls, we are playing a preroll and any pending content position wouldn't be // cleared. @@ -622,13 +621,14 @@ private AdsRenderingSettings setupAdsRendering(long contentPositionMs, long cont for (int i = 0; i < adGroupForPositionIndex; i++) { adPlaybackState = adPlaybackState.withSkippedAdGroup(i); } - if (adGroupForPositionIndex == adGroupTimesUs.length) { + if (adGroupForPositionIndex == adPlaybackState.adGroupCount) { // We don't need to play any ads. Because setPlayAdsAfterTime does not discard non-VMAP // ads, we signal that no ads will render so the caller can destroy the ads manager. return null; } - long adGroupForPositionTimeUs = adGroupTimesUs[adGroupForPositionIndex]; - long adGroupBeforePositionTimeUs = adGroupTimesUs[adGroupForPositionIndex - 1]; + long adGroupForPositionTimeUs = adPlaybackState.getAdGroup(adGroupForPositionIndex).timeUs; + long adGroupBeforePositionTimeUs = + adPlaybackState.getAdGroup(adGroupForPositionIndex - 1).timeUs; if (adGroupForPositionTimeUs == C.TIME_END_OF_SOURCE) { // Play the postroll by offsetting the start position just past the last non-postroll ad. adsRenderingSettings.setPlayAdsAfterTime( @@ -786,14 +786,14 @@ private boolean isWaitingForAdToLoad() { if (adGroupIndex == C.INDEX_UNSET) { return false; } - AdPlaybackState.AdGroup adGroup = adPlaybackState.adGroups[adGroupIndex]; + AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(adGroupIndex); if (adGroup.count != C.LENGTH_UNSET && adGroup.count != 0 && adGroup.states[0] != AdPlaybackState.AD_STATE_UNAVAILABLE) { // An ad is available already. return false; } - long adGroupTimeMs = C.usToMs(adPlaybackState.adGroupTimesUs[adGroupIndex]); + long adGroupTimeMs = C.usToMs(adGroup.timeUs); long contentPositionMs = getContentPeriodPositionMs(player, timeline, period); long timeUntilAdMs = adGroupTimeMs - contentPositionMs; return timeUntilAdMs < configuration.adPreloadTimeoutMs; @@ -877,13 +877,13 @@ private void handleTimelineOrPositionChanged() { } } if (!sentContentComplete && !wasPlayingAd && playingAd && imaAdState == IMA_AD_STATE_NONE) { - int adGroupIndex = player.getCurrentAdGroupIndex(); - if (adPlaybackState.adGroupTimesUs[adGroupIndex] == C.TIME_END_OF_SOURCE) { + AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(player.getCurrentAdGroupIndex()); + if (adGroup.timeUs == C.TIME_END_OF_SOURCE) { sendContentComplete(); } else { // IMA hasn't called playAd yet, so fake the content position. fakeContentProgressElapsedRealtimeMs = SystemClock.elapsedRealtime(); - fakeContentProgressOffsetMs = C.usToMs(adPlaybackState.adGroupTimesUs[adGroupIndex]); + fakeContentProgressOffsetMs = C.usToMs(adGroup.timeUs); if (fakeContentProgressOffsetMs == C.TIME_END_OF_SOURCE) { fakeContentProgressOffsetMs = contentDurationMs; } @@ -919,11 +919,11 @@ private void loadAdInternal(AdMediaInfo adMediaInfo, AdPodInfo adPodInfo) { // The ad count may increase on successive loads of ads in the same ad pod, for example, due to // separate requests for ad tags with multiple ads within the ad pod completing after an earlier // ad has loaded. See also https://github.com/google/ExoPlayer/issues/7477. - AdPlaybackState.AdGroup adGroup = adPlaybackState.adGroups[adInfo.adGroupIndex]; + AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(adInfo.adGroupIndex); adPlaybackState = adPlaybackState.withAdCount( adInfo.adGroupIndex, max(adPodInfo.getTotalAds(), adGroup.states.length)); - adGroup = adPlaybackState.adGroups[adInfo.adGroupIndex]; + adGroup = adPlaybackState.getAdGroup(adInfo.adGroupIndex); for (int i = 0; i < adIndexInAdGroup; i++) { // Any preceding ads that haven't loaded are not going to load. if (adGroup.states[i] == AdPlaybackState.AD_STATE_UNAVAILABLE) { @@ -1062,10 +1062,10 @@ private void handleAdGroupLoadError(Exception error) { private void markAdGroupInErrorStateAndClearPendingContentPosition(int adGroupIndex) { // Update the ad playback state so all ads in the ad group are in the error state. - AdPlaybackState.AdGroup adGroup = adPlaybackState.adGroups[adGroupIndex]; + AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(adGroupIndex); if (adGroup.count == C.LENGTH_UNSET) { adPlaybackState = adPlaybackState.withAdCount(adGroupIndex, max(1, adGroup.states.length)); - adGroup = adPlaybackState.adGroups[adGroupIndex]; + adGroup = adPlaybackState.getAdGroup(adGroupIndex); } for (int i = 0; i < adGroup.count; i++) { if (adGroup.states[i] == AdPlaybackState.AD_STATE_UNAVAILABLE) { @@ -1094,7 +1094,7 @@ private void handleAdPrepareError(int adGroupIndex, int adIndexInAdGroup, Except // Send IMA a content position at the ad group so that it will try to play it, at which point // we can notify that it failed to load. fakeContentProgressElapsedRealtimeMs = SystemClock.elapsedRealtime(); - fakeContentProgressOffsetMs = C.usToMs(adPlaybackState.adGroupTimesUs[adGroupIndex]); + fakeContentProgressOffsetMs = C.usToMs(adPlaybackState.getAdGroup(adGroupIndex).timeUs); if (fakeContentProgressOffsetMs == C.TIME_END_OF_SOURCE) { fakeContentProgressOffsetMs = contentDurationMs; } @@ -1109,7 +1109,7 @@ private void handleAdPrepareError(int adGroupIndex, int adIndexInAdGroup, Except adCallbacks.get(i).onEnded(adMediaInfo); } } - playingAdIndexInAdGroup = adPlaybackState.adGroups[adGroupIndex].getFirstAdIndexToPlay(); + playingAdIndexInAdGroup = adPlaybackState.getAdGroup(adGroupIndex).getFirstAdIndexToPlay(); for (int i = 0; i < adCallbacks.size(); i++) { adCallbacks.get(i).onError(checkNotNull(adMediaInfo)); } @@ -1138,7 +1138,7 @@ private void sendContentComplete() { Log.d(TAG, "adsLoader.contentComplete"); } for (int i = 0; i < adPlaybackState.adGroupCount; i++) { - if (adPlaybackState.adGroupTimesUs[i] != C.TIME_END_OF_SOURCE) { + if (adPlaybackState.getAdGroup(i).timeUs != C.TIME_END_OF_SOURCE) { adPlaybackState = adPlaybackState.withSkippedAdGroup(/* adGroupIndex= */ i); } } @@ -1213,7 +1213,7 @@ private int getAdGroupIndexForCuePointTimeSeconds(double cuePointTimeSeconds) { float cuePointTimeSecondsFloat = (float) cuePointTimeSeconds; long adPodTimeUs = Math.round((double) cuePointTimeSecondsFloat * C.MICROS_PER_SECOND); for (int adGroupIndex = 0; adGroupIndex < adPlaybackState.adGroupCount; adGroupIndex++) { - long adGroupTimeUs = adPlaybackState.adGroupTimesUs[adGroupIndex]; + long adGroupTimeUs = adPlaybackState.getAdGroup(adGroupIndex).timeUs; if (adGroupTimeUs != C.TIME_END_OF_SOURCE && Math.abs(adGroupTimeUs - adPodTimeUs) < THRESHOLD_AD_MATCH_US) { return adGroupIndex; @@ -1242,14 +1242,16 @@ private static long getContentPeriodPositionMs( } } - private static boolean hasMidrollAdGroups(long[] adGroupTimesUs) { - int count = adGroupTimesUs.length; + private static boolean hasMidrollAdGroups(AdPlaybackState adPlaybackState) { + int count = adPlaybackState.adGroupCount; if (count == 1) { - return adGroupTimesUs[0] != 0 && adGroupTimesUs[0] != C.TIME_END_OF_SOURCE; + long adGroupTimeUs = adPlaybackState.getAdGroup(0).timeUs; + return adGroupTimeUs != 0 && adGroupTimeUs != C.TIME_END_OF_SOURCE; } else if (count == 2) { - return adGroupTimesUs[0] != 0 || adGroupTimesUs[1] != C.TIME_END_OF_SOURCE; + return adPlaybackState.getAdGroup(0).timeUs != 0 + || adPlaybackState.getAdGroup(1).timeUs != C.TIME_END_OF_SOURCE; } else { - // There's at least one midroll ad group, as adGroupTimesUs is never empty. + // There's at least one midroll ad group, as adPlaybackState is never empty. return true; } } diff --git a/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java b/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java index 72cae676af2..f77a5a0aa6c 100644 --- a/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java +++ b/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java @@ -734,7 +734,7 @@ public AdDisplayContainer createAudioAdDisplayContainer(Context context, VideoAd // The reasonDetail parameter to createFriendlyObstruction is annotated @Nullable but the // annotation is not kept in the obfuscated dependency. - @SuppressWarnings("nullness:argument.type.incompatible") + @SuppressWarnings("nullness:argument") @Override public FriendlyObstruction createFriendlyObstruction( View view, diff --git a/extensions/ima/src/test/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoaderTest.java b/extensions/ima/src/test/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoaderTest.java index 6b62b38e4dd..ee889ab3493 100644 --- a/extensions/ima/src/test/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoaderTest.java +++ b/extensions/ima/src/test/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoaderTest.java @@ -56,6 +56,7 @@ import com.google.ads.interactivemedia.v3.api.player.VideoProgressUpdate; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline.Period; @@ -93,10 +94,12 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.mockito.stubbing.Answer; +import org.robolectric.annotation.internal.DoNotInstrument; import org.robolectric.shadows.ShadowSystemClock; /** Tests for {@link ImaAdsLoader}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class ImaAdsLoaderTest { private static final long CONTENT_DURATION_US = 10 * C.MICROS_PER_SECOND; @@ -271,7 +274,11 @@ public void startAndCallbacksAfterRelease() { adEventListener.onAdEvent(getAdEvent(AdEventType.STARTED, mockPrerollSingleAd)); videoAdPlayer.pauseAd(TEST_AD_MEDIA_INFO); videoAdPlayer.stopAd(TEST_AD_MEDIA_INFO); - imaAdsLoader.onPlayerError(ExoPlaybackException.createForSource(new IOException())); + ExoPlaybackException anException = + ExoPlaybackException.createForSource( + new IOException(), PlaybackException.ERROR_CODE_IO_UNSPECIFIED); + imaAdsLoader.onPlayerErrorChanged(anException); + imaAdsLoader.onPlayerError(anException); imaAdsLoader.onPositionDiscontinuity( new Player.PositionInfo( /* windowUid= */ new Object(), @@ -1411,7 +1418,8 @@ public TestAdsLoaderListener(int periodIndex) { public void onAdPlaybackState(AdPlaybackState adPlaybackState) { long[][] adDurationsUs = new long[adPlaybackState.adGroupCount][]; for (int adGroupIndex = 0; adGroupIndex < adPlaybackState.adGroupCount; adGroupIndex++) { - adDurationsUs[adGroupIndex] = new long[adPlaybackState.adGroups[adGroupIndex].uris.length]; + adDurationsUs[adGroupIndex] = + new long[adPlaybackState.getAdGroup(adGroupIndex).uris.length]; Arrays.fill(adDurationsUs[adGroupIndex], TEST_AD_DURATION_US); } adPlaybackState = adPlaybackState.withAdDurationsUs(adDurationsUs); diff --git a/extensions/leanback/src/main/java/com/google/android/exoplayer2/ext/leanback/LeanbackPlayerAdapter.java b/extensions/leanback/src/main/java/com/google/android/exoplayer2/ext/leanback/LeanbackPlayerAdapter.java index f2fc3279b82..f38fe14f201 100644 --- a/extensions/leanback/src/main/java/com/google/android/exoplayer2/ext/leanback/LeanbackPlayerAdapter.java +++ b/extensions/leanback/src/main/java/com/google/android/exoplayer2/ext/leanback/LeanbackPlayerAdapter.java @@ -28,15 +28,16 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ControlDispatcher; import com.google.android.exoplayer2.DefaultControlDispatcher; -import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlayerLibraryInfo; -import com.google.android.exoplayer2.PlaybackPreparer; +import com.google.android.exoplayer2.ForwardingPlayer; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player.DiscontinuityReason; import com.google.android.exoplayer2.Player.TimelineChangeReason; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.util.ErrorMessageProvider; import com.google.android.exoplayer2.util.Util; +import com.google.android.exoplayer2.video.VideoSize; /** Leanback {@code PlayerAdapter} implementation for {@link Player}. */ public final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnable { @@ -51,9 +52,8 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnab private final PlayerListener playerListener; private final int updatePeriodMs; - @Nullable private PlaybackPreparer playbackPreparer; private ControlDispatcher controlDispatcher; - @Nullable private ErrorMessageProvider errorMessageProvider; + @Nullable private ErrorMessageProvider errorMessageProvider; @Nullable private SurfaceHolderGlueHost surfaceHolderGlueHost; private boolean hasSurface; private boolean lastNotifiedPreparedState; @@ -77,28 +77,14 @@ public LeanbackPlayerAdapter(Context context, Player player, final int updatePer } /** - * @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} instead. The adapter calls - * {@link ControlDispatcher#dispatchPrepare(Player)} instead of {@link - * PlaybackPreparer#preparePlayback()}. The {@link DefaultControlDispatcher} that the adapter - * uses by default, calls {@link Player#prepare()}. If you wish to customize this behaviour, - * you can provide a custom implementation of {@link - * ControlDispatcher#dispatchPrepare(Player)}. + * @deprecated Use a {@link ForwardingPlayer} and pass it to the constructor instead. You can also + * customize some operations when configuring the player (for example by using {@code + * SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)}). */ - @SuppressWarnings("deprecation") @Deprecated - public void setPlaybackPreparer(@Nullable PlaybackPreparer playbackPreparer) { - this.playbackPreparer = playbackPreparer; - } - - /** - * Sets the {@link ControlDispatcher}. - * - * @param controlDispatcher The {@link ControlDispatcher}, or null to use - * {@link DefaultControlDispatcher}. - */ public void setControlDispatcher(@Nullable ControlDispatcher controlDispatcher) { - this.controlDispatcher = controlDispatcher == null ? new DefaultControlDispatcher() - : controlDispatcher; + this.controlDispatcher = + controlDispatcher == null ? new DefaultControlDispatcher() : controlDispatcher; } /** @@ -107,7 +93,7 @@ public void setControlDispatcher(@Nullable ControlDispatcher controlDispatcher) * @param errorMessageProvider The {@link ErrorMessageProvider}. */ public void setErrorMessageProvider( - @Nullable ErrorMessageProvider errorMessageProvider) { + @Nullable ErrorMessageProvider errorMessageProvider) { this.errorMessageProvider = errorMessageProvider; } @@ -148,7 +134,8 @@ public void setProgressUpdatingEnabled(boolean enabled) { @Override public boolean isPlaying() { int playbackState = player.getPlaybackState(); - return playbackState != Player.STATE_IDLE && playbackState != Player.STATE_ENDED + return playbackState != Player.STATE_IDLE + && playbackState != Player.STATE_ENDED && player.getPlayWhenReady(); } @@ -168,22 +155,20 @@ public long getCurrentPosition() { @Override public void play() { if (player.getPlaybackState() == Player.STATE_IDLE) { - if (playbackPreparer != null) { - playbackPreparer.preparePlayback(); - } else { - controlDispatcher.dispatchPrepare(player); - } + controlDispatcher.dispatchPrepare(player); } else if (player.getPlaybackState() == Player.STATE_ENDED) { controlDispatcher.dispatchSeekTo(player, player.getCurrentWindowIndex(), C.TIME_UNSET); } - if (controlDispatcher.dispatchSetPlayWhenReady(player, true)) { + if (player.isCommandAvailable(Player.COMMAND_PLAY_PAUSE) + && controlDispatcher.dispatchSetPlayWhenReady(player, true)) { getCallback().onPlayStateChanged(this); } } @Override public void pause() { - if (controlDispatcher.dispatchSetPlayWhenReady(player, false)) { + if (player.isCommandAvailable(Player.COMMAND_PLAY_PAUSE) + && controlDispatcher.dispatchSetPlayWhenReady(player, false)) { getCallback().onPlayStateChanged(this); } } @@ -241,7 +226,7 @@ private void maybeNotifyPreparedStateChanged(Callback callback) { } } - @SuppressWarnings("nullness:argument.type.incompatible") + @SuppressWarnings("nullness:argument") private static void removeSurfaceHolderCallback(SurfaceHolderGlueHost surfaceHolderGlueHost) { surfaceHolderGlueHost.setSurfaceHolderCallback(null); } @@ -265,7 +250,7 @@ public void surfaceDestroyed(SurfaceHolder surfaceHolder) { setVideoSurface(null); } - // Player.EventListener implementation. + // Player.Listener implementation. @Override public void onPlaybackStateChanged(@Player.State int playbackState) { @@ -273,14 +258,20 @@ public void onPlaybackStateChanged(@Player.State int playbackState) { } @Override - public void onPlayerError(ExoPlaybackException exception) { + public void onPlayerError(PlaybackException error) { Callback callback = getCallback(); if (errorMessageProvider != null) { - Pair errorMessage = errorMessageProvider.getErrorMessage(exception); + Pair errorMessage = errorMessageProvider.getErrorMessage(error); callback.onError(LeanbackPlayerAdapter.this, errorMessage.first, errorMessage.second); } else { - callback.onError(LeanbackPlayerAdapter.this, exception.type, context.getString( - R.string.lb_media_player_error, exception.type, exception.rendererIndex)); + callback.onError( + LeanbackPlayerAdapter.this, + error.errorCode, + // This string was probably tailored for MediaPlayer, whose callback takes 2 ints as + // error code. Since ExoPlayer provides a single error code, we just pass 0 as the + // extra. + context.getString( + R.string.lb_media_player_error, /* formatArgs...= */ error.errorCode, 0)); } } @@ -302,23 +293,13 @@ public void onPositionDiscontinuity( callback.onBufferedPositionChanged(LeanbackPlayerAdapter.this); } - // VideoListener implementation. - @Override - public void onVideoSizeChanged( - int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) { + public void onVideoSizeChanged(VideoSize videoSize) { // There's no way to pass pixelWidthHeightRatio to leanback, so we scale the width that we // pass to take it into account. This is necessary to ensure that leanback uses the correct // aspect ratio when playing content with non-square pixels. - int scaledWidth = Math.round(width * pixelWidthHeightRatio); - getCallback().onVideoSizeChanged(LeanbackPlayerAdapter.this, scaledWidth, height); + int scaledWidth = Math.round(videoSize.width * videoSize.pixelWidthHeightRatio); + getCallback().onVideoSizeChanged(LeanbackPlayerAdapter.this, scaledWidth, videoSize.height); } - - @Override - public void onRenderedFirstFrame() { - // Do nothing. - } - } - } diff --git a/extensions/media2/src/androidTest/java/com/google/android/exoplayer2/ext/media2/PlayerTestRule.java b/extensions/media2/src/androidTest/java/com/google/android/exoplayer2/ext/media2/PlayerTestRule.java index a995bfdb5ba..3c202ba375b 100644 --- a/extensions/media2/src/androidTest/java/com/google/android/exoplayer2/ext/media2/PlayerTestRule.java +++ b/extensions/media2/src/androidTest/java/com/google/android/exoplayer2/ext/media2/PlayerTestRule.java @@ -165,8 +165,8 @@ public Map> getResponseHeaders() { } @Override - public int read(byte[] target, int offset, int length) throws IOException { - return wrappedDataSource.read(target, offset, length); + public int read(byte[] buffer, int offset, int length) throws IOException { + return wrappedDataSource.read(buffer, offset, length); } @Override diff --git a/extensions/media2/src/androidTest/java/com/google/android/exoplayer2/ext/media2/SessionPlayerConnectorTest.java b/extensions/media2/src/androidTest/java/com/google/android/exoplayer2/ext/media2/SessionPlayerConnectorTest.java index d4e996caa2e..d8e29cc79fc 100644 --- a/extensions/media2/src/androidTest/java/com/google/android/exoplayer2/ext/media2/SessionPlayerConnectorTest.java +++ b/extensions/media2/src/androidTest/java/com/google/android/exoplayer2/ext/media2/SessionPlayerConnectorTest.java @@ -44,6 +44,7 @@ import androidx.test.platform.app.InstrumentationRegistry; import com.google.android.exoplayer2.ControlDispatcher; import com.google.android.exoplayer2.DefaultControlDispatcher; +import com.google.android.exoplayer2.ForwardingPlayer; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.ext.media2.test.R; @@ -168,10 +169,7 @@ public boolean dispatchSetPlayWhenReady(Player player, boolean playWhenReady) { SimpleExoPlayer simpleExoPlayer = null; SessionPlayerConnector playerConnector = null; try { - simpleExoPlayer = - new SimpleExoPlayer.Builder(context) - .setLooper(Looper.myLooper()) - .build(); + simpleExoPlayer = new SimpleExoPlayer.Builder(context).setLooper(Looper.myLooper()).build(); playerConnector = new SessionPlayerConnector(simpleExoPlayer, new DefaultMediaItemConverter()); playerConnector.setControlDispatcher(controlDispatcher); @@ -186,6 +184,45 @@ public boolean dispatchSetPlayWhenReady(Player player, boolean playWhenReady) { } } + @Test + @LargeTest + public void play_withForwardingPlayer_isSkipped() throws Exception { + if (Looper.myLooper() == null) { + Looper.prepare(); + } + + Player forwardingPlayer = null; + SessionPlayerConnector playerConnector = null; + try { + Player simpleExoPlayer = + new SimpleExoPlayer.Builder(context).setLooper(Looper.myLooper()).build(); + forwardingPlayer = + new ForwardingPlayer(simpleExoPlayer) { + @Override + public boolean isCommandAvailable(int command) { + if (command == COMMAND_PLAY_PAUSE) { + return false; + } + return super.isCommandAvailable(command); + } + + @Override + public Commands getAvailableCommands() { + return super.getAvailableCommands().buildUpon().remove(COMMAND_PLAY_PAUSE).build(); + } + }; + playerConnector = new SessionPlayerConnector(forwardingPlayer); + assertPlayerResult(playerConnector.play(), RESULT_INFO_SKIPPED); + } finally { + if (playerConnector != null) { + playerConnector.close(); + } + if (forwardingPlayer != null) { + forwardingPlayer.release(); + } + } + } + @Test @LargeTest public void setMediaItem_withAudioResource_notifiesOnPlaybackCompleted() throws Exception { @@ -1098,7 +1135,7 @@ public void onPlayerStateChanged(SessionPlayer player, int playerState) { .runOnMainSync( () -> simpleExoPlayer.addListener( - new Player.EventListener() { + new Player.Listener() { @Override public void onPlayWhenReadyChanged(boolean playWhenReady, int reason) { if (playWhenReady) { diff --git a/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/PlayerWrapper.java b/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/PlayerWrapper.java index ea29ccbe538..4b25db56437 100644 --- a/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/PlayerWrapper.java +++ b/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/PlayerWrapper.java @@ -15,6 +15,14 @@ */ package com.google.android.exoplayer2.ext.media2; +import static com.google.android.exoplayer2.Player.COMMAND_GET_AUDIO_ATTRIBUTES; +import static com.google.android.exoplayer2.Player.COMMAND_PLAY_PAUSE; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_IN_CURRENT_WINDOW; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_NEXT; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_PREVIOUS; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_WINDOW; +import static com.google.android.exoplayer2.Player.COMMAND_SET_REPEAT_MODE; +import static com.google.android.exoplayer2.Player.COMMAND_SET_SHUFFLE_MODE; import static com.google.android.exoplayer2.util.Util.postOrRun; import android.os.Handler; @@ -27,8 +35,9 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ControlDispatcher; import com.google.android.exoplayer2.DefaultControlDispatcher; -import com.google.android.exoplayer2.ExoPlaybackException; +import com.google.android.exoplayer2.ForwardingPlayer; import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Timeline; @@ -154,6 +163,12 @@ public PlayerWrapper(Listener listener, Player player, MediaItemConverter mediaI } } + /** + * @deprecated Use a {@link ForwardingPlayer} and pass it to the constructor instead. You can also + * customize some operations when configuring the player (for example by using {@code + * SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)}). + */ + @Deprecated public void setControlDispatcher(ControlDispatcher controlDispatcher) { this.controlDispatcher = controlDispatcher; } @@ -231,11 +246,13 @@ public boolean movePlaylistItem( } public boolean skipToPreviousPlaylistItem() { - return controlDispatcher.dispatchPrevious(player); + return player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS) + && controlDispatcher.dispatchPrevious(player); } public boolean skipToNextPlaylistItem() { - return controlDispatcher.dispatchNext(player); + return player.isCommandAvailable(COMMAND_SEEK_TO_NEXT) + && controlDispatcher.dispatchNext(player); } public boolean skipToPlaylistItem(@IntRange(from = 0) int index) { @@ -247,7 +264,8 @@ public boolean skipToPlaylistItem(@IntRange(from = 0) int index) { Assertions.checkState(0 <= index && index < timeline.getWindowCount()); int windowIndex = player.getCurrentWindowIndex(); if (windowIndex != index) { - return controlDispatcher.dispatchSeekTo(player, index, C.TIME_UNSET); + return player.isCommandAvailable(COMMAND_SEEK_TO_WINDOW) + && controlDispatcher.dispatchSeekTo(player, index, C.TIME_UNSET); } return false; } @@ -258,13 +276,15 @@ public boolean updatePlaylistMetadata(@Nullable MediaMetadata metadata) { } public boolean setRepeatMode(int repeatMode) { - return controlDispatcher.dispatchSetRepeatMode( - player, Utils.getExoPlayerRepeatMode(repeatMode)); + return player.isCommandAvailable(COMMAND_SET_REPEAT_MODE) + && controlDispatcher.dispatchSetRepeatMode( + player, Utils.getExoPlayerRepeatMode(repeatMode)); } public boolean setShuffleMode(int shuffleMode) { - return controlDispatcher.dispatchSetShuffleModeEnabled( - player, Utils.getExoPlayerShuffleMode(shuffleMode)); + return player.isCommandAvailable(COMMAND_SET_SHUFFLE_MODE) + && controlDispatcher.dispatchSetShuffleModeEnabled( + player, Utils.getExoPlayerShuffleMode(shuffleMode)); } @Nullable @@ -314,8 +334,9 @@ public boolean prepare() { public boolean play() { if (player.getPlaybackState() == Player.STATE_ENDED) { boolean seekHandled = - controlDispatcher.dispatchSeekTo( - player, player.getCurrentWindowIndex(), /* positionMs= */ 0); + player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_WINDOW) + && controlDispatcher.dispatchSeekTo( + player, player.getCurrentWindowIndex(), /* positionMs= */ 0); if (!seekHandled) { return false; } @@ -325,7 +346,8 @@ public boolean play() { if (playWhenReady && suppressReason == Player.PLAYBACK_SUPPRESSION_REASON_NONE) { return false; } - return controlDispatcher.dispatchSetPlayWhenReady(player, /* playWhenReady= */ true); + return player.isCommandAvailable(COMMAND_PLAY_PAUSE) + && controlDispatcher.dispatchSetPlayWhenReady(player, /* playWhenReady= */ true); } public boolean pause() { @@ -334,11 +356,13 @@ public boolean pause() { if (!playWhenReady && suppressReason == Player.PLAYBACK_SUPPRESSION_REASON_NONE) { return false; } - return controlDispatcher.dispatchSetPlayWhenReady(player, /* playWhenReady= */ false); + return player.isCommandAvailable(COMMAND_PLAY_PAUSE) + && controlDispatcher.dispatchSetPlayWhenReady(player, /* playWhenReady= */ false); } public boolean seekTo(long position) { - return controlDispatcher.dispatchSeekTo(player, player.getCurrentWindowIndex(), position); + return player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_WINDOW) + && controlDispatcher.dispatchSeekTo(player, player.getCurrentWindowIndex(), position); } public long getCurrentPosition() { @@ -443,7 +467,7 @@ public void setAudioAttributes(AudioAttributesCompat audioAttributes) { public AudioAttributesCompat getAudioAttributes() { AudioAttributes audioAttributes = AudioAttributes.DEFAULT; - if (player.isCommandAvailable(Player.COMMAND_GET_AUDIO_ATTRIBUTES)) { + if (player.isCommandAvailable(COMMAND_GET_AUDIO_ATTRIBUTES)) { audioAttributes = player.getAudioAttributes(); } return Utils.getAudioAttributesCompat(audioAttributes); @@ -480,11 +504,11 @@ public boolean canSkipToPlaylistItem() { } public boolean canSkipToPreviousPlaylistItem() { - return player.hasPrevious(); + return player.hasPreviousWindow(); } public boolean canSkipToNextPlaylistItem() { - return player.hasNext(); + return player.hasNextWindow(); } public boolean hasError() { @@ -564,15 +588,13 @@ private void releaseMediaItem(androidx.media2.common.MediaItem media2MediaItem) private final class ComponentListener implements Player.Listener { - // Player.EventListener implementation. - @Override public void onPlayWhenReadyChanged(boolean playWhenReady, int reason) { updateSessionPlayerState(); } @Override - public void onPlaybackStateChanged(@Player.State int state) { + public void onPlaybackStateChanged(@Player.State int playbackState) { handlePlayerStateChanged(); } @@ -585,7 +607,7 @@ public void onPositionDiscontinuity( } @Override - public void onPlayerError(ExoPlaybackException error) { + public void onPlayerError(PlaybackException error) { updateSessionPlayerState(); } @@ -616,8 +638,6 @@ public void onTimelineChanged(Timeline timeline, int reason) { listener.onPlaylistChanged(); } - // AudioListener implementation. - @Override public void onAudioAttributesChanged(AudioAttributes audioAttributes) { listener.onAudioAttributesChanged(Utils.getAudioAttributesCompat(audioAttributes)); diff --git a/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/SessionCallback.java b/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/SessionCallback.java index 4b161a73454..c718efa85d5 100644 --- a/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/SessionCallback.java +++ b/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/SessionCallback.java @@ -352,7 +352,7 @@ public void onShuffleModeChanged(SessionPlayer player, int shuffleMode) { // TODO(internal b/160846312): Remove warning suppression and mark item @Nullable once we depend // on media2 1.2.0. @Override - @SuppressWarnings("nullness:override.param.invalid") + @SuppressWarnings("nullness:override.param") public void onCurrentMediaItemChanged(SessionPlayer player, MediaItem item) { currentMediaItemBuffered = isBufferedState(player.getBufferingState()); updateAllowedCommands(); diff --git a/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/SessionCallbackBuilder.java b/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/SessionCallbackBuilder.java index 516ec20b3bc..b905464ee8b 100644 --- a/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/SessionCallbackBuilder.java +++ b/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/SessionCallbackBuilder.java @@ -97,14 +97,14 @@ public interface AllowedCommandProvider { * @param session The media session. * @param controllerInfo The {@link ControllerInfo} for the controller for which allowed * commands are being queried. - * @param baseAllowedSessionCommand Base allowed session commands for customization. + * @param baseAllowedSessionCommands Base allowed session commands for customization. * @return The allowed commands for the controller. * @see MediaSession.SessionCallback#onConnect(MediaSession, ControllerInfo) */ SessionCommandGroup getAllowedCommands( MediaSession session, ControllerInfo controllerInfo, - SessionCommandGroup baseAllowedSessionCommand); + SessionCommandGroup baseAllowedSessionCommands); /** * Called when a {@link MediaController} has called an API that controls {@link SessionPlayer} diff --git a/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/SessionPlayerConnector.java b/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/SessionPlayerConnector.java index e51964b648d..e2eb6d1134c 100644 --- a/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/SessionPlayerConnector.java +++ b/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/SessionPlayerConnector.java @@ -30,8 +30,8 @@ import androidx.media2.common.MediaMetadata; import androidx.media2.common.SessionPlayer; import com.google.android.exoplayer2.ControlDispatcher; -import com.google.android.exoplayer2.DefaultControlDispatcher; import com.google.android.exoplayer2.ExoPlayerLibraryInfo; +import com.google.android.exoplayer2.ForwardingPlayer; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Log; @@ -87,7 +87,7 @@ public final class SessionPlayerConnector extends SessionPlayer { /** * Creates an instance using {@link DefaultMediaItemConverter} to convert between ExoPlayer and - * media2 MediaItems and {@link DefaultControlDispatcher} to dispatch player commands. + * media2 MediaItems. * * @param player The player to wrap. */ @@ -96,7 +96,7 @@ public SessionPlayerConnector(Player player) { } /** - * Creates an instance using the provided {@link ControlDispatcher} to dispatch player commands. + * Creates an instance. * * @param player The player to wrap. * @param mediaItemConverter The {@link MediaItemConverter}. @@ -114,10 +114,11 @@ public SessionPlayerConnector(Player player, MediaItemConverter mediaItemConvert } /** - * Sets the {@link ControlDispatcher}. - * - * @param controlDispatcher The {@link ControlDispatcher}. + * @deprecated Use a {@link ForwardingPlayer} and pass it to the constructor instead. You can also + * customize some operations when configuring the player (for example by using {@code + * SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)}). */ + @Deprecated public void setControlDispatcher(ControlDispatcher controlDispatcher) { player.setControlDispatcher(controlDispatcher); } @@ -571,7 +572,6 @@ private void notifySessionPlayerCallback(SessionPlayerCallbackNotifier notifier) // TODO(internal b/160846312): Remove this suppress warnings and call onCurrentMediaItemChanged // with a null item once we depend on media2 1.2.0. - @SuppressWarnings("nullness:argument.type.incompatible") private void handlePlaylistChangedOnHandler() { List currentPlaylist = player.getPlaylist(); MediaMetadata playlistMetadata = player.getPlaylistMetadata(); diff --git a/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/Utils.java b/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/Utils.java index 873e35cc25e..87b52f35982 100644 --- a/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/Utils.java +++ b/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/Utils.java @@ -89,7 +89,6 @@ public static int getRepeatMode(@Player.RepeatMode int exoPlayerRepeatMode) { } } - private Utils() { // Prevent instantiation. } diff --git a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java index f806a579be8..3c461c8853f 100644 --- a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java +++ b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java @@ -16,6 +16,9 @@ package com.google.android.exoplayer2.ext.mediasession; import static androidx.media.utils.MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_MEDIA_ID; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_BACK; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_FORWARD; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_IN_CURRENT_WINDOW; import static com.google.android.exoplayer2.Player.EVENT_IS_PLAYING_CHANGED; import static com.google.android.exoplayer2.Player.EVENT_PLAYBACK_PARAMETERS_CHANGED; import static com.google.android.exoplayer2.Player.EVENT_PLAYBACK_STATE_CHANGED; @@ -44,9 +47,10 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ControlDispatcher; import com.google.android.exoplayer2.DefaultControlDispatcher; -import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlayerLibraryInfo; +import com.google.android.exoplayer2.ForwardingPlayer; import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.util.Assertions; @@ -59,6 +63,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; /** @@ -102,10 +107,6 @@ public final class MediaSessionConnector { ExoPlayerLibraryInfo.registerModule("goog.exo.mediasession"); } - /** Indicates this session supports the set playback speed command. */ - // TODO(b/174297519) Replace with PlaybackStateCompat.ACTION_SET_PLAYBACK_SPEED when released. - public static final long ACTION_SET_PLAYBACK_SPEED = 1 << 22; - /** Playback actions supported by the connector. */ @LongDef( flag = true, @@ -119,7 +120,7 @@ public final class MediaSessionConnector { PlaybackStateCompat.ACTION_STOP, PlaybackStateCompat.ACTION_SET_REPEAT_MODE, PlaybackStateCompat.ACTION_SET_SHUFFLE_MODE, - ACTION_SET_PLAYBACK_SPEED + PlaybackStateCompat.ACTION_SET_PLAYBACK_SPEED }) @Retention(RetentionPolicy.SOURCE) public @interface PlaybackActions {} @@ -135,12 +136,12 @@ public final class MediaSessionConnector { | PlaybackStateCompat.ACTION_STOP | PlaybackStateCompat.ACTION_SET_REPEAT_MODE | PlaybackStateCompat.ACTION_SET_SHUFFLE_MODE - | ACTION_SET_PLAYBACK_SPEED; + | PlaybackStateCompat.ACTION_SET_PLAYBACK_SPEED; /** The default playback actions. */ @PlaybackActions public static final long DEFAULT_PLAYBACK_ACTIONS = - ALL_PLAYBACK_ACTIONS - ACTION_SET_PLAYBACK_SPEED; + ALL_PLAYBACK_ACTIONS - PlaybackStateCompat.ACTION_SET_PLAYBACK_SPEED; /** * The name of the {@link PlaybackStateCompat} float extra with the value of {@code @@ -155,7 +156,7 @@ public final class MediaSessionConnector { | PlaybackStateCompat.ACTION_STOP | PlaybackStateCompat.ACTION_SET_SHUFFLE_MODE | PlaybackStateCompat.ACTION_SET_REPEAT_MODE - | ACTION_SET_PLAYBACK_SPEED; + | PlaybackStateCompat.ACTION_SET_PLAYBACK_SPEED; private static final int BASE_MEDIA_SESSION_FLAGS = MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS; @@ -169,12 +170,13 @@ public final class MediaSessionConnector { public interface CommandReceiver { /** * See {@link MediaSessionCompat.Callback#onCommand(String, Bundle, ResultReceiver)}. The - * receiver may handle the command, but is not required to do so. Changes to the player should - * be made via the {@link ControlDispatcher}. + * receiver may handle the command, but is not required to do so. * * @param player The player connected to the media session. - * @param controlDispatcher A {@link ControlDispatcher} that should be used for dispatching - * changes to the player. + * @param controlDispatcher This parameter is deprecated. Use {@code player} instead. Operations + * can be customized by passing a {@link ForwardingPlayer} to {@link #setPlayer(Player)}, or + * when configuring the player (for example by using {@code + * SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)}). * @param command The command name. * @param extras Optional parameters for the command, may be null. * @param cb A result receiver to which a result may be sent by the command, may be null. @@ -182,7 +184,7 @@ public interface CommandReceiver { */ boolean onCommand( Player player, - ControlDispatcher controlDispatcher, + @Deprecated ControlDispatcher controlDispatcher, String command, @Nullable Bundle extras, @Nullable ResultReceiver cb); @@ -294,26 +296,32 @@ public interface QueueNavigator extends CommandReceiver { * See {@link MediaSessionCompat.Callback#onSkipToPrevious()}. * * @param player The player connected to the media session. - * @param controlDispatcher A {@link ControlDispatcher} that should be used for dispatching - * changes to the player. + * @param controlDispatcher This parameter is deprecated. Use {@code player} instead. Operations + * can be customized by passing a {@link ForwardingPlayer} to {@link #setPlayer(Player)}, or + * when configuring the player (for example by using {@code + * SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)}). */ - void onSkipToPrevious(Player player, ControlDispatcher controlDispatcher); + void onSkipToPrevious(Player player, @Deprecated ControlDispatcher controlDispatcher); /** * See {@link MediaSessionCompat.Callback#onSkipToQueueItem(long)}. * * @param player The player connected to the media session. - * @param controlDispatcher A {@link ControlDispatcher} that should be used for dispatching - * changes to the player. + * @param controlDispatcher This parameter is deprecated. Use {@code player} instead. Operations + * can be customized by passing a {@link ForwardingPlayer} to {@link #setPlayer(Player)}, or + * when configuring the player (for example by using {@code + * SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)}). */ - void onSkipToQueueItem(Player player, ControlDispatcher controlDispatcher, long id); + void onSkipToQueueItem(Player player, @Deprecated ControlDispatcher controlDispatcher, long id); /** * See {@link MediaSessionCompat.Callback#onSkipToNext()}. * * @param player The player connected to the media session. - * @param controlDispatcher A {@link ControlDispatcher} that should be used for dispatching - * changes to the player. + * @param controlDispatcher This parameter is deprecated. Use {@code player} instead. Operations + * can be customized by passing a {@link ForwardingPlayer} to {@link #setPlayer(Player)}, or + * when configuring the player (for example by using {@code + * SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)}). */ - void onSkipToNext(Player player, ControlDispatcher controlDispatcher); + void onSkipToNext(Player player, @Deprecated ControlDispatcher controlDispatcher); } /** Handles media session queue edits. */ @@ -366,13 +374,15 @@ public interface MediaButtonEventHandler { * See {@link MediaSessionCompat.Callback#onMediaButtonEvent(Intent)}. * * @param player The {@link Player}. - * @param controlDispatcher A {@link ControlDispatcher} that should be used for dispatching - * changes to the player. + * @param controlDispatcher This parameter is deprecated. Use {@code player} instead. Operations + * can be customized by passing a {@link ForwardingPlayer} to {@link #setPlayer(Player)}, or + * when configuring the player (for example by using {@code + * SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)}). * @param mediaButtonEvent The {@link Intent}. * @return True if the event was handled, false otherwise. */ boolean onMediaButtonEvent( - Player player, ControlDispatcher controlDispatcher, Intent mediaButtonEvent); + Player player, @Deprecated ControlDispatcher controlDispatcher, Intent mediaButtonEvent); } /** @@ -384,13 +394,18 @@ public interface CustomActionProvider { * Called when a custom action provided by this provider is sent to the media session. * * @param player The player connected to the media session. - * @param controlDispatcher A {@link ControlDispatcher} that should be used for dispatching - * changes to the player. + * @param controlDispatcher This parameter is deprecated. Use {@code player} instead. Operations + * can be customized by passing a {@link ForwardingPlayer} to {@link #setPlayer(Player)}, or + * when configuring the player (for example by using {@code + * SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)}). * @param action The name of the action which was sent by a media controller. * @param extras Optional extras sent by a media controller, may be null. */ void onCustomAction( - Player player, ControlDispatcher controlDispatcher, String action, @Nullable Bundle extras); + Player player, + @Deprecated ControlDispatcher controlDispatcher, + String action, + @Nullable Bundle extras); /** * Returns a {@link PlaybackStateCompat.CustomAction} which will be published to the media @@ -420,6 +435,45 @@ public interface MediaMetadataProvider { * @return The {@link MediaMetadataCompat} to be published to the session. */ MediaMetadataCompat getMetadata(Player player); + + /** Returns whether the old and the new metadata are considered the same. */ + default boolean sameAs(MediaMetadataCompat oldMetadata, MediaMetadataCompat newMetadata) { + if (oldMetadata == newMetadata) { + return true; + } + if (oldMetadata.size() != newMetadata.size()) { + return false; + } + Set oldKeySet = oldMetadata.keySet(); + Bundle oldMetadataBundle = oldMetadata.getBundle(); + Bundle newMetadataBundle = newMetadata.getBundle(); + for (String key : oldKeySet) { + Object oldProperty = oldMetadataBundle.get(key); + Object newProperty = newMetadataBundle.get(key); + if (oldProperty == newProperty) { + continue; + } + if (oldProperty instanceof Bitmap && newProperty instanceof Bitmap) { + if (!((Bitmap) oldProperty).sameAs(((Bitmap) newProperty))) { + return false; + } + } else if (oldProperty instanceof RatingCompat && newProperty instanceof RatingCompat) { + RatingCompat oldRating = (RatingCompat) oldProperty; + RatingCompat newRating = (RatingCompat) newProperty; + if (oldRating.hasHeart() != newRating.hasHeart() + || oldRating.isRated() != newRating.isRated() + || oldRating.isThumbUp() != newRating.isThumbUp() + || oldRating.getPercentRating() != newRating.getPercentRating() + || oldRating.getStarRating() != newRating.getStarRating() + || oldRating.getRatingStyle() != newRating.getRatingStyle()) { + return false; + } + } else if (!Util.areEqual(oldProperty, newProperty)) { + return false; + } + } + return true; + } } /** The wrapped {@link MediaSessionCompat}. */ @@ -435,7 +489,7 @@ public interface MediaMetadataProvider { private Map customActionMap; @Nullable private MediaMetadataProvider mediaMetadataProvider; @Nullable private Player player; - @Nullable private ErrorMessageProvider errorMessageProvider; + @Nullable private ErrorMessageProvider errorMessageProvider; @Nullable private Pair customError; @Nullable private Bundle customErrorExtras; @Nullable private PlaybackPreparer playbackPreparer; @@ -446,6 +500,8 @@ public interface MediaMetadataProvider { @Nullable private MediaButtonEventHandler mediaButtonEventHandler; private long enabledPlaybackActions; + private boolean metadataDeduplicationEnabled; + private boolean dispatchUnsupportedActionsEnabled; /** * Creates an instance. @@ -504,10 +560,11 @@ public void setPlaybackPreparer(@Nullable PlaybackPreparer playbackPreparer) { } /** - * Sets the {@link ControlDispatcher}. - * - * @param controlDispatcher The {@link ControlDispatcher}. + * @deprecated Use a {@link ForwardingPlayer} and pass it to {@link #setPlayer(Player)} instead. + * You can also customize some operations when configuring the player (for example by using + * {@code SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)}). */ + @Deprecated public void setControlDispatcher(ControlDispatcher controlDispatcher) { if (this.controlDispatcher != controlDispatcher) { this.controlDispatcher = controlDispatcher; @@ -551,39 +608,13 @@ public void setEnabledPlaybackActions(@PlaybackActions long enabledPlaybackActio } } - /** - * @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} with {@link - * DefaultControlDispatcher#DefaultControlDispatcher(long, long)} instead. - */ - @SuppressWarnings("deprecation") - @Deprecated - public void setRewindIncrementMs(int rewindMs) { - if (controlDispatcher instanceof DefaultControlDispatcher) { - ((DefaultControlDispatcher) controlDispatcher).setRewindIncrementMs(rewindMs); - invalidateMediaSessionPlaybackState(); - } - } - - /** - * @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} with {@link - * DefaultControlDispatcher#DefaultControlDispatcher(long, long)} instead. - */ - @SuppressWarnings("deprecation") - @Deprecated - public void setFastForwardIncrementMs(int fastForwardMs) { - if (controlDispatcher instanceof DefaultControlDispatcher) { - ((DefaultControlDispatcher) controlDispatcher).setFastForwardIncrementMs(fastForwardMs); - invalidateMediaSessionPlaybackState(); - } - } - /** * Sets the optional {@link ErrorMessageProvider}. * * @param errorMessageProvider The error message provider. */ public void setErrorMessageProvider( - @Nullable ErrorMessageProvider errorMessageProvider) { + @Nullable ErrorMessageProvider errorMessageProvider) { if (this.errorMessageProvider != errorMessageProvider) { this.errorMessageProvider = errorMessageProvider; invalidateMediaSessionPlaybackState(); @@ -710,6 +741,27 @@ public void setMediaMetadataProvider(@Nullable MediaMetadataProvider mediaMetada } } + /** + * Sets whether actions that are not advertised to the {@link MediaSessionCompat} will be + * dispatched either way. Default value is false. + */ + public void setDispatchUnsupportedActionsEnabled(boolean dispatchUnsupportedActionsEnabled) { + this.dispatchUnsupportedActionsEnabled = dispatchUnsupportedActionsEnabled; + } + + /** + * Sets whether {@link MediaMetadataProvider#sameAs(MediaMetadataCompat, MediaMetadataCompat)} + * should be consulted before calling {@link MediaSessionCompat#setMetadata(MediaMetadataCompat)}. + * + *

      Note that this comparison is normally only required when you are using media sources that + * may introduce duplicate updates of the metadata for the same media item (e.g. live streams). + * + * @param metadataDeduplicationEnabled Whether to deduplicate metadata objects on invalidation. + */ + public void setMetadataDeduplicationEnabled(boolean metadataDeduplicationEnabled) { + this.metadataDeduplicationEnabled = metadataDeduplicationEnabled; + } + /** * Updates the metadata of the media session. * @@ -724,6 +776,14 @@ public final void invalidateMediaSessionMetadata() { mediaMetadataProvider != null && player != null ? mediaMetadataProvider.getMetadata(player) : METADATA_EMPTY; + @Nullable MediaMetadataProvider mediaMetadataProvider = this.mediaMetadataProvider; + if (metadataDeduplicationEnabled && mediaMetadataProvider != null) { + @Nullable MediaMetadataCompat oldMetadata = mediaSession.getController().getMetadata(); + if (oldMetadata != null && mediaMetadataProvider.sameAs(oldMetadata, metadata)) { + // Do not update if metadata did not change. + return; + } + } mediaSession.setMetadata(metadata); } @@ -763,7 +823,7 @@ public final void invalidateMediaSessionPlaybackState() { customActionMap = Collections.unmodifiableMap(currentActions); Bundle extras = new Bundle(); - @Nullable ExoPlaybackException playbackError = player.getPlayerError(); + @Nullable PlaybackException playbackError = player.getPlayerError(); boolean reportError = playbackError != null || customError != null; int sessionPlaybackState = reportError @@ -871,16 +931,16 @@ private long buildPrepareActions() { } private long buildPlaybackActions(Player player) { - boolean enableSeeking = false; - boolean enableRewind = false; - boolean enableFastForward = false; + boolean enableSeeking = player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_WINDOW); + boolean enableRewind = + player.isCommandAvailable(COMMAND_SEEK_BACK) && controlDispatcher.isRewindEnabled(); + boolean enableFastForward = + player.isCommandAvailable(COMMAND_SEEK_FORWARD) && controlDispatcher.isFastForwardEnabled(); + boolean enableSetRating = false; boolean enableSetCaptioningEnabled = false; Timeline timeline = player.getCurrentTimeline(); if (!timeline.isEmpty() && !player.isPlayingAd()) { - enableSeeking = player.isCurrentWindowSeekable(); - enableRewind = enableSeeking && controlDispatcher.isRewindEnabled(); - enableFastForward = enableSeeking && controlDispatcher.isFastForwardEnabled(); enableSetRating = ratingCallback != null; enableSetCaptioningEnabled = captionCallback != null && captionCallback.hasCaptions(player); } @@ -913,13 +973,15 @@ private long buildPlaybackActions(Player player) { @EnsuresNonNullIf(result = true, expression = "player") private boolean canDispatchPlaybackAction(long action) { - return player != null && (enabledPlaybackActions & action) != 0; + return player != null + && ((enabledPlaybackActions & action) != 0 || dispatchUnsupportedActionsEnabled); } @EnsuresNonNullIf(result = true, expression = "playbackPreparer") private boolean canDispatchToPlaybackPreparer(long action) { return playbackPreparer != null - && (playbackPreparer.getSupportedPrepareActions() & action) != 0; + && ((playbackPreparer.getSupportedPrepareActions() & action) != 0 + || dispatchUnsupportedActionsEnabled); } @EnsuresNonNullIf( @@ -928,7 +990,8 @@ private boolean canDispatchToPlaybackPreparer(long action) { private boolean canDispatchToQueueNavigator(long action) { return player != null && queueNavigator != null - && (queueNavigator.getSupportedQueueNavigatorActions(player) & action) != 0; + && ((queueNavigator.getSupportedQueueNavigatorActions(player) & action) != 0 + || dispatchUnsupportedActionsEnabled); } @EnsuresNonNullIf( @@ -1245,7 +1308,7 @@ public void onSetRepeatMode(@PlaybackStateCompat.RepeatMode int mediaSessionRepe @Override public void onSetPlaybackSpeed(float speed) { - if (canDispatchPlaybackAction(ACTION_SET_PLAYBACK_SPEED) && speed > 0) { + if (canDispatchPlaybackAction(PlaybackStateCompat.ACTION_SET_PLAYBACK_SPEED) && speed > 0) { controlDispatcher.dispatchSetPlaybackParameters( player, player.getPlaybackParameters().withSpeed(speed)); } diff --git a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/RepeatModeActionProvider.java b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/RepeatModeActionProvider.java index 87b9447f7ce..99c85b23538 100644 --- a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/RepeatModeActionProvider.java +++ b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/RepeatModeActionProvider.java @@ -33,8 +33,7 @@ public final class RepeatModeActionProvider implements MediaSessionConnector.Cus private static final String ACTION_REPEAT_MODE = "ACTION_EXO_REPEAT_MODE"; - @RepeatModeUtil.RepeatToggleModes - private final int repeatToggleModes; + @RepeatModeUtil.RepeatToggleModes private final int repeatToggleModes; private final CharSequence repeatAllDescription; private final CharSequence repeatOneDescription; private final CharSequence repeatOffDescription; @@ -66,7 +65,10 @@ public RepeatModeActionProvider( @Override public void onCustomAction( - Player player, ControlDispatcher controlDispatcher, String action, @Nullable Bundle extras) { + Player player, + @Deprecated ControlDispatcher controlDispatcher, + String action, + @Nullable Bundle extras) { int mode = player.getRepeatMode(); int proposedMode = RepeatModeUtil.getNextRepeatMode(mode, repeatToggleModes); if (mode != proposedMode) { @@ -93,9 +95,9 @@ public PlaybackStateCompat.CustomAction getCustomAction(Player player) { iconResourceId = R.drawable.exo_media_action_repeat_off; break; } - PlaybackStateCompat.CustomAction.Builder repeatBuilder = new PlaybackStateCompat.CustomAction - .Builder(ACTION_REPEAT_MODE, actionLabel, iconResourceId); + PlaybackStateCompat.CustomAction.Builder repeatBuilder = + new PlaybackStateCompat.CustomAction.Builder( + ACTION_REPEAT_MODE, actionLabel, iconResourceId); return repeatBuilder.build(); } - } diff --git a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/TimelineQueueEditor.java b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/TimelineQueueEditor.java index cab16744b95..f6af25d1887 100644 --- a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/TimelineQueueEditor.java +++ b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/TimelineQueueEditor.java @@ -57,8 +57,8 @@ public interface MediaDescriptionConverter { /** * Adapter to get {@link MediaDescriptionCompat} of items in the queue and to notify the - * application about changes in the queue to sync the data structure backing the - * {@link MediaSessionConnector}. + * application about changes in the queue to sync the data structure backing the {@link + * MediaSessionConnector}. */ public interface QueueDataAdapter { /** @@ -83,9 +83,7 @@ public interface QueueDataAdapter { void move(int from, int to); } - /** - * Used to evaluate whether two {@link MediaDescriptionCompat} are considered equal. - */ + /** Used to evaluate whether two {@link MediaDescriptionCompat} are considered equal. */ interface MediaDescriptionEqualityChecker { /** * Returns {@code true} whether the descriptions are considered equal. @@ -181,7 +179,7 @@ public void onRemoveQueueItem(Player player, MediaDescriptionCompat description) @Override public boolean onCommand( Player player, - ControlDispatcher controlDispatcher, + @Deprecated ControlDispatcher controlDispatcher, String command, @Nullable Bundle extras, @Nullable ResultReceiver cb) { diff --git a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/TimelineQueueNavigator.java b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/TimelineQueueNavigator.java index 4a27ca9d93c..2b33d9b9899 100644 --- a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/TimelineQueueNavigator.java +++ b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/TimelineQueueNavigator.java @@ -15,9 +15,9 @@ */ package com.google.android.exoplayer2.ext.mediasession; -import static com.google.android.exoplayer2.Player.COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM; -import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM; -import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_IN_CURRENT_WINDOW; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_NEXT_WINDOW; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_PREVIOUS_WINDOW; import static java.lang.Math.min; import android.os.Bundle; @@ -51,8 +51,8 @@ public abstract class TimelineQueueNavigator implements MediaSessionConnector.Qu /** * Creates an instance for a given {@link MediaSessionCompat}. - *

      - * Equivalent to {@code TimelineQueueNavigator(mediaSession, DEFAULT_MAX_QUEUE_SIZE)}. + * + *

      Equivalent to {@code TimelineQueueNavigator(mediaSession, DEFAULT_MAX_QUEUE_SIZE)}. * * @param mediaSession The {@link MediaSessionCompat}. */ @@ -62,10 +62,10 @@ public TimelineQueueNavigator(MediaSessionCompat mediaSession) { /** * Creates an instance for a given {@link MediaSessionCompat} and maximum queue size. - *

      - * If the number of windows in the {@link Player}'s {@link Timeline} exceeds {@code maxQueueSize}, - * the media session queue will correspond to {@code maxQueueSize} windows centered on the one - * currently being played. + * + *

      If the number of windows in the {@link Player}'s {@link Timeline} exceeds {@code + * maxQueueSize}, the media session queue will correspond to {@code maxQueueSize} windows centered + * on the one currently being played. * * @param mediaSession The {@link MediaSessionCompat}. * @param maxQueueSize The maximum queue size. @@ -102,12 +102,12 @@ public long getSupportedQueueNavigatorActions(Player player) { timeline.getWindow(player.getCurrentWindowIndex(), window); enableSkipTo = timeline.getWindowCount() > 1; enablePrevious = - player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM) + player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_WINDOW) || !window.isLive() - || player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); + || player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS_WINDOW); enableNext = (window.isLive() && window.isDynamic) - || player.isCommandAvailable(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); + || player.isCommandAvailable(COMMAND_SEEK_TO_NEXT_WINDOW); } long actions = 0; @@ -144,12 +144,13 @@ public final long getActiveQueueItemId(@Nullable Player player) { } @Override - public void onSkipToPrevious(Player player, ControlDispatcher controlDispatcher) { + public void onSkipToPrevious(Player player, @Deprecated ControlDispatcher controlDispatcher) { controlDispatcher.dispatchPrevious(player); } @Override - public void onSkipToQueueItem(Player player, ControlDispatcher controlDispatcher, long id) { + public void onSkipToQueueItem( + Player player, @Deprecated ControlDispatcher controlDispatcher, long id) { Timeline timeline = player.getCurrentTimeline(); if (timeline.isEmpty() || player.isPlayingAd()) { return; @@ -161,7 +162,7 @@ public void onSkipToQueueItem(Player player, ControlDispatcher controlDispatcher } @Override - public void onSkipToNext(Player player, ControlDispatcher controlDispatcher) { + public void onSkipToNext(Player player, @Deprecated ControlDispatcher controlDispatcher) { controlDispatcher.dispatchNext(player); } @@ -170,7 +171,7 @@ public void onSkipToNext(Player player, ControlDispatcher controlDispatcher) { @Override public boolean onCommand( Player player, - ControlDispatcher controlDispatcher, + @Deprecated ControlDispatcher controlDispatcher, String command, @Nullable Bundle extras, @Nullable ResultReceiver cb) { diff --git a/extensions/okhttp/README.md b/extensions/okhttp/README.md index 2f9893fe3bc..2aad867e79a 100644 --- a/extensions/okhttp/README.md +++ b/extensions/okhttp/README.md @@ -1,8 +1,11 @@ # ExoPlayer OkHttp extension # -The OkHttp extension is an [HttpDataSource][] implementation using Square's +The OkHttp extension is an [HttpDataSource][] implementation that uses Square's [OkHttp][]. +OkHttp is a modern network stack that's widely used by many popular Android +applications. It supports the HTTP and HTTP/2 protocols. + [HttpDataSource]: https://exoplayer.dev/doc/reference/com/google/android/exoplayer2/upstream/HttpDataSource.html [OkHttp]: https://square.github.io/okhttp/ @@ -34,27 +37,18 @@ locally. Instructions for doing this can be found in ExoPlayer's ## Using the extension ## ExoPlayer requests data through `DataSource` instances. These instances are -either instantiated and injected from application code, or obtained from -instances of `DataSource.Factory` that are instantiated and injected from -application code. +obtained from instances of `DataSource.Factory`, which are instantiated and +injected from application code. If your application only needs to play http(s) content, using the OkHttp -extension is as simple as updating any `DataSource`s and `DataSource.Factory` -instantiations in your application code to use `OkHttpDataSource` and -`OkHttpDataSourceFactory` respectively. If your application also needs to play -non-http(s) content such as local files, use -``` -new DefaultDataSource( - ... - new OkHttpDataSource(...) /* baseDataSource argument */); -``` -and +extension is as simple as updating any `DataSource.Factory` instantiations in +your application code to use `OkHttpDataSource.Factory`. If your application +also needs to play non-http(s) content such as local files, use: ``` new DefaultDataSourceFactory( ... - new OkHttpDataSourceFactory(...) /* baseDataSourceFactory argument */); + /* baseDataSourceFactory= */ new OkHttpDataSource.Factory(...)); ``` -respectively. ## Links ## diff --git a/extensions/okhttp/build.gradle b/extensions/okhttp/build.gradle index 758eb646f61..96424b43808 100644 --- a/extensions/okhttp/build.gradle +++ b/extensions/okhttp/build.gradle @@ -13,19 +13,17 @@ // limitations under the License. apply from: "$gradle.ext.exoplayerSettingsDir/common_library_config.gradle" +android.defaultConfig.minSdkVersion 21 + dependencies { implementation project(modulePrefix + 'library-common') implementation 'androidx.annotation:annotation:' + androidxAnnotationVersion compileOnly 'org.checkerframework:checker-qual:' + checkerframeworkVersion compileOnly 'org.jetbrains.kotlin:kotlin-annotations-jvm:' + kotlinAnnotationsVersion testImplementation project(modulePrefix + 'testutils') - testImplementation 'com.squareup.okhttp3:mockwebserver:' + mockWebServerVersion + testImplementation 'com.squareup.okhttp3:mockwebserver:' + okhttpVersion testImplementation 'org.robolectric:robolectric:' + robolectricVersion - // Do not update to 3.13.X or later until minSdkVersion is increased to 21: - // https://cashapp.github.io/2019-02-05/okhttp-3-13-requires-android-5 - // Since OkHttp is distributed as a jar rather than an aar, Gradle won't - // stop us from making this mistake! - api 'com.squareup.okhttp3:okhttp:3.12.11' + api 'com.squareup.okhttp3:okhttp:' + okhttpVersion } ext { diff --git a/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java b/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java index 0b881955a1c..9d5d1cc5a07 100644 --- a/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java +++ b/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java @@ -23,6 +23,7 @@ import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlayerLibraryInfo; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.upstream.BaseDataSource; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSourceException; @@ -32,7 +33,6 @@ import com.google.android.exoplayer2.upstream.TransferListener; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Util; -import com.google.common.base.Ascii; import com.google.common.base.Predicate; import com.google.common.net.HttpHeaders; import java.io.IOException; @@ -288,13 +288,8 @@ public long open(DataSpec dataSpec) throws HttpDataSourceException { responseBody = Assertions.checkNotNull(response.body()); responseByteStream = responseBody.byteStream(); } catch (IOException e) { - @Nullable String message = e.getMessage(); - if (message != null - && Ascii.toLowerCase(message).matches("cleartext communication.*not permitted.*")) { - throw new CleartextNotPermittedException(e, dataSpec); - } - throw new HttpDataSourceException( - "Unable to connect", e, dataSpec, HttpDataSourceException.TYPE_OPEN); + throw HttpDataSourceException.createForIOException( + e, dataSpec, HttpDataSourceException.TYPE_OPEN); } int responseCode = response.code(); @@ -319,13 +314,13 @@ public long open(DataSpec dataSpec) throws HttpDataSourceException { } Map> headers = response.headers().toMultimap(); closeConnectionQuietly(); - InvalidResponseCodeException exception = - new InvalidResponseCodeException( - responseCode, response.message(), headers, dataSpec, errorResponseBody); - if (responseCode == 416) { - exception.initCause(new DataSourceException(DataSourceException.POSITION_OUT_OF_RANGE)); - } - throw exception; + @Nullable + IOException cause = + responseCode == 416 + ? new DataSourceException(PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE) + : null; + throw new InvalidResponseCodeException( + responseCode, response.message(), cause, headers, dataSpec, errorResponseBody); } // Check for a valid content type. @@ -353,29 +348,27 @@ public long open(DataSpec dataSpec) throws HttpDataSourceException { transferStarted(dataSpec); try { - if (!skipFully(bytesToSkip)) { - throw new DataSourceException(DataSourceException.POSITION_OUT_OF_RANGE); - } - } catch (IOException e) { + skipFully(bytesToSkip, dataSpec); + } catch (HttpDataSourceException e) { closeConnectionQuietly(); - throw new HttpDataSourceException(e, dataSpec, HttpDataSourceException.TYPE_OPEN); + throw e; } return bytesToRead; } @Override - public int read(byte[] buffer, int offset, int readLength) throws HttpDataSourceException { + public int read(byte[] buffer, int offset, int length) throws HttpDataSourceException { try { - return readInternal(buffer, offset, readLength); + return readInternal(buffer, offset, length); } catch (IOException e) { - throw new HttpDataSourceException( - e, Assertions.checkNotNull(dataSpec), HttpDataSourceException.TYPE_READ); + throw HttpDataSourceException.createForIOException( + e, castNonNull(dataSpec), HttpDataSourceException.TYPE_READ); } } @Override - public void close() throws HttpDataSourceException { + public void close() { if (opened) { opened = false; transferEnded(); @@ -391,7 +384,10 @@ private Request makeRequest(DataSpec dataSpec) throws HttpDataSourceException { @Nullable HttpUrl url = HttpUrl.parse(dataSpec.uri.toString()); if (url == null) { throw new HttpDataSourceException( - "Malformed URL", dataSpec, HttpDataSourceException.TYPE_OPEN); + "Malformed URL", + dataSpec, + PlaybackException.ERROR_CODE_FAILED_RUNTIME_CHECK, + HttpDataSourceException.TYPE_OPEN); } Request.Builder builder = new Request.Builder().url(url); @@ -437,37 +433,51 @@ private Request makeRequest(DataSpec dataSpec) throws HttpDataSourceException { * Attempts to skip the specified number of bytes in full. * * @param bytesToSkip The number of bytes to skip. - * @throws InterruptedIOException If the thread is interrupted during the operation. - * @throws IOException If an error occurs reading from the source. - * @return Whether the bytes were skipped in full. If {@code false} then the data ended before the - * specified number of bytes were skipped. Always {@code true} if {@code bytesToSkip == 0}. + * @param dataSpec The {@link DataSpec}. + * @throws HttpDataSourceException If the thread is interrupted during the operation, or an error + * occurs while reading from the source, or if the data ended before skipping the specified + * number of bytes. */ - private boolean skipFully(long bytesToSkip) throws IOException { + private void skipFully(long bytesToSkip, DataSpec dataSpec) throws HttpDataSourceException { if (bytesToSkip == 0) { - return true; + return; } byte[] skipBuffer = new byte[4096]; - while (bytesToSkip > 0) { - int readLength = (int) min(bytesToSkip, skipBuffer.length); - int read = castNonNull(responseByteStream).read(skipBuffer, 0, readLength); - if (Thread.currentThread().isInterrupted()) { - throw new InterruptedIOException(); + try { + while (bytesToSkip > 0) { + int readLength = (int) min(bytesToSkip, skipBuffer.length); + int read = castNonNull(responseByteStream).read(skipBuffer, 0, readLength); + if (Thread.currentThread().isInterrupted()) { + throw new InterruptedIOException(); + } + if (read == -1) { + throw new HttpDataSourceException( + dataSpec, + PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE, + HttpDataSourceException.TYPE_OPEN); + } + bytesToSkip -= read; + bytesTransferred(read); } - if (read == -1) { - return false; + return; + } catch (IOException e) { + if (e instanceof HttpDataSourceException) { + throw (HttpDataSourceException) e; + } else { + throw new HttpDataSourceException( + dataSpec, + PlaybackException.ERROR_CODE_IO_UNSPECIFIED, + HttpDataSourceException.TYPE_OPEN); } - bytesToSkip -= read; - bytesTransferred(read); } - return true; } /** - * Reads up to {@code length} bytes of data and stores them into {@code buffer}, starting at - * index {@code offset}. - *

      - * This method blocks until at least one byte of data can be read, the end of the opened range is - * detected, or an exception is thrown. + * Reads up to {@code length} bytes of data and stores them into {@code buffer}, starting at index + * {@code offset}. + * + *

      This method blocks until at least one byte of data can be read, the end of the opened range + * is detected, or an exception is thrown. * * @param buffer The buffer into which the read data should be stored. * @param offset The start offset into {@code buffer} at which data should be written. @@ -498,9 +508,7 @@ private int readInternal(byte[] buffer, int offset, int readLength) throws IOExc return read; } - /** - * Closes the current connection quietly, if there is one. - */ + /** Closes the current connection quietly, if there is one. */ private void closeConnectionQuietly() { if (response != null) { Assertions.checkNotNull(response.body()).close(); @@ -508,5 +516,4 @@ private void closeConnectionQuietly() { } responseByteStream = null; } - } diff --git a/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSourceFactory.java b/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSourceFactory.java index 5b6a31ca923..05780cbe3a9 100644 --- a/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSourceFactory.java +++ b/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSourceFactory.java @@ -104,11 +104,7 @@ public OkHttpDataSourceFactory( protected OkHttpDataSource createDataSourceInternal( HttpDataSource.RequestProperties defaultRequestProperties) { OkHttpDataSource dataSource = - new OkHttpDataSource( - callFactory, - userAgent, - cacheControl, - defaultRequestProperties); + new OkHttpDataSource(callFactory, userAgent, cacheControl, defaultRequestProperties); if (listener != null) { dataSource.addTransferListener(listener); } diff --git a/extensions/opus/src/androidTest/java/com/google/android/exoplayer2/ext/opus/OpusPlaybackTest.java b/extensions/opus/src/androidTest/java/com/google/android/exoplayer2/ext/opus/OpusPlaybackTest.java index 9cb606a718a..d5d1adf8991 100644 --- a/extensions/opus/src/androidTest/java/com/google/android/exoplayer2/ext/opus/OpusPlaybackTest.java +++ b/extensions/opus/src/androidTest/java/com/google/android/exoplayer2/ext/opus/OpusPlaybackTest.java @@ -23,8 +23,8 @@ import androidx.annotation.Nullable; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; -import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.RenderersFactory; @@ -79,7 +79,7 @@ private static class TestPlaybackRunnable implements Player.Listener, Runnable { private final Uri uri; @Nullable private SimpleExoPlayer player; - @Nullable private ExoPlaybackException playbackException; + @Nullable private PlaybackException playbackException; public TestPlaybackRunnable(Uri uri, Context context) { this.uri = uri; @@ -109,7 +109,7 @@ public void run() { } @Override - public void onPlayerError(ExoPlaybackException error) { + public void onPlayerError(PlaybackException error) { playbackException = error; } @@ -121,7 +121,5 @@ public void onPlaybackStateChanged(@Player.State int playbackState) { Looper.myLooper().quit(); } } - } - } diff --git a/extensions/opus/src/main/java/com/google/android/exoplayer2/ext/opus/OpusDecoderException.java b/extensions/opus/src/main/java/com/google/android/exoplayer2/ext/opus/OpusDecoderException.java index 8d9cfea7636..e9563b9af14 100644 --- a/extensions/opus/src/main/java/com/google/android/exoplayer2/ext/opus/OpusDecoderException.java +++ b/extensions/opus/src/main/java/com/google/android/exoplayer2/ext/opus/OpusDecoderException.java @@ -27,5 +27,4 @@ public final class OpusDecoderException extends DecoderException { /* package */ OpusDecoderException(String message, Throwable cause) { super(message, cause); } - } diff --git a/extensions/opus/src/main/java/com/google/android/exoplayer2/ext/opus/OpusLibrary.java b/extensions/opus/src/main/java/com/google/android/exoplayer2/ext/opus/OpusLibrary.java index 71ba1db106d..47b1cef657e 100644 --- a/extensions/opus/src/main/java/com/google/android/exoplayer2/ext/opus/OpusLibrary.java +++ b/extensions/opus/src/main/java/com/google/android/exoplayer2/ext/opus/OpusLibrary.java @@ -48,9 +48,7 @@ public static void setLibraries( OpusLibrary.exoMediaCryptoType = exoMediaCryptoType; } - /** - * Returns whether the underlying library is available, loading it if necessary. - */ + /** Returns whether the underlying library is available, loading it if necessary. */ public static boolean isAvailable() { return LOADER.isAvailable(); } @@ -71,5 +69,6 @@ public static boolean matchesExpectedExoMediaCryptoType( } public static native String opusGetVersion(); + public static native boolean opusIsSecureDecodeSupported(); } diff --git a/extensions/opus/src/main/jni/opus_jni.cc b/extensions/opus/src/main/jni/opus_jni.cc index a2515be7f6e..96c2838039a 100644 --- a/extensions/opus/src/main/jni/opus_jni.cc +++ b/extensions/opus/src/main/jni/opus_jni.cc @@ -14,38 +14,37 @@ * limitations under the License. */ -#include - #include +#include #include -#include "opus.h" // NOLINT +#include "opus.h" // NOLINT #include "opus_multistream.h" // NOLINT #define LOG_TAG "opus_jni" -#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, \ - __VA_ARGS__)) - -#define DECODER_FUNC(RETURN_TYPE, NAME, ...) \ - extern "C" { \ - JNIEXPORT RETURN_TYPE \ - Java_com_google_android_exoplayer2_ext_opus_OpusDecoder_ ## NAME \ - (JNIEnv* env, jobject thiz, ##__VA_ARGS__);\ - } \ - JNIEXPORT RETURN_TYPE \ - Java_com_google_android_exoplayer2_ext_opus_OpusDecoder_ ## NAME \ - (JNIEnv* env, jobject thiz, ##__VA_ARGS__)\ - -#define LIBRARY_FUNC(RETURN_TYPE, NAME, ...) \ - extern "C" { \ - JNIEXPORT RETURN_TYPE \ - Java_com_google_android_exoplayer2_ext_opus_OpusLibrary_ ## NAME \ - (JNIEnv* env, jobject thiz, ##__VA_ARGS__);\ - } \ - JNIEXPORT RETURN_TYPE \ - Java_com_google_android_exoplayer2_ext_opus_OpusLibrary_ ## NAME \ - (JNIEnv* env, jobject thiz, ##__VA_ARGS__)\ +#define LOGE(...) \ + ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) + +#define DECODER_FUNC(RETURN_TYPE, NAME, ...) \ + extern "C" { \ + JNIEXPORT RETURN_TYPE \ + Java_com_google_android_exoplayer2_ext_opus_OpusDecoder_##NAME( \ + JNIEnv* env, jobject thiz, ##__VA_ARGS__); \ + } \ + JNIEXPORT RETURN_TYPE \ + Java_com_google_android_exoplayer2_ext_opus_OpusDecoder_##NAME( \ + JNIEnv* env, jobject thiz, ##__VA_ARGS__) + +#define LIBRARY_FUNC(RETURN_TYPE, NAME, ...) \ + extern "C" { \ + JNIEXPORT RETURN_TYPE \ + Java_com_google_android_exoplayer2_ext_opus_OpusLibrary_##NAME( \ + JNIEnv* env, jobject thiz, ##__VA_ARGS__); \ + } \ + JNIEXPORT RETURN_TYPE \ + Java_com_google_android_exoplayer2_ext_opus_OpusLibrary_##NAME( \ + JNIEnv* env, jobject thiz, ##__VA_ARGS__) // JNI references for SimpleOutputBuffer class. static jmethodID outputBufferInit; @@ -66,7 +65,8 @@ static int errorCode; static bool outputFloat = false; DECODER_FUNC(jlong, opusInit, jint sampleRate, jint channelCount, - jint numStreams, jint numCoupled, jint gain, jbyteArray jStreamMap) { + jint numStreams, jint numCoupled, jint gain, + jbyteArray jStreamMap) { int status = OPUS_INVALID_STATE; ::channelCount = channelCount; errorCode = 0; @@ -88,21 +88,20 @@ DECODER_FUNC(jlong, opusInit, jint sampleRate, jint channelCount, // Populate JNI References. const jclass outputBufferClass = env->FindClass( "com/google/android/exoplayer2/decoder/SimpleOutputBuffer"); - outputBufferInit = env->GetMethodID(outputBufferClass, "init", - "(JI)Ljava/nio/ByteBuffer;"); + outputBufferInit = + env->GetMethodID(outputBufferClass, "init", "(JI)Ljava/nio/ByteBuffer;"); return reinterpret_cast(decoder); } DECODER_FUNC(jint, opusDecode, jlong jDecoder, jlong jTimeUs, - jobject jInputBuffer, jint inputSize, jobject jOutputBuffer) { + jobject jInputBuffer, jint inputSize, jobject jOutputBuffer) { OpusMSDecoder* decoder = reinterpret_cast(jDecoder); - const uint8_t* inputBuffer = - reinterpret_cast( - env->GetDirectBufferAddress(jInputBuffer)); + const uint8_t* inputBuffer = reinterpret_cast( + env->GetDirectBufferAddress(jInputBuffer)); - const int byteSizePerSample = outputFloat ? - kBytesPerFloatSample : kBytesPerIntPcmSample; + const int byteSizePerSample = + outputFloat ? kBytesPerFloatSample : kBytesPerIntPcmSample; const jint outputSize = kMaxOpusOutputPacketSizeSamples * byteSizePerSample * channelCount; @@ -111,8 +110,8 @@ DECODER_FUNC(jint, opusDecode, jlong jDecoder, jlong jTimeUs, // Exception is thrown in Java when returning from the native call. return -1; } - const jobject jOutputBufferData = env->CallObjectMethod(jOutputBuffer, - outputBufferInit, jTimeUs, outputSize); + const jobject jOutputBufferData = env->CallObjectMethod( + jOutputBuffer, outputBufferInit, jTimeUs, outputSize); if (env->ExceptionCheck()) { // Exception is thrown in Java when returning from the native call. return -1; @@ -122,26 +121,28 @@ DECODER_FUNC(jint, opusDecode, jlong jDecoder, jlong jTimeUs, if (outputFloat) { float* outputBufferData = reinterpret_cast( env->GetDirectBufferAddress(jOutputBufferData)); - sampleCount = opus_multistream_decode_float(decoder, inputBuffer, inputSize, - outputBufferData, kMaxOpusOutputPacketSizeSamples, 0); + sampleCount = opus_multistream_decode_float( + decoder, inputBuffer, inputSize, outputBufferData, + kMaxOpusOutputPacketSizeSamples, 0); } else { int16_t* outputBufferData = reinterpret_cast( env->GetDirectBufferAddress(jOutputBufferData)); sampleCount = opus_multistream_decode(decoder, inputBuffer, inputSize, - outputBufferData, kMaxOpusOutputPacketSizeSamples, 0); + outputBufferData, + kMaxOpusOutputPacketSizeSamples, 0); } // record error code errorCode = (sampleCount < 0) ? sampleCount : 0; return (sampleCount < 0) ? sampleCount - : sampleCount * byteSizePerSample * channelCount; + : sampleCount * byteSizePerSample * channelCount; } DECODER_FUNC(jint, opusSecureDecode, jlong jDecoder, jlong jTimeUs, - jobject jInputBuffer, jint inputSize, jobject jOutputBuffer, - jint sampleRate, jobject mediaCrypto, jint inputMode, jbyteArray key, - jbyteArray javaIv, jint inputNumSubSamples, jintArray numBytesOfClearData, - jintArray numBytesOfEncryptedData) { + jobject jInputBuffer, jint inputSize, jobject jOutputBuffer, + jint sampleRate, jobject mediaCrypto, jint inputMode, + jbyteArray key, jbyteArray javaIv, jint inputNumSubSamples, + jintArray numBytesOfClearData, jintArray numBytesOfEncryptedData) { // Doesn't support // Java client should have checked vpxSupportSecureDecode // and avoid calling this @@ -163,13 +164,9 @@ DECODER_FUNC(jstring, opusGetErrorMessage, jlong jContext) { return env->NewStringUTF(opus_strerror(errorCode)); } -DECODER_FUNC(jint, opusGetErrorCode, jlong jContext) { - return errorCode; -} +DECODER_FUNC(jint, opusGetErrorCode, jlong jContext) { return errorCode; } -DECODER_FUNC(void, opusSetFloatOutput) { - outputFloat = true; -} +DECODER_FUNC(void, opusSetFloatOutput) { outputFloat = true; } LIBRARY_FUNC(jstring, opusIsSecureDecodeSupported) { // Doesn't support diff --git a/extensions/rtmp/README.md b/extensions/rtmp/README.md index a34341692bd..99e9d25e8e8 100644 --- a/extensions/rtmp/README.md +++ b/extensions/rtmp/README.md @@ -35,18 +35,17 @@ locally. Instructions for doing this can be found in ExoPlayer's ## Using the extension ## ExoPlayer requests data through `DataSource` instances. These instances are -either instantiated and injected from application code, or obtained from -instances of `DataSource.Factory` that are instantiated and injected from -application code. +obtained from instances of `DataSource.Factory`, which are instantiated and +injected from application code. `DefaultDataSource` will automatically use the RTMP extension whenever it's available. Hence if your application is using `DefaultDataSource` or `DefaultDataSourceFactory`, adding support for RTMP streams is as simple as adding a dependency to the RTMP extension as described above. No changes to your application code are required. Alternatively, if you know that your application -doesn't need to handle any other protocols, you can update any `DataSource`s and +doesn't need to handle any other protocols, you can update any `DataSource.Factory` instantiations in your application code to use -`RtmpDataSource` and `RtmpDataSourceFactory` directly. +`RtmpDataSource.Factory` directly. ## Links ## diff --git a/extensions/rtmp/src/main/java/com/google/android/exoplayer2/ext/rtmp/RtmpDataSource.java b/extensions/rtmp/src/main/java/com/google/android/exoplayer2/ext/rtmp/RtmpDataSource.java index 587e310d648..8093b4d275d 100644 --- a/extensions/rtmp/src/main/java/com/google/android/exoplayer2/ext/rtmp/RtmpDataSource.java +++ b/extensions/rtmp/src/main/java/com/google/android/exoplayer2/ext/rtmp/RtmpDataSource.java @@ -24,6 +24,7 @@ import com.google.android.exoplayer2.upstream.BaseDataSource; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSpec; +import com.google.android.exoplayer2.upstream.TransferListener; import java.io.IOException; import net.butterflytv.rtmp_client.RtmpClient; import net.butterflytv.rtmp_client.RtmpClient.RtmpIOException; @@ -35,6 +36,36 @@ public final class RtmpDataSource extends BaseDataSource { ExoPlayerLibraryInfo.registerModule("goog.exo.rtmp"); } + /** {@link DataSource.Factory} for {@link RtmpDataSource} instances. */ + public static final class Factory implements DataSource.Factory { + + @Nullable private TransferListener transferListener; + + /** + * Sets the {@link TransferListener} that will be used. + * + *

      The default is {@code null}. + * + *

      See {@link DataSource#addTransferListener(TransferListener)}. + * + * @param transferListener The listener that will be used. + * @return This factory. + */ + public Factory setTransferListener(@Nullable TransferListener transferListener) { + this.transferListener = transferListener; + return this; + } + + @Override + public RtmpDataSource createDataSource() { + RtmpDataSource dataSource = new RtmpDataSource(); + if (transferListener != null) { + dataSource.addTransferListener(transferListener); + } + return dataSource; + } + } + @Nullable private RtmpClient rtmpClient; @Nullable private Uri uri; @@ -54,8 +85,8 @@ public long open(DataSpec dataSpec) throws RtmpIOException { } @Override - public int read(byte[] buffer, int offset, int readLength) throws IOException { - int bytesRead = castNonNull(rtmpClient).read(buffer, offset, readLength); + public int read(byte[] buffer, int offset, int length) throws IOException { + int bytesRead = castNonNull(rtmpClient).read(buffer, offset, length); if (bytesRead == -1) { return C.RESULT_END_OF_INPUT; } @@ -80,5 +111,4 @@ public void close() { public Uri getUri() { return uri; } - } diff --git a/extensions/rtmp/src/main/java/com/google/android/exoplayer2/ext/rtmp/RtmpDataSourceFactory.java b/extensions/rtmp/src/main/java/com/google/android/exoplayer2/ext/rtmp/RtmpDataSourceFactory.java index 167a4175d74..7d05adb18df 100644 --- a/extensions/rtmp/src/main/java/com/google/android/exoplayer2/ext/rtmp/RtmpDataSourceFactory.java +++ b/extensions/rtmp/src/main/java/com/google/android/exoplayer2/ext/rtmp/RtmpDataSourceFactory.java @@ -17,10 +17,10 @@ import androidx.annotation.Nullable; import com.google.android.exoplayer2.upstream.DataSource; -import com.google.android.exoplayer2.upstream.HttpDataSource.Factory; import com.google.android.exoplayer2.upstream.TransferListener; -/** A {@link Factory} that produces {@link RtmpDataSource}. */ +/** @deprecated Use {@link RtmpDataSource.Factory} instead. */ +@Deprecated public final class RtmpDataSourceFactory implements DataSource.Factory { @Nullable private final TransferListener listener; @@ -42,5 +42,4 @@ public RtmpDataSource createDataSource() { } return dataSource; } - } diff --git a/extensions/vp9/README.md b/extensions/vp9/README.md index 30b7a252d0b..84f3f013265 100644 --- a/extensions/vp9/README.md +++ b/extensions/vp9/README.md @@ -146,7 +146,7 @@ GL rendering mode has better performance, so should be preferred. ## Links ## -* [Javadoc][]: Classes matching `com.google.android.exoplayer2.ext.vp9.*` - belong to this module. +* [Javadoc][]: Classes matching `com.google.android.exoplayer2.ext.vp9.*` + belong to this module. [Javadoc]: https://exoplayer.dev/doc/reference/index.html diff --git a/extensions/vp9/proguard-rules.txt b/extensions/vp9/proguard-rules.txt index 6e473eb21e1..56fca12d191 100644 --- a/extensions/vp9/proguard-rules.txt +++ b/extensions/vp9/proguard-rules.txt @@ -10,8 +10,3 @@ *; } -# The deprecated VpxOutputBuffer might be used by old binary versions. Remove -# once VpxOutputBuffer is removed. --keep class com.google.android.exoplayer2.ext.vp9.VpxOutputBuffer { - *; -} diff --git a/extensions/vp9/src/androidTest/java/com/google/android/exoplayer2/ext/vp9/VpxPlaybackTest.java b/extensions/vp9/src/androidTest/java/com/google/android/exoplayer2/ext/vp9/VpxPlaybackTest.java index d7a19f16629..b9d841ccf84 100644 --- a/extensions/vp9/src/androidTest/java/com/google/android/exoplayer2/ext/vp9/VpxPlaybackTest.java +++ b/extensions/vp9/src/androidTest/java/com/google/android/exoplayer2/ext/vp9/VpxPlaybackTest.java @@ -24,8 +24,8 @@ import androidx.annotation.Nullable; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; -import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.RenderersFactory; @@ -107,7 +107,7 @@ private static class TestPlaybackRunnable implements Player.Listener, Runnable { private final Uri uri; @Nullable private SimpleExoPlayer player; - @Nullable private ExoPlaybackException playbackException; + @Nullable private PlaybackException playbackException; public TestPlaybackRunnable(Uri uri, Context context) { this.uri = uri; @@ -144,7 +144,7 @@ public void run() { } @Override - public void onPlayerError(ExoPlaybackException error) { + public void onPlayerError(PlaybackException error) { playbackException = error; } @@ -157,5 +157,4 @@ public void onPlaybackStateChanged(@Player.State int playbackState) { } } } - } diff --git a/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxDecoder.java b/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxDecoder.java index 021ce3a9460..7e8eedb2100 100644 --- a/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxDecoder.java +++ b/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxDecoder.java @@ -145,8 +145,8 @@ protected VpxDecoderException decode( if (result != NO_ERROR) { if (result == DRM_ERROR) { String message = "Drm error: " + vpxGetErrorMessage(vpxDecContext); - DecryptionException cause = new DecryptionException( - vpxGetErrorCode(vpxDecContext), message); + DecryptionException cause = + new DecryptionException(vpxGetErrorCode(vpxDecContext), message); return new VpxDecoderException(message, cause); } else { return new VpxDecoderException("Decode error: " + vpxGetErrorMessage(vpxDecContext)); @@ -209,6 +209,7 @@ private native long vpxInit( boolean disableLoopFilter, boolean enableRowMultiThreadMode, int threads); private native long vpxClose(long context); + private native long vpxDecode(long context, ByteBuffer encoded, int length); private native long vpxSecureDecode( @@ -239,6 +240,6 @@ private native int vpxRenderFrame( private native int vpxReleaseFrame(long context, VideoDecoderOutputBuffer outputBuffer); private native int vpxGetErrorCode(long context); - private native String vpxGetErrorMessage(long context); + private native String vpxGetErrorMessage(long context); } diff --git a/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxLibrary.java b/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxLibrary.java index 339ec021c6d..8325265685a 100644 --- a/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxLibrary.java +++ b/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxLibrary.java @@ -48,9 +48,7 @@ public static void setLibraries( VpxLibrary.exoMediaCryptoType = exoMediaCryptoType; } - /** - * Returns whether the underlying library is available, loading it if necessary. - */ + /** Returns whether the underlying library is available, loading it if necessary. */ public static boolean isAvailable() { return LOADER.isAvailable(); } @@ -70,13 +68,10 @@ public static String getBuildConfig() { return isAvailable() ? vpxGetBuildConfig() : null; } - /** - * Returns true if the underlying libvpx library supports high bit depth. - */ + /** Returns true if the underlying libvpx library supports high bit depth. */ public static boolean isHighBitDepthSupported() { String config = getBuildConfig(); - int indexHbd = config != null - ? config.indexOf("--enable-vp9-highbitdepth") : -1; + int indexHbd = config != null ? config.indexOf("--enable-vp9-highbitdepth") : -1; return indexHbd >= 0; } @@ -90,7 +85,8 @@ public static boolean matchesExpectedExoMediaCryptoType( } private static native String vpxGetVersion(); + private static native String vpxGetBuildConfig(); - public static native boolean vpxIsSecureDecodeSupported(); + public static native boolean vpxIsSecureDecodeSupported(); } diff --git a/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxOutputBuffer.java b/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxOutputBuffer.java deleted file mode 100644 index 6d36164d1de..00000000000 --- a/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxOutputBuffer.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.android.exoplayer2.ext.vp9; - -import com.google.android.exoplayer2.video.VideoDecoderOutputBuffer; - -// TODO(b/139174707): Delete this class once binaries in WVVp9OpusPlaybackTest are updated to depend -// on VideoDecoderOutputBuffer. Also mark VideoDecoderOutputBuffer as final and remove proguard -// config for VpxOutputBuffer. -/** - * Video output buffer, populated by {@link VpxDecoder}. - * - * @deprecated Use {@link VideoDecoderOutputBuffer} instead. - */ -@Deprecated -public final class VpxOutputBuffer extends VideoDecoderOutputBuffer { - - /** - * Creates VpxOutputBuffer. - * - * @param owner Buffer owner. - */ - public VpxOutputBuffer(Owner owner) { - super(owner); - } -} diff --git a/extensions/vp9/src/main/jni/vpx_jni.cc b/extensions/vp9/src/main/jni/vpx_jni.cc index 1fc0f9d56e9..3f4c89dc7b4 100644 --- a/extensions/vp9/src/main/jni/vpx_jni.cc +++ b/extensions/vp9/src/main/jni/vpx_jni.cc @@ -18,12 +18,12 @@ #ifdef __ARM_NEON__ #include #endif -#include - #include #include #include +#include #include + #include #include #include @@ -31,12 +31,12 @@ #include #define VPX_CODEC_DISABLE_COMPAT 1 -#include "vpx/vpx_decoder.h" #include "vpx/vp8dx.h" +#include "vpx/vpx_decoder.h" #define LOG_TAG "vpx_jni" -#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, \ - __VA_ARGS__)) +#define LOGE(...) \ + ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) #define DECODER_FUNC(RETURN_TYPE, NAME, ...) \ extern "C" { \ @@ -480,12 +480,12 @@ DECODER_FUNC(jlong, vpxInit, jboolean disableLoopFilter, // Populate JNI References. const jclass outputBufferClass = env->FindClass( "com/google/android/exoplayer2/video/VideoDecoderOutputBuffer"); - initForYuvFrame = env->GetMethodID(outputBufferClass, "initForYuvFrame", - "(IIIII)Z"); + initForYuvFrame = + env->GetMethodID(outputBufferClass, "initForYuvFrame", "(IIIII)Z"); initForPrivateFrame = env->GetMethodID(outputBufferClass, "initForPrivateFrame", "(II)V"); - dataField = env->GetFieldID(outputBufferClass, "data", - "Ljava/nio/ByteBuffer;"); + dataField = + env->GetFieldID(outputBufferClass, "data", "Ljava/nio/ByteBuffer;"); outputModeField = env->GetFieldID(outputBufferClass, "mode", "I"); decoderPrivateField = env->GetFieldID(outputBufferClass, "decoderPrivate", "I"); @@ -508,9 +508,9 @@ DECODER_FUNC(jlong, vpxDecode, jlong jContext, jobject encoded, jint len) { } DECODER_FUNC(jlong, vpxSecureDecode, jlong jContext, jobject encoded, jint len, - jobject mediaCrypto, jint inputMode, jbyteArray&, jbyteArray&, - jint inputNumSubSamples, jintArray numBytesOfClearData, - jintArray numBytesOfEncryptedData) { + jobject mediaCrypto, jint inputMode, jbyteArray&, jbyteArray&, + jint inputNumSubSamples, jintArray numBytesOfClearData, + jintArray numBytesOfEncryptedData) { // Doesn't support // Java client should have checked vpxSupportSecureDecode // and avoid calling this @@ -534,19 +534,15 @@ DECODER_FUNC(jint, vpxGetFrame, jlong jContext, jobject jOutputBuffer) { return 1; } - // LINT.IfChange const int kOutputModeYuv = 0; const int kOutputModeSurfaceYuv = 1; - // LINT.ThenChange(../../../../../library/common/src/main/java/com/google/android/exoplayer2/C.java) int outputMode = env->GetIntField(jOutputBuffer, outputModeField); if (outputMode == kOutputModeYuv) { - // LINT.IfChange const int kColorspaceUnknown = 0; const int kColorspaceBT601 = 1; const int kColorspaceBT709 = 2; const int kColorspaceBT2020 = 3; - // LINT.ThenChange(../../../../../library/core/src/main/java/com/google/android/exoplayer2/video/VideoDecoderOutputBuffer.java) int colorspace = kColorspaceUnknown; switch (img->cs) { @@ -556,7 +552,7 @@ DECODER_FUNC(jint, vpxGetFrame, jlong jContext, jobject jOutputBuffer) { case VPX_CS_BT_709: colorspace = kColorspaceBT709; break; - case VPX_CS_BT_2020: + case VPX_CS_BT_2020: colorspace = kColorspaceBT2020; break; default: diff --git a/gradle.properties b/gradle.properties index 297016aec14..226168bb1d3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,7 @@ ## Project-wide Gradle settings. android.useAndroidX=true android.enableJetifier=true +# https://github.com/robolectric/robolectric/issues/6521#issuecomment-851736355 +android.jetifier.ignorelist=bcprov buildDir=buildout org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8efe8c9f90e..76c4be41e97 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https://services.gradle.org/distributions/gradle-6.7.1-all.zip +distributionUrl=https://services.gradle.org/distributions/gradle-6.9-all.zip diff --git a/library/common/build.gradle b/library/common/build.gradle index d1d0d86f422..bdfe7a00f37 100644 --- a/library/common/build.gradle +++ b/library/common/build.gradle @@ -35,8 +35,9 @@ dependencies { testImplementation 'androidx.test.ext:junit:' + androidxTestJUnitVersion testImplementation 'junit:junit:' + junitVersion testImplementation 'com.google.truth:truth:' + truthVersion - testImplementation 'com.squareup.okhttp3:mockwebserver:' + mockWebServerVersion + testImplementation 'com.squareup.okhttp3:mockwebserver:' + okhttpVersion testImplementation 'org.robolectric:robolectric:' + robolectricVersion + testImplementation project(modulePrefix + 'library-core') testImplementation project(modulePrefix + 'testutils') } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/BasePlayer.java b/library/common/src/main/java/com/google/android/exoplayer2/BasePlayer.java index 57550d589b6..74b5760ca7e 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/BasePlayer.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/BasePlayer.java @@ -15,6 +15,9 @@ */ package com.google.android.exoplayer2; +import static java.lang.Math.max; +import static java.lang.Math.min; + import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Util; import java.util.Collections; @@ -25,7 +28,7 @@ public abstract class BasePlayer implements Player { protected final Timeline.Window window; - public BasePlayer() { + protected BasePlayer() { window = new Timeline.Window(); } @@ -86,14 +89,6 @@ public final boolean isCommandAvailable(@Command int command) { return getAvailableCommands().contains(command); } - /** @deprecated Use {@link #getPlayerError()} instead. */ - @Deprecated - @Override - @Nullable - public final ExoPlaybackException getPlaybackError() { - return getPlayerError(); - } - @Override public final void play() { setPlayWhenReady(true); @@ -126,32 +121,97 @@ public final void seekTo(long positionMs) { seekTo(getCurrentWindowIndex(), positionMs); } + @Override + public final void seekBack() { + seekToOffset(-getSeekBackIncrement()); + } + + @Override + public final void seekForward() { + seekToOffset(getSeekForwardIncrement()); + } + + @Deprecated @Override public final boolean hasPrevious() { + return hasPreviousWindow(); + } + + @Override + public final boolean hasPreviousWindow() { return getPreviousWindowIndex() != C.INDEX_UNSET; } + @Deprecated @Override public final void previous() { + seekToPreviousWindow(); + } + + @Override + public final void seekToPreviousWindow() { int previousWindowIndex = getPreviousWindowIndex(); if (previousWindowIndex != C.INDEX_UNSET) { seekToDefaultPosition(previousWindowIndex); } } + @Override + public final void seekToPrevious() { + Timeline timeline = getCurrentTimeline(); + if (timeline.isEmpty() || isPlayingAd()) { + return; + } + boolean hasPreviousWindow = hasPreviousWindow(); + if (isCurrentWindowLive() && !isCurrentWindowSeekable()) { + if (hasPreviousWindow) { + seekToPreviousWindow(); + } + } else if (hasPreviousWindow && getCurrentPosition() <= getMaxSeekToPreviousPosition()) { + seekToPreviousWindow(); + } else { + seekTo(/* positionMs= */ 0); + } + } + + @Deprecated @Override public final boolean hasNext() { + return hasNextWindow(); + } + + @Override + public final boolean hasNextWindow() { return getNextWindowIndex() != C.INDEX_UNSET; } + @Deprecated @Override public final void next() { + seekToNextWindow(); + } + + @Override + public final void seekToNextWindow() { int nextWindowIndex = getNextWindowIndex(); if (nextWindowIndex != C.INDEX_UNSET) { seekToDefaultPosition(nextWindowIndex); } } + @Override + public final void seekToNext() { + Timeline timeline = getCurrentTimeline(); + if (timeline.isEmpty() || isPlayingAd()) { + return; + } + if (hasNextWindow()) { + seekToNextWindow(); + } else if (isCurrentWindowLive() && isCurrentWindowDynamic()) { + seekToDefaultPosition(); + } + } + @Override public final void setPlaybackSpeed(float speed) { setPlaybackParameters(getPlaybackParameters().withSpeed(speed)); @@ -180,24 +240,6 @@ public final int getPreviousWindowIndex() { getCurrentWindowIndex(), getRepeatModeForNavigation(), getShuffleModeEnabled()); } - /** - * @deprecated Use {@link #getCurrentMediaItem()} and {@link MediaItem.PlaybackProperties#tag} - * instead. - */ - @Deprecated - @Override - @Nullable - public final Object getCurrentTag() { - Timeline timeline = getCurrentTimeline(); - if (timeline.isEmpty()) { - return null; - } - @Nullable - MediaItem.PlaybackProperties playbackProperties = - timeline.getWindow(getCurrentWindowIndex(), window).mediaItem.playbackProperties; - return playbackProperties != null ? playbackProperties.tag : null; - } - @Override @Nullable public final MediaItem getCurrentMediaItem() { @@ -272,20 +314,48 @@ public final long getContentDuration() { : timeline.getWindow(getCurrentWindowIndex(), window).getDurationMs(); } + /** + * Returns the {@link Commands} available in the player. + * + * @param permanentAvailableCommands The commands permanently available in the player. + * @return The available {@link Commands}. + */ + protected Commands getAvailableCommands(Commands permanentAvailableCommands) { + return new Commands.Builder() + .addAll(permanentAvailableCommands) + .addIf(COMMAND_SEEK_TO_DEFAULT_POSITION, !isPlayingAd()) + .addIf(COMMAND_SEEK_IN_CURRENT_WINDOW, isCurrentWindowSeekable() && !isPlayingAd()) + .addIf(COMMAND_SEEK_TO_PREVIOUS_WINDOW, hasPreviousWindow() && !isPlayingAd()) + .addIf( + COMMAND_SEEK_TO_PREVIOUS, + !getCurrentTimeline().isEmpty() + && (hasPreviousWindow() || !isCurrentWindowLive() || isCurrentWindowSeekable()) + && !isPlayingAd()) + .addIf(COMMAND_SEEK_TO_NEXT_WINDOW, hasNextWindow() && !isPlayingAd()) + .addIf( + COMMAND_SEEK_TO_NEXT, + !getCurrentTimeline().isEmpty() + && (hasNextWindow() || (isCurrentWindowLive() && isCurrentWindowDynamic())) + && !isPlayingAd()) + .addIf(COMMAND_SEEK_TO_WINDOW, !isPlayingAd()) + .addIf(COMMAND_SEEK_BACK, isCurrentWindowSeekable() && !isPlayingAd()) + .addIf(COMMAND_SEEK_FORWARD, isCurrentWindowSeekable() && !isPlayingAd()) + .build(); + } + @RepeatMode private int getRepeatModeForNavigation() { @RepeatMode int repeatMode = getRepeatMode(); return repeatMode == REPEAT_MODE_ONE ? REPEAT_MODE_OFF : repeatMode; } - protected Commands getAvailableCommands(Commands permanentAvailableCommands) { - return new Commands.Builder() - .addAll(permanentAvailableCommands) - .addIf(COMMAND_SEEK_TO_DEFAULT_POSITION, !isPlayingAd()) - .addIf(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, isCurrentWindowSeekable() && !isPlayingAd()) - .addIf(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, hasNext() && !isPlayingAd()) - .addIf(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM, hasPrevious() && !isPlayingAd()) - .addIf(COMMAND_SEEK_TO_MEDIA_ITEM, !isPlayingAd()) - .build(); + private void seekToOffset(long offsetMs) { + long positionMs = getCurrentPosition() + offsetMs; + long durationMs = getDuration(); + if (durationMs != C.TIME_UNSET) { + positionMs = min(positionMs, durationMs); + } + positionMs = max(positionMs, 0); + seekTo(positionMs); } } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/C.java b/library/common/src/main/java/com/google/android/exoplayer2/C.java index eba6c0cfcda..b5df4c4e1ca 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/C.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/C.java @@ -49,14 +49,10 @@ private C() {} */ public static final long TIME_UNSET = Long.MIN_VALUE + 1; - /** - * Represents an unset or unknown index. - */ + /** Represents an unset or unknown index. */ public static final int INDEX_UNSET = -1; - /** - * Represents an unset or unknown position. - */ + /** Represents an unset or unknown position. */ public static final int POSITION_UNSET = -1; /** Represents an unset or unknown rate. */ @@ -74,9 +70,7 @@ private C() {} /** The number of microseconds in one second. */ public static final long MICROS_PER_SECOND = 1000000L; - /** - * The number of nanoseconds in one second. - */ + /** The number of nanoseconds in one second. */ public static final long NANOS_PER_SECOND = 1000000000L; /** The number of bits per byte. */ @@ -115,14 +109,10 @@ private C() {} */ @Deprecated public static final String UTF16LE_NAME = "UTF-16LE"; - /** - * The name of the serif font family. - */ + /** The name of the serif font family. */ public static final String SERIF_NAME = "serif"; - /** - * The name of the sans-serif font family. - */ + /** The name of the sans-serif font family. */ public static final String SANS_SERIF_NAME = "sans-serif"; /** @@ -133,22 +123,16 @@ private C() {} @Retention(RetentionPolicy.SOURCE) @IntDef({CRYPTO_MODE_UNENCRYPTED, CRYPTO_MODE_AES_CTR, CRYPTO_MODE_AES_CBC}) public @interface CryptoMode {} - /** - * @see MediaCodec#CRYPTO_MODE_UNENCRYPTED - */ + /** @see MediaCodec#CRYPTO_MODE_UNENCRYPTED */ public static final int CRYPTO_MODE_UNENCRYPTED = MediaCodec.CRYPTO_MODE_UNENCRYPTED; - /** - * @see MediaCodec#CRYPTO_MODE_AES_CTR - */ + /** @see MediaCodec#CRYPTO_MODE_AES_CTR */ public static final int CRYPTO_MODE_AES_CTR = MediaCodec.CRYPTO_MODE_AES_CTR; - /** - * @see MediaCodec#CRYPTO_MODE_AES_CBC - */ + /** @see MediaCodec#CRYPTO_MODE_AES_CBC */ public static final int CRYPTO_MODE_AES_CBC = MediaCodec.CRYPTO_MODE_AES_CBC; /** - * Represents an unset {@link android.media.AudioTrack} session identifier. Equal to - * {@link AudioManager#AUDIO_SESSION_ID_GENERATE}. + * Represents an unset {@link android.media.AudioTrack} session identifier. Equal to {@link + * AudioManager#AUDIO_SESSION_ID_GENERATE}. */ public static final int AUDIO_SESSION_ID_UNSET = AudioManager.AUDIO_SESSION_ID_GENERATE; @@ -267,33 +251,19 @@ private C() {} STREAM_TYPE_VOICE_CALL }) public @interface StreamType {} - /** - * @see AudioManager#STREAM_ALARM - */ + /** @see AudioManager#STREAM_ALARM */ public static final int STREAM_TYPE_ALARM = AudioManager.STREAM_ALARM; - /** - * @see AudioManager#STREAM_DTMF - */ + /** @see AudioManager#STREAM_DTMF */ public static final int STREAM_TYPE_DTMF = AudioManager.STREAM_DTMF; - /** - * @see AudioManager#STREAM_MUSIC - */ + /** @see AudioManager#STREAM_MUSIC */ public static final int STREAM_TYPE_MUSIC = AudioManager.STREAM_MUSIC; - /** - * @see AudioManager#STREAM_NOTIFICATION - */ + /** @see AudioManager#STREAM_NOTIFICATION */ public static final int STREAM_TYPE_NOTIFICATION = AudioManager.STREAM_NOTIFICATION; - /** - * @see AudioManager#STREAM_RING - */ + /** @see AudioManager#STREAM_RING */ public static final int STREAM_TYPE_RING = AudioManager.STREAM_RING; - /** - * @see AudioManager#STREAM_SYSTEM - */ + /** @see AudioManager#STREAM_SYSTEM */ public static final int STREAM_TYPE_SYSTEM = AudioManager.STREAM_SYSTEM; - /** - * @see AudioManager#STREAM_VOICE_CALL - */ + /** @see AudioManager#STREAM_VOICE_CALL */ public static final int STREAM_TYPE_VOICE_CALL = AudioManager.STREAM_VOICE_CALL; /** The default stream type used by audio renderers. Equal to {@link #STREAM_TYPE_MUSIC}. */ public static final int STREAM_TYPE_DEFAULT = STREAM_TYPE_MUSIC; @@ -313,29 +283,17 @@ private C() {} CONTENT_TYPE_UNKNOWN }) public @interface AudioContentType {} - /** - * @see android.media.AudioAttributes#CONTENT_TYPE_MOVIE - */ + /** @see android.media.AudioAttributes#CONTENT_TYPE_MOVIE */ public static final int CONTENT_TYPE_MOVIE = android.media.AudioAttributes.CONTENT_TYPE_MOVIE; - /** - * @see android.media.AudioAttributes#CONTENT_TYPE_MUSIC - */ + /** @see android.media.AudioAttributes#CONTENT_TYPE_MUSIC */ public static final int CONTENT_TYPE_MUSIC = android.media.AudioAttributes.CONTENT_TYPE_MUSIC; - /** - * @see android.media.AudioAttributes#CONTENT_TYPE_SONIFICATION - */ + /** @see android.media.AudioAttributes#CONTENT_TYPE_SONIFICATION */ public static final int CONTENT_TYPE_SONIFICATION = android.media.AudioAttributes.CONTENT_TYPE_SONIFICATION; - /** - * @see android.media.AudioAttributes#CONTENT_TYPE_SPEECH - */ - public static final int CONTENT_TYPE_SPEECH = - android.media.AudioAttributes.CONTENT_TYPE_SPEECH; - /** - * @see android.media.AudioAttributes#CONTENT_TYPE_UNKNOWN - */ - public static final int CONTENT_TYPE_UNKNOWN = - android.media.AudioAttributes.CONTENT_TYPE_UNKNOWN; + /** @see android.media.AudioAttributes#CONTENT_TYPE_SPEECH */ + public static final int CONTENT_TYPE_SPEECH = android.media.AudioAttributes.CONTENT_TYPE_SPEECH; + /** @see android.media.AudioAttributes#CONTENT_TYPE_UNKNOWN */ + public static final int CONTENT_TYPE_UNKNOWN = android.media.AudioAttributes.CONTENT_TYPE_UNKNOWN; /** * Flags for audio attributes. Possible flag value is {@link #FLAG_AUDIBILITY_ENFORCED}. @@ -349,9 +307,7 @@ private C() {} flag = true, value = {FLAG_AUDIBILITY_ENFORCED}) public @interface AudioFlags {} - /** - * @see android.media.AudioAttributes#FLAG_AUDIBILITY_ENFORCED - */ + /** @see android.media.AudioAttributes#FLAG_AUDIBILITY_ENFORCED */ public static final int FLAG_AUDIBILITY_ENFORCED = android.media.AudioAttributes.FLAG_AUDIBILITY_ENFORCED; @@ -386,74 +342,46 @@ private C() {} USAGE_VOICE_COMMUNICATION_SIGNALLING }) public @interface AudioUsage {} - /** - * @see android.media.AudioAttributes#USAGE_ALARM - */ + /** @see android.media.AudioAttributes#USAGE_ALARM */ public static final int USAGE_ALARM = android.media.AudioAttributes.USAGE_ALARM; /** @see android.media.AudioAttributes#USAGE_ASSISTANCE_ACCESSIBILITY */ public static final int USAGE_ASSISTANCE_ACCESSIBILITY = android.media.AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY; - /** - * @see android.media.AudioAttributes#USAGE_ASSISTANCE_NAVIGATION_GUIDANCE - */ + /** @see android.media.AudioAttributes#USAGE_ASSISTANCE_NAVIGATION_GUIDANCE */ public static final int USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = android.media.AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE; - /** - * @see android.media.AudioAttributes#USAGE_ASSISTANCE_SONIFICATION - */ + /** @see android.media.AudioAttributes#USAGE_ASSISTANCE_SONIFICATION */ public static final int USAGE_ASSISTANCE_SONIFICATION = android.media.AudioAttributes.USAGE_ASSISTANCE_SONIFICATION; /** @see android.media.AudioAttributes#USAGE_ASSISTANT */ public static final int USAGE_ASSISTANT = android.media.AudioAttributes.USAGE_ASSISTANT; - /** - * @see android.media.AudioAttributes#USAGE_GAME - */ + /** @see android.media.AudioAttributes#USAGE_GAME */ public static final int USAGE_GAME = android.media.AudioAttributes.USAGE_GAME; - /** - * @see android.media.AudioAttributes#USAGE_MEDIA - */ + /** @see android.media.AudioAttributes#USAGE_MEDIA */ public static final int USAGE_MEDIA = android.media.AudioAttributes.USAGE_MEDIA; - /** - * @see android.media.AudioAttributes#USAGE_NOTIFICATION - */ + /** @see android.media.AudioAttributes#USAGE_NOTIFICATION */ public static final int USAGE_NOTIFICATION = android.media.AudioAttributes.USAGE_NOTIFICATION; - /** - * @see android.media.AudioAttributes#USAGE_NOTIFICATION_COMMUNICATION_DELAYED - */ + /** @see android.media.AudioAttributes#USAGE_NOTIFICATION_COMMUNICATION_DELAYED */ public static final int USAGE_NOTIFICATION_COMMUNICATION_DELAYED = android.media.AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_DELAYED; - /** - * @see android.media.AudioAttributes#USAGE_NOTIFICATION_COMMUNICATION_INSTANT - */ + /** @see android.media.AudioAttributes#USAGE_NOTIFICATION_COMMUNICATION_INSTANT */ public static final int USAGE_NOTIFICATION_COMMUNICATION_INSTANT = android.media.AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT; - /** - * @see android.media.AudioAttributes#USAGE_NOTIFICATION_COMMUNICATION_REQUEST - */ + /** @see android.media.AudioAttributes#USAGE_NOTIFICATION_COMMUNICATION_REQUEST */ public static final int USAGE_NOTIFICATION_COMMUNICATION_REQUEST = android.media.AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST; - /** - * @see android.media.AudioAttributes#USAGE_NOTIFICATION_EVENT - */ + /** @see android.media.AudioAttributes#USAGE_NOTIFICATION_EVENT */ public static final int USAGE_NOTIFICATION_EVENT = android.media.AudioAttributes.USAGE_NOTIFICATION_EVENT; - /** - * @see android.media.AudioAttributes#USAGE_NOTIFICATION_RINGTONE - */ + /** @see android.media.AudioAttributes#USAGE_NOTIFICATION_RINGTONE */ public static final int USAGE_NOTIFICATION_RINGTONE = android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE; - /** - * @see android.media.AudioAttributes#USAGE_UNKNOWN - */ + /** @see android.media.AudioAttributes#USAGE_UNKNOWN */ public static final int USAGE_UNKNOWN = android.media.AudioAttributes.USAGE_UNKNOWN; - /** - * @see android.media.AudioAttributes#USAGE_VOICE_COMMUNICATION - */ + /** @see android.media.AudioAttributes#USAGE_VOICE_COMMUNICATION */ public static final int USAGE_VOICE_COMMUNICATION = android.media.AudioAttributes.USAGE_VOICE_COMMUNICATION; - /** - * @see android.media.AudioAttributes#USAGE_VOICE_COMMUNICATION_SIGNALLING - */ + /** @see android.media.AudioAttributes#USAGE_VOICE_COMMUNICATION_SIGNALLING */ public static final int USAGE_VOICE_COMMUNICATION_SIGNALLING = android.media.AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING; @@ -518,13 +446,9 @@ private C() {} BUFFER_FLAG_DECODE_ONLY }) public @interface BufferFlags {} - /** - * Indicates that a buffer holds a synchronization sample. - */ + /** Indicates that a buffer holds a synchronization sample. */ public static final int BUFFER_FLAG_KEY_FRAME = MediaCodec.BUFFER_FLAG_KEY_FRAME; - /** - * Flag for empty buffers that signal that the end of the stream was reached. - */ + /** Flag for empty buffers that signal that the end of the stream was reached. */ public static final int BUFFER_FLAG_END_OF_STREAM = MediaCodec.BUFFER_FLAG_END_OF_STREAM; /** Indicates that a buffer has supplemental data. */ public static final int BUFFER_FLAG_HAS_SUPPLEMENTAL_DATA = 1 << 28; // 0x10000000 @@ -535,7 +459,6 @@ private C() {} /** Indicates that a buffer should be decoded but not rendered. */ public static final int BUFFER_FLAG_DECODE_ONLY = 1 << 31; // 0x80000000 - // LINT.IfChange /** * Video decoder output modes. Possible modes are {@link #VIDEO_OUTPUT_MODE_NONE}, {@link * #VIDEO_OUTPUT_MODE_YUV} and {@link #VIDEO_OUTPUT_MODE_SURFACE_YUV}. @@ -550,10 +473,6 @@ private C() {} public static final int VIDEO_OUTPUT_MODE_YUV = 0; /** Video decoder output mode that renders 4:2:0 YUV planes directly to a surface. */ public static final int VIDEO_OUTPUT_MODE_SURFACE_YUV = 1; - // LINT.ThenChange( - // ../../../../../../../../../../../media/libraries/decoder_av1/src/main/jni/gav1_jni.cc, - // ../../../../../../../../../../../media/libraries/decoder_vp9/src/main/jni/vpx_jni.cc - // ) /** * Video scaling modes for {@link MediaCodec}-based renderers. One of {@link @@ -582,9 +501,7 @@ private C() {} flag = true, value = {SELECTION_FLAG_DEFAULT, SELECTION_FLAG_FORCED, SELECTION_FLAG_AUTOSELECT}) public @interface SelectionFlags {} - /** - * Indicates that the track should be selected if user preferences do not state otherwise. - */ + /** Indicates that the track should be selected if user preferences do not state otherwise. */ public static final int SELECTION_FLAG_DEFAULT = 1; /** * Indicates that the track should be selected if its language matches the language of the @@ -613,17 +530,11 @@ private C() {} @Retention(RetentionPolicy.SOURCE) @IntDef({TYPE_DASH, TYPE_SS, TYPE_HLS, TYPE_RTSP, TYPE_OTHER}) public @interface ContentType {} - /** - * Value returned by {@link Util#inferContentType(String)} for DASH manifests. - */ + /** Value returned by {@link Util#inferContentType(String)} for DASH manifests. */ public static final int TYPE_DASH = 0; - /** - * Value returned by {@link Util#inferContentType(String)} for Smooth Streaming manifests. - */ + /** Value returned by {@link Util#inferContentType(String)} for Smooth Streaming manifests. */ public static final int TYPE_SS = 1; - /** - * Value returned by {@link Util#inferContentType(String)} for HLS manifests. - */ + /** Value returned by {@link Util#inferContentType(String)} for HLS manifests. */ public static final int TYPE_HLS = 2; /** Value returned by {@link Util#inferContentType(String)} for RTSP. */ public static final int TYPE_RTSP = 3; @@ -633,27 +544,41 @@ private C() {} */ public static final int TYPE_OTHER = 4; - /** - * A return value for methods where the end of an input was encountered. - */ + /** A return value for methods where the end of an input was encountered. */ public static final int RESULT_END_OF_INPUT = -1; /** * A return value for methods where the length of parsed data exceeds the maximum length allowed. */ public static final int RESULT_MAX_LENGTH_EXCEEDED = -2; - /** - * A return value for methods where nothing was read. - */ + /** A return value for methods where nothing was read. */ public static final int RESULT_NOTHING_READ = -3; - /** - * A return value for methods where a buffer was read. - */ + /** A return value for methods where a buffer was read. */ public static final int RESULT_BUFFER_READ = -4; - /** - * A return value for methods where a format was read. - */ + /** A return value for methods where a format was read. */ public static final int RESULT_FORMAT_READ = -5; + /** + * Represents a type of data. May be one of {@link #DATA_TYPE_UNKNOWN}, {@link #DATA_TYPE_MEDIA}, + * {@link #DATA_TYPE_MEDIA_INITIALIZATION}, {@link #DATA_TYPE_DRM}, {@link #DATA_TYPE_MANIFEST}, + * {@link #DATA_TYPE_TIME_SYNCHRONIZATION}, {@link #DATA_TYPE_AD}, or {@link + * #DATA_TYPE_MEDIA_PROGRESSIVE_LIVE}. May also be an app-defined value (see {@link + * #DATA_TYPE_CUSTOM_BASE}). + */ + @Documented + @Retention(RetentionPolicy.SOURCE) + @IntDef( + open = true, + value = { + DATA_TYPE_UNKNOWN, + DATA_TYPE_MEDIA, + DATA_TYPE_MEDIA_INITIALIZATION, + DATA_TYPE_DRM, + DATA_TYPE_MANIFEST, + DATA_TYPE_TIME_SYNCHRONIZATION, + DATA_TYPE_AD, + DATA_TYPE_MEDIA_PROGRESSIVE_LIVE + }) + public @interface DataType {} /** A data type constant for data of unknown or unspecified type. */ public static final int DATA_TYPE_UNKNOWN = 0; /** A data type constant for media, typically containing media samples. */ @@ -702,25 +627,15 @@ private C() {} */ public static final int TRACK_TYPE_CUSTOM_BASE = 10000; - /** - * A selection reason constant for selections whose reasons are unknown or unspecified. - */ + /** A selection reason constant for selections whose reasons are unknown or unspecified. */ public static final int SELECTION_REASON_UNKNOWN = 0; - /** - * A selection reason constant for an initial track selection. - */ + /** A selection reason constant for an initial track selection. */ public static final int SELECTION_REASON_INITIAL = 1; - /** - * A selection reason constant for an manual (i.e. user initiated) track selection. - */ + /** A selection reason constant for an manual (i.e. user initiated) track selection. */ public static final int SELECTION_REASON_MANUAL = 2; - /** - * A selection reason constant for an adaptive track selection. - */ + /** A selection reason constant for an adaptive track selection. */ public static final int SELECTION_REASON_ADAPTIVE = 3; - /** - * A selection reason constant for a trick play track selection. - */ + /** A selection reason constant for a trick play track selection. */ public static final int SELECTION_REASON_TRICK_PLAY = 4; /** * Applications or extensions may define custom {@code SELECTION_REASON_*} constants greater than @@ -731,6 +646,17 @@ private C() {} /** A default size in bytes for an individual allocation that forms part of a larger buffer. */ public static final int DEFAULT_BUFFER_SEGMENT_SIZE = 64 * 1024; + /** A default seek back increment, in milliseconds. */ + public static final long DEFAULT_SEEK_BACK_INCREMENT_MS = 5000; + /** A default seek forward increment, in milliseconds. */ + public static final long DEFAULT_SEEK_FORWARD_INCREMENT_MS = 15_000; + + /** + * A default maximum position for which a seek to previous will seek to the previous window, in + * milliseconds. + */ + public static final int DEFAULT_MAX_SEEK_TO_PREVIOUS_POSITION_MS = 3000; + /** "cenc" scheme type name as defined in ISO/IEC 23001-7:2016. */ @SuppressWarnings("ConstantField") public static final String CENC_TYPE_cenc = "cenc"; @@ -748,36 +674,36 @@ private C() {} public static final String CENC_TYPE_cbcs = "cbcs"; /** - * The Nil UUID as defined by - * RFC4122. + * The Nil UUID as defined by RFC4122. */ public static final UUID UUID_NIL = new UUID(0L, 0L); /** - * UUID for the W3C - * Common PSSH + * UUID for the W3C Common PSSH * box. */ public static final UUID COMMON_PSSH_UUID = new UUID(0x1077EFECC0B24D02L, 0xACE33C1E52E2FB4BL); /** * UUID for the ClearKey DRM scheme. - *

      - * ClearKey is supported on Android devices running Android 5.0 (API Level 21) and up. + * + *

      ClearKey is supported on Android devices running Android 5.0 (API Level 21) and up. */ public static final UUID CLEARKEY_UUID = new UUID(0xE2719D58A985B3C9L, 0x781AB030AF78D30EL); /** * UUID for the Widevine DRM scheme. - *

      - * Widevine is supported on Android devices running Android 4.3 (API Level 18) and up. + * + *

      Widevine is supported on Android devices running Android 4.3 (API Level 18) and up. */ public static final UUID WIDEVINE_UUID = new UUID(0xEDEF8BA979D64ACEL, 0xA3C827DCD51D21EDL); /** * UUID for the PlayReady DRM scheme. - *

      - * PlayReady is supported on all AndroidTV devices. Note that most other Android devices do not + * + *

      PlayReady is supported on all AndroidTV devices. Note that most other Android devices do not * provide PlayReady support. */ public static final UUID PLAYREADY_UUID = new UUID(0x9A04F07998404286L, 0xAB92E65BE0885F95L); @@ -821,21 +747,15 @@ private C() {} STEREO_MODE_STEREO_MESH }) public @interface StereoMode {} - /** - * Indicates Monoscopic stereo layout, used with 360/3D/VR videos. - */ + /** Indicates Monoscopic stereo layout, used with 360/3D/VR videos. */ public static final int STEREO_MODE_MONO = 0; - /** - * Indicates Top-Bottom stereo layout, used with 360/3D/VR videos. - */ + /** Indicates Top-Bottom stereo layout, used with 360/3D/VR videos. */ public static final int STEREO_MODE_TOP_BOTTOM = 1; - /** - * Indicates Left-Right stereo layout, used with 360/3D/VR videos. - */ + /** Indicates Left-Right stereo layout, used with 360/3D/VR videos. */ public static final int STEREO_MODE_LEFT_RIGHT = 2; /** - * Indicates a stereo layout where the left and right eyes have separate meshes, - * used with 360/3D/VR videos. + * Indicates a stereo layout where the left and right eyes have separate meshes, used with + * 360/3D/VR videos. */ public static final int STEREO_MODE_STEREO_MESH = 3; @@ -847,17 +767,11 @@ private C() {} @Retention(RetentionPolicy.SOURCE) @IntDef({Format.NO_VALUE, COLOR_SPACE_BT709, COLOR_SPACE_BT601, COLOR_SPACE_BT2020}) public @interface ColorSpace {} - /** - * @see MediaFormat#COLOR_STANDARD_BT709 - */ + /** @see MediaFormat#COLOR_STANDARD_BT709 */ public static final int COLOR_SPACE_BT709 = MediaFormat.COLOR_STANDARD_BT709; - /** - * @see MediaFormat#COLOR_STANDARD_BT601_PAL - */ + /** @see MediaFormat#COLOR_STANDARD_BT601_PAL */ public static final int COLOR_SPACE_BT601 = MediaFormat.COLOR_STANDARD_BT601_PAL; - /** - * @see MediaFormat#COLOR_STANDARD_BT2020 - */ + /** @see MediaFormat#COLOR_STANDARD_BT2020 */ public static final int COLOR_SPACE_BT2020 = MediaFormat.COLOR_STANDARD_BT2020; /** @@ -868,17 +782,11 @@ private C() {} @Retention(RetentionPolicy.SOURCE) @IntDef({Format.NO_VALUE, COLOR_TRANSFER_SDR, COLOR_TRANSFER_ST2084, COLOR_TRANSFER_HLG}) public @interface ColorTransfer {} - /** - * @see MediaFormat#COLOR_TRANSFER_SDR_VIDEO - */ + /** @see MediaFormat#COLOR_TRANSFER_SDR_VIDEO */ public static final int COLOR_TRANSFER_SDR = MediaFormat.COLOR_TRANSFER_SDR_VIDEO; - /** - * @see MediaFormat#COLOR_TRANSFER_ST2084 - */ + /** @see MediaFormat#COLOR_TRANSFER_ST2084 */ public static final int COLOR_TRANSFER_ST2084 = MediaFormat.COLOR_TRANSFER_ST2084; - /** - * @see MediaFormat#COLOR_TRANSFER_HLG - */ + /** @see MediaFormat#COLOR_TRANSFER_HLG */ public static final int COLOR_TRANSFER_HLG = MediaFormat.COLOR_TRANSFER_HLG; /** @@ -889,13 +797,9 @@ private C() {} @Retention(RetentionPolicy.SOURCE) @IntDef({Format.NO_VALUE, COLOR_RANGE_LIMITED, COLOR_RANGE_FULL}) public @interface ColorRange {} - /** - * @see MediaFormat#COLOR_RANGE_LIMITED - */ + /** @see MediaFormat#COLOR_RANGE_LIMITED */ public static final int COLOR_RANGE_LIMITED = MediaFormat.COLOR_RANGE_LIMITED; - /** - * @see MediaFormat#COLOR_RANGE_FULL - */ + /** @see MediaFormat#COLOR_RANGE_FULL */ public static final int COLOR_RANGE_FULL = MediaFormat.COLOR_RANGE_FULL; /** Video projection types. */ @@ -1155,8 +1059,8 @@ public static long usToMs(long timeUs) { } /** - * Converts a time in milliseconds to the corresponding time in microseconds, preserving - * {@link #TIME_UNSET} values and {@link #TIME_END_OF_SOURCE} values. + * Converts a time in milliseconds to the corresponding time in microseconds, preserving {@link + * #TIME_UNSET} values and {@link #TIME_END_OF_SOURCE} values. * * @param timeMs The time in milliseconds. * @return The corresponding time in microseconds. @@ -1200,4 +1104,55 @@ public static String getFormatSupportString(@FormatSupport int formatSupport) { throw new IllegalStateException(); } } + + // Copy of relevant error codes defined in MediaDrm.ErrorCodes from API 31. + // TODO (internal b/192337376): Remove once ExoPlayer depends on SDK 31. + private static final int ERROR_KEY_EXPIRED = 2; + private static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION = 4; + private static final int ERROR_INSUFFICIENT_SECURITY = 7; + private static final int ERROR_FRAME_TOO_LARGE = 8; + private static final int ERROR_CERTIFICATE_MALFORMED = 10; + private static final int ERROR_INIT_DATA = 15; + private static final int ERROR_KEY_NOT_LOADED = 16; + private static final int ERROR_LICENSE_PARSE = 17; + private static final int ERROR_LICENSE_POLICY = 18; + private static final int ERROR_LICENSE_RELEASE = 19; + private static final int ERROR_LICENSE_REQUEST_REJECTED = 20; + private static final int ERROR_LICENSE_RESTORE = 21; + private static final int ERROR_LICENSE_STATE = 22; + private static final int ERROR_PROVISIONING_CERTIFICATE = 24; + private static final int ERROR_PROVISIONING_CONFIG = 25; + private static final int ERROR_PROVISIONING_PARSE = 26; + private static final int ERROR_PROVISIONING_REQUEST_REJECTED = 27; + private static final int ERROR_PROVISIONING_RETRY = 28; + + @PlaybackException.ErrorCode + public static int getErrorCodeForMediaDrmErrorCode(int mediaDrmErrorCode) { + switch (mediaDrmErrorCode) { + case ERROR_PROVISIONING_CONFIG: + case ERROR_PROVISIONING_PARSE: + case ERROR_PROVISIONING_REQUEST_REJECTED: + case ERROR_PROVISIONING_CERTIFICATE: + case ERROR_PROVISIONING_RETRY: + return PlaybackException.ERROR_CODE_DRM_PROVISIONING_FAILED; + case ERROR_LICENSE_PARSE: + case ERROR_LICENSE_RELEASE: + case ERROR_LICENSE_REQUEST_REJECTED: + case ERROR_LICENSE_RESTORE: + case ERROR_LICENSE_STATE: + case ERROR_CERTIFICATE_MALFORMED: + return PlaybackException.ERROR_CODE_DRM_LICENSE_ACQUISITION_FAILED; + case ERROR_LICENSE_POLICY: + case ERROR_INSUFFICIENT_OUTPUT_PROTECTION: + case ERROR_INSUFFICIENT_SECURITY: + case ERROR_KEY_EXPIRED: + case ERROR_KEY_NOT_LOADED: + return PlaybackException.ERROR_CODE_DRM_DISALLOWED_OPERATION; + case ERROR_INIT_DATA: + case ERROR_FRAME_TOO_LARGE: + return PlaybackException.ERROR_CODE_DRM_CONTENT_ERROR; + default: + return PlaybackException.ERROR_CODE_DRM_SYSTEM_ERROR; + } + } } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/ControlDispatcher.java b/library/common/src/main/java/com/google/android/exoplayer2/ControlDispatcher.java index 4e9b20acf35..a24131e9560 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/ControlDispatcher.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/ControlDispatcher.java @@ -17,13 +17,8 @@ import com.google.android.exoplayer2.Player.RepeatMode; -/** - * Dispatches operations to the {@link Player}. - * - *

      Implementations may choose to suppress (e.g. prevent playback from resuming if audio focus is - * denied) or modify (e.g. change the seek position to prevent a user from seeking past a - * non-skippable advert) operations. - */ +/** @deprecated Use a {@link ForwardingPlayer} or configure the player to customize operations. */ +@Deprecated public interface ControlDispatcher { /** @@ -55,7 +50,7 @@ public interface ControlDispatcher { boolean dispatchSeekTo(Player player, int windowIndex, long positionMs); /** - * Dispatches a {@link Player#previous()} operation. + * Dispatches a {@link Player#seekToPreviousWindow()} operation. * * @param player The {@link Player} to which the operation should be dispatched. * @return True if the operation was dispatched. False if suppressed. @@ -63,7 +58,7 @@ public interface ControlDispatcher { boolean dispatchPrevious(Player player); /** - * Dispatches a {@link Player#next()} operation. + * Dispatches a {@link Player#seekToNextWindow()} operation. * * @param player The {@link Player} to which the operation should be dispatched. * @return True if the operation was dispatched. False if suppressed. diff --git a/library/common/src/main/java/com/google/android/exoplayer2/DefaultControlDispatcher.java b/library/common/src/main/java/com/google/android/exoplayer2/DefaultControlDispatcher.java index 03f03d5903a..b20daebefb0 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/DefaultControlDispatcher.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/DefaultControlDispatcher.java @@ -18,24 +18,19 @@ import static java.lang.Math.max; import static java.lang.Math.min; -/** Default {@link ControlDispatcher}. */ +/** @deprecated Use a {@link ForwardingPlayer} or configure the player to customize operations. */ +@Deprecated public class DefaultControlDispatcher implements ControlDispatcher { - /** The default fast forward increment, in milliseconds. */ - public static final int DEFAULT_FAST_FORWARD_MS = 15_000; - /** The default rewind increment, in milliseconds. */ - public static final int DEFAULT_REWIND_MS = 5000; - - private static final int MAX_POSITION_FOR_SEEK_TO_PREVIOUS = 3000; - - private final Timeline.Window window; - - private long rewindIncrementMs; - private long fastForwardIncrementMs; + private final long rewindIncrementMs; + private final long fastForwardIncrementMs; + private final boolean rewindAndFastForwardIncrementsSet; /** Creates an instance. */ public DefaultControlDispatcher() { - this(DEFAULT_FAST_FORWARD_MS, DEFAULT_REWIND_MS); + fastForwardIncrementMs = C.TIME_UNSET; + rewindIncrementMs = C.TIME_UNSET; + rewindAndFastForwardIncrementsSet = false; } /** @@ -49,7 +44,7 @@ public DefaultControlDispatcher() { public DefaultControlDispatcher(long fastForwardIncrementMs, long rewindIncrementMs) { this.fastForwardIncrementMs = fastForwardIncrementMs; this.rewindIncrementMs = rewindIncrementMs; - window = new Timeline.Window(); + rewindAndFastForwardIncrementsSet = true; } @Override @@ -72,44 +67,21 @@ public boolean dispatchSeekTo(Player player, int windowIndex, long positionMs) { @Override public boolean dispatchPrevious(Player player) { - Timeline timeline = player.getCurrentTimeline(); - if (timeline.isEmpty() || player.isPlayingAd()) { - return true; - } - int windowIndex = player.getCurrentWindowIndex(); - timeline.getWindow(windowIndex, window); - int previousWindowIndex = player.getPreviousWindowIndex(); - boolean isUnseekableLiveStream = window.isLive() && !window.isSeekable; - if (previousWindowIndex != C.INDEX_UNSET - && (player.getCurrentPosition() <= MAX_POSITION_FOR_SEEK_TO_PREVIOUS - || isUnseekableLiveStream)) { - player.seekTo(previousWindowIndex, C.TIME_UNSET); - } else if (!isUnseekableLiveStream) { - player.seekTo(windowIndex, /* positionMs= */ 0); - } + player.seekToPrevious(); return true; } @Override public boolean dispatchNext(Player player) { - Timeline timeline = player.getCurrentTimeline(); - if (timeline.isEmpty() || player.isPlayingAd()) { - return true; - } - int windowIndex = player.getCurrentWindowIndex(); - timeline.getWindow(windowIndex, window); - int nextWindowIndex = player.getNextWindowIndex(); - if (nextWindowIndex != C.INDEX_UNSET) { - player.seekTo(nextWindowIndex, C.TIME_UNSET); - } else if (window.isLive() && window.isDynamic) { - player.seekTo(windowIndex, C.TIME_UNSET); - } + player.seekToNext(); return true; } @Override public boolean dispatchRewind(Player player) { - if (isRewindEnabled() && player.isCurrentWindowSeekable()) { + if (!rewindAndFastForwardIncrementsSet) { + player.seekBack(); + } else if (isRewindEnabled() && player.isCurrentWindowSeekable()) { seekToOffset(player, -rewindIncrementMs); } return true; @@ -117,7 +89,9 @@ public boolean dispatchRewind(Player player) { @Override public boolean dispatchFastForward(Player player) { - if (isFastForwardEnabled() && player.isCurrentWindowSeekable()) { + if (!rewindAndFastForwardIncrementsSet) { + player.seekForward(); + } else if (isFastForwardEnabled() && player.isCurrentWindowSeekable()) { seekToOffset(player, fastForwardIncrementMs); } return true; @@ -150,40 +124,24 @@ public boolean dispatchSetPlaybackParameters( @Override public boolean isRewindEnabled() { - return rewindIncrementMs > 0; + return !rewindAndFastForwardIncrementsSet || rewindIncrementMs > 0; } @Override public boolean isFastForwardEnabled() { - return fastForwardIncrementMs > 0; + return !rewindAndFastForwardIncrementsSet || fastForwardIncrementMs > 0; } /** Returns the rewind increment in milliseconds. */ - public long getRewindIncrementMs() { - return rewindIncrementMs; + public long getRewindIncrementMs(Player player) { + return rewindAndFastForwardIncrementsSet ? rewindIncrementMs : player.getSeekBackIncrement(); } /** Returns the fast forward increment in milliseconds. */ - public long getFastForwardIncrementMs() { - return fastForwardIncrementMs; - } - - /** - * @deprecated Create a new instance instead and pass the new instance to the UI component. This - * makes sure the UI gets updated and is in sync with the new values. - */ - @Deprecated - public void setRewindIncrementMs(long rewindMs) { - this.rewindIncrementMs = rewindMs; - } - - /** - * @deprecated Create a new instance instead and pass the new instance to the UI component. This - * makes sure the UI gets updated and is in sync with the new values. - */ - @Deprecated - public void setFastForwardIncrementMs(long fastForwardMs) { - this.fastForwardIncrementMs = fastForwardMs; + public long getFastForwardIncrementMs(Player player) { + return rewindAndFastForwardIncrementsSet + ? fastForwardIncrementMs + : player.getSeekForwardIncrement(); } // Internal methods. @@ -195,6 +153,6 @@ private static void seekToOffset(Player player, long offsetMs) { positionMs = min(positionMs, durationMs); } positionMs = max(positionMs, 0); - player.seekTo(player.getCurrentWindowIndex(), positionMs); + player.seekTo(positionMs); } } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java b/library/common/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java index 68bb899a738..198ec238178 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java @@ -21,18 +21,16 @@ /** Information about the ExoPlayer library. */ public final class ExoPlayerLibraryInfo { - /** - * A tag to use when logging library information. - */ + /** A tag to use when logging library information. */ public static final String TAG = "ExoPlayer"; /** The version of the library expressed as a string, for example "1.2.3". */ // Intentionally hardcoded. Do not derive from other constants (e.g. VERSION_INT) or vice versa. - public static final String VERSION = "2.14.2"; + public static final String VERSION = "2.15.0"; /** The version of the library expressed as {@code "ExoPlayerLib/" + VERSION}. */ // Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa. - public static final String VERSION_SLASHY = "ExoPlayerLib/2.14.2"; + public static final String VERSION_SLASHY = "ExoPlayerLib/2.15.0"; /** * The version of the library expressed as an integer, for example 1002003. @@ -42,7 +40,7 @@ public final class ExoPlayerLibraryInfo { * integer version 123045006 (123-045-006). */ // Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa. - public static final int VERSION_INT = 2014002; + public static final int VERSION_INT = 2015000; /** * The default user agent for requests made by the library. @@ -73,9 +71,7 @@ public final class ExoPlayerLibraryInfo { private ExoPlayerLibraryInfo() {} // Prevents instantiation. - /** - * Returns a string consisting of registered module names separated by ", ". - */ + /** Returns a string consisting of registered module names separated by ", ". */ public static synchronized String registeredModules() { return registeredModulesString; } @@ -90,5 +86,4 @@ public static synchronized void registerModule(String name) { registeredModulesString = registeredModulesString + ", " + name; } } - } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/Format.java b/library/common/src/main/java/com/google/android/exoplayer2/Format.java index d4eb5e13d2f..eba199299ea 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/Format.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/Format.java @@ -43,7 +43,7 @@ * format being constructed. For information about different types of format, see ExoPlayer's Supported formats page. * - *

      Fields commonly relevant to all formats

      + *

      Fields commonly relevant to all formats

      * *
        *
      • {@link #id} @@ -57,7 +57,7 @@ *
      • {@link #metadata} *
      * - *

      Fields relevant to container formats

      + *

      Fields relevant to container formats

      * *
        *
      • {@link #containerMimeType} @@ -70,7 +70,7 @@ * href="#audio-formats">audio and text formats. *
      * - *

      Fields relevant to sample formats

      + *

      Fields relevant to sample formats

      * *
        *
      • {@link #sampleMimeType} @@ -83,7 +83,7 @@ * href="#text-formats">text formats. *
      * - *

      Fields relevant to video formats

      + *

      Fields relevant to video formats

      * *
        *
      • {@link #width} @@ -96,7 +96,7 @@ *
      • {@link #colorInfo} *
      * - *

      Fields relevant to audio formats

      + *

      Fields relevant to audio formats

      * *
        *
      • {@link #channelCount} @@ -106,7 +106,7 @@ *
      • {@link #encoderPadding} *
      * - *

      Fields relevant to text formats

      + *

      Fields relevant to text formats

      * *
        *
      • {@link #accessibilityChannel} @@ -686,8 +686,8 @@ public Format build() { */ public final int maxInputSize; /** - * Initialization data that must be provided to the decoder. Will not be null, but may be empty - * if initialization data is not required. + * Initialization data that must be provided to the decoder. Will not be null, but may be empty if + * initialization data is not required. */ public final List initializationData; /** DRM initialization data if the stream is protected, or null otherwise. */ @@ -702,17 +702,11 @@ public Format build() { // Video specific. - /** - * The width of the video in pixels, or {@link #NO_VALUE} if unknown or not applicable. - */ + /** The width of the video in pixels, or {@link #NO_VALUE} if unknown or not applicable. */ public final int width; - /** - * The height of the video in pixels, or {@link #NO_VALUE} if unknown or not applicable. - */ + /** The height of the video in pixels, or {@link #NO_VALUE} if unknown or not applicable. */ public final int height; - /** - * The frame rate in frames per second, or {@link #NO_VALUE} if unknown or not applicable. - */ + /** The frame rate in frames per second, or {@link #NO_VALUE} if unknown or not applicable. */ public final float frameRate; /** * The clockwise rotation that should be applied to the video for it to be rendered in the correct @@ -734,13 +728,9 @@ public Format build() { // Audio specific. - /** - * The number of audio channels, or {@link #NO_VALUE} if unknown or not applicable. - */ + /** The number of audio channels, or {@link #NO_VALUE} if unknown or not applicable. */ public final int channelCount; - /** - * The audio sampling rate in Hz, or {@link #NO_VALUE} if unknown or not applicable. - */ + /** The audio sampling rate in Hz, or {@link #NO_VALUE} if unknown or not applicable. */ public final int sampleRate; /** The {@link C.PcmEncoding} for PCM audio. Set to {@link #NO_VALUE} for other media types. */ @C.PcmEncoding public final int pcmEncoding; @@ -773,40 +763,6 @@ public Format build() { // Video. - /** @deprecated Use {@link Format.Builder}. */ - @Deprecated - public static Format createVideoContainerFormat( - @Nullable String id, - @Nullable String label, - @Nullable String containerMimeType, - @Nullable String sampleMimeType, - @Nullable String codecs, - @Nullable Metadata metadata, - int bitrate, - int width, - int height, - float frameRate, - @Nullable List initializationData, - @C.SelectionFlags int selectionFlags, - @C.RoleFlags int roleFlags) { - return new Builder() - .setId(id) - .setLabel(label) - .setSelectionFlags(selectionFlags) - .setRoleFlags(roleFlags) - .setAverageBitrate(bitrate) - .setPeakBitrate(bitrate) - .setCodecs(codecs) - .setMetadata(metadata) - .setContainerMimeType(containerMimeType) - .setSampleMimeType(sampleMimeType) - .setInitializationData(initializationData) - .setWidth(width) - .setHeight(height) - .setFrameRate(frameRate) - .build(); - } - /** @deprecated Use {@link Format.Builder}. */ @Deprecated public static Format createVideoSampleFormat( @@ -867,80 +823,8 @@ public static Format createVideoSampleFormat( .build(); } - /** @deprecated Use {@link Format.Builder}. */ - @Deprecated - public static Format createVideoSampleFormat( - @Nullable String id, - @Nullable String sampleMimeType, - @Nullable String codecs, - int bitrate, - int maxInputSize, - int width, - int height, - float frameRate, - @Nullable List initializationData, - int rotationDegrees, - float pixelWidthHeightRatio, - @Nullable byte[] projectionData, - @C.StereoMode int stereoMode, - @Nullable ColorInfo colorInfo, - @Nullable DrmInitData drmInitData) { - return new Builder() - .setId(id) - .setAverageBitrate(bitrate) - .setPeakBitrate(bitrate) - .setCodecs(codecs) - .setSampleMimeType(sampleMimeType) - .setMaxInputSize(maxInputSize) - .setInitializationData(initializationData) - .setDrmInitData(drmInitData) - .setWidth(width) - .setHeight(height) - .setFrameRate(frameRate) - .setRotationDegrees(rotationDegrees) - .setPixelWidthHeightRatio(pixelWidthHeightRatio) - .setProjectionData(projectionData) - .setStereoMode(stereoMode) - .setColorInfo(colorInfo) - .build(); - } - // Audio. - /** @deprecated Use {@link Format.Builder}. */ - @Deprecated - public static Format createAudioContainerFormat( - @Nullable String id, - @Nullable String label, - @Nullable String containerMimeType, - @Nullable String sampleMimeType, - @Nullable String codecs, - @Nullable Metadata metadata, - int bitrate, - int channelCount, - int sampleRate, - @Nullable List initializationData, - @C.SelectionFlags int selectionFlags, - @C.RoleFlags int roleFlags, - @Nullable String language) { - return new Builder() - .setId(id) - .setLabel(label) - .setLanguage(language) - .setSelectionFlags(selectionFlags) - .setRoleFlags(roleFlags) - .setAverageBitrate(bitrate) - .setPeakBitrate(bitrate) - .setCodecs(codecs) - .setMetadata(metadata) - .setContainerMimeType(containerMimeType) - .setSampleMimeType(sampleMimeType) - .setInitializationData(initializationData) - .setChannelCount(channelCount) - .setSampleRate(sampleRate) - .build(); - } - /** @deprecated Use {@link Format.Builder}. */ @Deprecated public static Format createAudioSampleFormat( @@ -1003,155 +887,6 @@ public static Format createAudioSampleFormat( .build(); } - /** @deprecated Use {@link Format.Builder}. */ - @Deprecated - public static Format createAudioSampleFormat( - @Nullable String id, - @Nullable String sampleMimeType, - @Nullable String codecs, - int bitrate, - int maxInputSize, - int channelCount, - int sampleRate, - @C.PcmEncoding int pcmEncoding, - int encoderDelay, - int encoderPadding, - @Nullable List initializationData, - @Nullable DrmInitData drmInitData, - @C.SelectionFlags int selectionFlags, - @Nullable String language, - @Nullable Metadata metadata) { - return new Builder() - .setId(id) - .setLanguage(language) - .setSelectionFlags(selectionFlags) - .setAverageBitrate(bitrate) - .setPeakBitrate(bitrate) - .setCodecs(codecs) - .setMetadata(metadata) - .setSampleMimeType(sampleMimeType) - .setMaxInputSize(maxInputSize) - .setInitializationData(initializationData) - .setDrmInitData(drmInitData) - .setChannelCount(channelCount) - .setSampleRate(sampleRate) - .setPcmEncoding(pcmEncoding) - .setEncoderDelay(encoderDelay) - .setEncoderPadding(encoderPadding) - .build(); - } - - // Text. - - /** @deprecated Use {@link Format.Builder}. */ - @Deprecated - public static Format createTextContainerFormat( - @Nullable String id, - @Nullable String label, - @Nullable String containerMimeType, - @Nullable String sampleMimeType, - @Nullable String codecs, - int bitrate, - @C.SelectionFlags int selectionFlags, - @C.RoleFlags int roleFlags, - @Nullable String language) { - return new Builder() - .setId(id) - .setLabel(label) - .setLanguage(language) - .setSelectionFlags(selectionFlags) - .setRoleFlags(roleFlags) - .setAverageBitrate(bitrate) - .setPeakBitrate(bitrate) - .setCodecs(codecs) - .setContainerMimeType(containerMimeType) - .setSampleMimeType(sampleMimeType) - .build(); - } - - /** @deprecated Use {@link Format.Builder}. */ - @Deprecated - public static Format createTextContainerFormat( - @Nullable String id, - @Nullable String label, - @Nullable String containerMimeType, - @Nullable String sampleMimeType, - @Nullable String codecs, - int bitrate, - @C.SelectionFlags int selectionFlags, - @C.RoleFlags int roleFlags, - @Nullable String language, - int accessibilityChannel) { - return new Builder() - .setId(id) - .setLabel(label) - .setLanguage(language) - .setSelectionFlags(selectionFlags) - .setRoleFlags(roleFlags) - .setAverageBitrate(bitrate) - .setPeakBitrate(bitrate) - .setCodecs(codecs) - .setContainerMimeType(containerMimeType) - .setSampleMimeType(sampleMimeType) - .setAccessibilityChannel(accessibilityChannel) - .build(); - } - - /** @deprecated Use {@link Format.Builder}. */ - @Deprecated - public static Format createTextSampleFormat( - @Nullable String id, - @Nullable String sampleMimeType, - @C.SelectionFlags int selectionFlags, - @Nullable String language) { - return new Builder() - .setId(id) - .setLanguage(language) - .setSelectionFlags(selectionFlags) - .setSampleMimeType(sampleMimeType) - .build(); - } - - /** @deprecated Use {@link Format.Builder}. */ - @Deprecated - public static Format createTextSampleFormat( - @Nullable String id, - @Nullable String sampleMimeType, - @C.SelectionFlags int selectionFlags, - @Nullable String language, - int accessibilityChannel, - long subsampleOffsetUs, - @Nullable List initializationData) { - return new Builder() - .setId(id) - .setLanguage(language) - .setSelectionFlags(selectionFlags) - .setSampleMimeType(sampleMimeType) - .setInitializationData(initializationData) - .setSubsampleOffsetUs(subsampleOffsetUs) - .setAccessibilityChannel(accessibilityChannel) - .build(); - } - - // Image. - - /** @deprecated Use {@link Format.Builder}. */ - @Deprecated - public static Format createImageSampleFormat( - @Nullable String id, - @Nullable String sampleMimeType, - @C.SelectionFlags int selectionFlags, - @Nullable List initializationData, - @Nullable String language) { - return new Builder() - .setId(id) - .setLanguage(language) - .setSelectionFlags(selectionFlags) - .setSampleMimeType(sampleMimeType) - .setInitializationData(initializationData) - .build(); - } - // Generic. /** @deprecated Use {@link Format.Builder}. */ @@ -1688,17 +1423,17 @@ public void writeToParcel(Parcel dest, int flags) { dest.writeInt(accessibilityChannel); } - public static final Creator CREATOR = new Creator() { - - @Override - public Format createFromParcel(Parcel in) { - return new Format(in); - } + public static final Creator CREATOR = + new Creator() { - @Override - public Format[] newArray(int size) { - return new Format[size]; - } + @Override + public Format createFromParcel(Parcel in) { + return new Format(in); + } - }; + @Override + public Format[] newArray(int size) { + return new Format[size]; + } + }; } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/ForwardingPlayer.java b/library/common/src/main/java/com/google/android/exoplayer2/ForwardingPlayer.java new file mode 100644 index 00000000000..7112efa8a28 --- /dev/null +++ b/library/common/src/main/java/com/google/android/exoplayer2/ForwardingPlayer.java @@ -0,0 +1,873 @@ +/* + * 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 com.google.android.exoplayer2; + +import android.os.Looper; +import android.view.Surface; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.TextureView; +import androidx.annotation.Nullable; +import com.google.android.exoplayer2.audio.AudioAttributes; +import com.google.android.exoplayer2.device.DeviceInfo; +import com.google.android.exoplayer2.metadata.Metadata; +import com.google.android.exoplayer2.source.TrackGroupArray; +import com.google.android.exoplayer2.text.Cue; +import com.google.android.exoplayer2.trackselection.TrackSelectionArray; +import com.google.android.exoplayer2.video.VideoSize; +import java.util.List; + +/** + * A {@link Player} that forwards operations to another {@link Player}. Applications can use this + * class to suppress or modify specific operations, by overriding the respective methods. + */ +public class ForwardingPlayer implements Player { + + private final Player player; + + /** Creates a new instance that forwards all operations to {@code player}. */ + public ForwardingPlayer(Player player) { + this.player = player; + } + + @Override + public Looper getApplicationLooper() { + return player.getApplicationLooper(); + } + + @Override + @SuppressWarnings("deprecation") // Implementing deprecated method. + public void addListener(EventListener listener) { + player.addListener(new ForwardingEventListener(this, listener)); + } + + @Override + public void addListener(Listener listener) { + player.addListener(new ForwardingListener(this, listener)); + } + + @Override + @SuppressWarnings("deprecation") // Implementing deprecated method. + public void removeListener(EventListener listener) { + player.removeListener(new ForwardingEventListener(this, listener)); + } + + @Override + public void removeListener(Listener listener) { + player.removeListener(new ForwardingListener(this, listener)); + } + + @Override + public void setMediaItems(List mediaItems) { + player.setMediaItems(mediaItems); + } + + @Override + public void setMediaItems(List mediaItems, boolean resetPosition) { + player.setMediaItems(mediaItems, resetPosition); + } + + @Override + public void setMediaItems( + List mediaItems, int startWindowIndex, long startPositionMs) { + player.setMediaItems(mediaItems, startWindowIndex, startPositionMs); + } + + @Override + public void setMediaItem(MediaItem mediaItem) { + player.setMediaItem(mediaItem); + } + + @Override + public void setMediaItem(MediaItem mediaItem, long startPositionMs) { + player.setMediaItem(mediaItem, startPositionMs); + } + + @Override + public void setMediaItem(MediaItem mediaItem, boolean resetPosition) { + player.setMediaItem(mediaItem, resetPosition); + } + + @Override + public void addMediaItem(MediaItem mediaItem) { + player.addMediaItem(mediaItem); + } + + @Override + public void addMediaItem(int index, MediaItem mediaItem) { + player.addMediaItem(index, mediaItem); + } + + @Override + public void addMediaItems(List mediaItems) { + player.addMediaItems(mediaItems); + } + + @Override + public void addMediaItems(int index, List mediaItems) { + player.addMediaItems(index, mediaItems); + } + + @Override + public void moveMediaItem(int currentIndex, int newIndex) { + player.moveMediaItem(currentIndex, newIndex); + } + + @Override + public void moveMediaItems(int fromIndex, int toIndex, int newIndex) { + player.moveMediaItems(fromIndex, toIndex, newIndex); + } + + @Override + public void removeMediaItem(int index) { + player.removeMediaItem(index); + } + + @Override + public void removeMediaItems(int fromIndex, int toIndex) { + player.removeMediaItems(fromIndex, toIndex); + } + + @Override + public void clearMediaItems() { + player.clearMediaItems(); + } + + @Override + public boolean isCommandAvailable(@Command int command) { + return player.isCommandAvailable(command); + } + + @Override + public Commands getAvailableCommands() { + return player.getAvailableCommands(); + } + + @Override + public void prepare() { + player.prepare(); + } + + @Override + public int getPlaybackState() { + return player.getPlaybackState(); + } + + @Override + public int getPlaybackSuppressionReason() { + return player.getPlaybackSuppressionReason(); + } + + @Override + public boolean isPlaying() { + return player.isPlaying(); + } + + @Nullable + @Override + public PlaybackException getPlayerError() { + return player.getPlayerError(); + } + + @Override + public void play() { + player.play(); + } + + @Override + public void pause() { + player.pause(); + } + + @Override + public void setPlayWhenReady(boolean playWhenReady) { + player.setPlayWhenReady(playWhenReady); + } + + @Override + public boolean getPlayWhenReady() { + return player.getPlayWhenReady(); + } + + @Override + public void setRepeatMode(@RepeatMode int repeatMode) { + player.setRepeatMode(repeatMode); + } + + @Override + public int getRepeatMode() { + return player.getRepeatMode(); + } + + @Override + public void setShuffleModeEnabled(boolean shuffleModeEnabled) { + player.setShuffleModeEnabled(shuffleModeEnabled); + } + + @Override + public boolean getShuffleModeEnabled() { + return player.getShuffleModeEnabled(); + } + + @Override + public boolean isLoading() { + return player.isLoading(); + } + + @Override + public void seekToDefaultPosition() { + player.seekToDefaultPosition(); + } + + @Override + public void seekToDefaultPosition(int windowIndex) { + player.seekToDefaultPosition(windowIndex); + } + + @Override + public void seekTo(long positionMs) { + player.seekTo(positionMs); + } + + @Override + public void seekTo(int windowIndex, long positionMs) { + player.seekTo(windowIndex, positionMs); + } + + @Override + public long getSeekBackIncrement() { + return player.getSeekBackIncrement(); + } + + @Override + public void seekBack() { + player.seekBack(); + } + + @Override + public long getSeekForwardIncrement() { + return player.getSeekForwardIncrement(); + } + + @Override + public void seekForward() { + player.seekForward(); + } + + @Deprecated + @Override + public boolean hasPrevious() { + return player.hasPrevious(); + } + + @Override + public boolean hasPreviousWindow() { + return player.hasPreviousWindow(); + } + + @Deprecated + @Override + public void previous() { + player.previous(); + } + + @Override + public void seekToPreviousWindow() { + player.seekToPreviousWindow(); + } + + @Override + public void seekToPrevious() { + player.seekToPrevious(); + } + + @Override + public int getMaxSeekToPreviousPosition() { + return player.getMaxSeekToPreviousPosition(); + } + + @Deprecated + @Override + public boolean hasNext() { + return player.hasNext(); + } + + @Override + public boolean hasNextWindow() { + return player.hasNextWindow(); + } + + @Deprecated + @Override + public void next() { + player.next(); + } + + @Override + public void seekToNextWindow() { + player.seekToNextWindow(); + } + + @Override + public void seekToNext() { + player.seekToNext(); + } + + @Override + public void setPlaybackParameters(PlaybackParameters playbackParameters) { + player.setPlaybackParameters(playbackParameters); + } + + @Override + public void setPlaybackSpeed(float speed) { + player.setPlaybackSpeed(speed); + } + + @Override + public PlaybackParameters getPlaybackParameters() { + return player.getPlaybackParameters(); + } + + @Override + public void stop() { + player.stop(); + } + + @Override + @SuppressWarnings("deprecation") // Forwarding to deprecated method. + public void stop(boolean reset) { + player.stop(reset); + } + + @Override + public void release() { + player.release(); + } + + @Override + public TrackGroupArray getCurrentTrackGroups() { + return player.getCurrentTrackGroups(); + } + + @Override + public TrackSelectionArray getCurrentTrackSelections() { + return player.getCurrentTrackSelections(); + } + + @Deprecated + @Override + public List getCurrentStaticMetadata() { + return player.getCurrentStaticMetadata(); + } + + @Override + public MediaMetadata getMediaMetadata() { + return player.getMediaMetadata(); + } + + @Override + public MediaMetadata getPlaylistMetadata() { + return player.getPlaylistMetadata(); + } + + @Override + public void setPlaylistMetadata(MediaMetadata mediaMetadata) { + player.setPlaylistMetadata(mediaMetadata); + } + + @Nullable + @Override + public Object getCurrentManifest() { + return player.getCurrentManifest(); + } + + @Override + public Timeline getCurrentTimeline() { + return player.getCurrentTimeline(); + } + + @Override + public int getCurrentPeriodIndex() { + return player.getCurrentPeriodIndex(); + } + + @Override + public int getCurrentWindowIndex() { + return player.getCurrentWindowIndex(); + } + + @Override + public int getNextWindowIndex() { + return player.getNextWindowIndex(); + } + + @Override + public int getPreviousWindowIndex() { + return player.getPreviousWindowIndex(); + } + + @Nullable + @Override + public MediaItem getCurrentMediaItem() { + return player.getCurrentMediaItem(); + } + + @Override + public int getMediaItemCount() { + return player.getMediaItemCount(); + } + + @Override + public MediaItem getMediaItemAt(int index) { + return player.getMediaItemAt(index); + } + + @Override + public long getDuration() { + return player.getDuration(); + } + + @Override + public long getCurrentPosition() { + return player.getCurrentPosition(); + } + + @Override + public long getBufferedPosition() { + return player.getBufferedPosition(); + } + + @Override + public int getBufferedPercentage() { + return player.getBufferedPercentage(); + } + + @Override + public long getTotalBufferedDuration() { + return player.getTotalBufferedDuration(); + } + + @Override + public boolean isCurrentWindowDynamic() { + return player.isCurrentWindowDynamic(); + } + + @Override + public boolean isCurrentWindowLive() { + return player.isCurrentWindowLive(); + } + + @Override + public long getCurrentLiveOffset() { + return player.getCurrentLiveOffset(); + } + + @Override + public boolean isCurrentWindowSeekable() { + return player.isCurrentWindowSeekable(); + } + + @Override + public boolean isPlayingAd() { + return player.isPlayingAd(); + } + + @Override + public int getCurrentAdGroupIndex() { + return player.getCurrentAdGroupIndex(); + } + + @Override + public int getCurrentAdIndexInAdGroup() { + return player.getCurrentAdIndexInAdGroup(); + } + + @Override + public long getContentDuration() { + return player.getContentDuration(); + } + + @Override + public long getContentPosition() { + return player.getContentPosition(); + } + + @Override + public long getContentBufferedPosition() { + return player.getContentBufferedPosition(); + } + + @Override + public AudioAttributes getAudioAttributes() { + return player.getAudioAttributes(); + } + + @Override + public void setVolume(float audioVolume) { + player.setVolume(audioVolume); + } + + @Override + public float getVolume() { + return player.getVolume(); + } + + @Override + public VideoSize getVideoSize() { + return player.getVideoSize(); + } + + @Override + public void clearVideoSurface() { + player.clearVideoSurface(); + } + + @Override + public void clearVideoSurface(@Nullable Surface surface) { + player.clearVideoSurface(surface); + } + + @Override + public void setVideoSurface(@Nullable Surface surface) { + player.setVideoSurface(surface); + } + + @Override + public void setVideoSurfaceHolder(@Nullable SurfaceHolder surfaceHolder) { + player.setVideoSurfaceHolder(surfaceHolder); + } + + @Override + public void clearVideoSurfaceHolder(@Nullable SurfaceHolder surfaceHolder) { + player.clearVideoSurfaceHolder(surfaceHolder); + } + + @Override + public void setVideoSurfaceView(@Nullable SurfaceView surfaceView) { + player.setVideoSurfaceView(surfaceView); + } + + @Override + public void clearVideoSurfaceView(@Nullable SurfaceView surfaceView) { + player.clearVideoSurfaceView(surfaceView); + } + + @Override + public void setVideoTextureView(@Nullable TextureView textureView) { + player.setVideoTextureView(textureView); + } + + @Override + public void clearVideoTextureView(@Nullable TextureView textureView) { + player.clearVideoTextureView(textureView); + } + + @Override + public List getCurrentCues() { + return player.getCurrentCues(); + } + + @Override + public DeviceInfo getDeviceInfo() { + return player.getDeviceInfo(); + } + + @Override + public int getDeviceVolume() { + return player.getDeviceVolume(); + } + + @Override + public boolean isDeviceMuted() { + return player.isDeviceMuted(); + } + + @Override + public void setDeviceVolume(int volume) { + player.setDeviceVolume(volume); + } + + @Override + public void increaseDeviceVolume() { + player.increaseDeviceVolume(); + } + + @Override + public void decreaseDeviceVolume() { + player.decreaseDeviceVolume(); + } + + @Override + public void setDeviceMuted(boolean muted) { + player.setDeviceMuted(muted); + } + + @SuppressWarnings("deprecation") // Use of deprecated type for backwards compatibility. + private static class ForwardingEventListener implements EventListener { + + private final ForwardingPlayer forwardingPlayer; + private final EventListener eventListener; + + private ForwardingEventListener( + ForwardingPlayer forwardingPlayer, EventListener eventListener) { + this.forwardingPlayer = forwardingPlayer; + this.eventListener = eventListener; + } + + @Override + public void onTimelineChanged(Timeline timeline, @TimelineChangeReason int reason) { + eventListener.onTimelineChanged(timeline, reason); + } + + @Override + public void onMediaItemTransition( + @Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) { + eventListener.onMediaItemTransition(mediaItem, reason); + } + + @Override + public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) { + eventListener.onTracksChanged(trackGroups, trackSelections); + } + + @Deprecated + @Override + public void onStaticMetadataChanged(List metadataList) { + eventListener.onStaticMetadataChanged(metadataList); + } + + @Override + public void onMediaMetadataChanged(MediaMetadata mediaMetadata) { + eventListener.onMediaMetadataChanged(mediaMetadata); + } + + @Override + public void onPlaylistMetadataChanged(MediaMetadata mediaMetadata) { + eventListener.onPlaylistMetadataChanged(mediaMetadata); + } + + @Override + public void onIsLoadingChanged(boolean isLoading) { + eventListener.onIsLoadingChanged(isLoading); + } + + @Override + public void onLoadingChanged(boolean isLoading) { + eventListener.onIsLoadingChanged(isLoading); + } + + @Override + public void onAvailableCommandsChanged(Commands availableCommands) { + eventListener.onAvailableCommandsChanged(availableCommands); + } + + @Override + public void onPlayerStateChanged(boolean playWhenReady, @State int playbackState) { + eventListener.onPlayerStateChanged(playWhenReady, playbackState); + } + + @Override + public void onPlaybackStateChanged(@State int playbackState) { + eventListener.onPlaybackStateChanged(playbackState); + } + + @Override + public void onPlayWhenReadyChanged( + boolean playWhenReady, @PlayWhenReadyChangeReason int reason) { + eventListener.onPlayWhenReadyChanged(playWhenReady, reason); + } + + @Override + public void onPlaybackSuppressionReasonChanged( + @PlayWhenReadyChangeReason int playbackSuppressionReason) { + eventListener.onPlaybackSuppressionReasonChanged(playbackSuppressionReason); + } + + @Override + public void onIsPlayingChanged(boolean isPlaying) { + eventListener.onIsPlayingChanged(isPlaying); + } + + @Override + public void onRepeatModeChanged(@RepeatMode int repeatMode) { + eventListener.onRepeatModeChanged(repeatMode); + } + + @Override + public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) { + eventListener.onShuffleModeEnabledChanged(shuffleModeEnabled); + } + + @Override + public void onPlayerError(PlaybackException error) { + eventListener.onPlayerError(error); + } + + @Override + public void onPlayerErrorChanged(@Nullable PlaybackException error) { + eventListener.onPlayerErrorChanged(error); + } + + @Override + public void onPositionDiscontinuity(@DiscontinuityReason int reason) { + eventListener.onPositionDiscontinuity(reason); + } + + @Override + public void onPositionDiscontinuity( + PositionInfo oldPosition, PositionInfo newPosition, @DiscontinuityReason int reason) { + eventListener.onPositionDiscontinuity(oldPosition, newPosition, reason); + } + + @Override + public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) { + eventListener.onPlaybackParametersChanged(playbackParameters); + } + + @Override + public void onSeekBackIncrementChanged(long seekBackIncrementMs) { + eventListener.onSeekBackIncrementChanged(seekBackIncrementMs); + } + + @Override + public void onSeekForwardIncrementChanged(long seekForwardIncrementMs) { + eventListener.onSeekForwardIncrementChanged(seekForwardIncrementMs); + } + + @Override + public void onMaxSeekToPreviousPositionChanged(int maxSeekToPreviousPositionMs) { + eventListener.onMaxSeekToPreviousPositionChanged(maxSeekToPreviousPositionMs); + } + + @Override + public void onSeekProcessed() { + eventListener.onSeekProcessed(); + } + + @Override + public void onEvents(Player player, Events events) { + // Replace player with forwarding player. + eventListener.onEvents(forwardingPlayer, events); + } + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) { + return true; + } + if (!(o instanceof ForwardingEventListener)) { + return false; + } + + ForwardingEventListener that = (ForwardingEventListener) o; + + if (!forwardingPlayer.equals(that.forwardingPlayer)) { + return false; + } + return eventListener.equals(that.eventListener); + } + + @Override + public int hashCode() { + int result = forwardingPlayer.hashCode(); + result = 31 * result + eventListener.hashCode(); + return result; + } + } + + private static final class ForwardingListener extends ForwardingEventListener + implements Listener { + + private final Listener listener; + + public ForwardingListener(ForwardingPlayer forwardingPlayer, Listener listener) { + super(forwardingPlayer, listener); + this.listener = listener; + } + + // VideoListener methods. + + @Override + public void onVideoSizeChanged(VideoSize videoSize) { + listener.onVideoSizeChanged(videoSize); + } + + @Override + @SuppressWarnings("deprecation") // Forwarding to deprecated method. + public void onVideoSizeChanged( + int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) { + listener.onVideoSizeChanged(width, height, unappliedRotationDegrees, pixelWidthHeightRatio); + } + + @Override + public void onSurfaceSizeChanged(int width, int height) { + listener.onSurfaceSizeChanged(width, height); + } + + @Override + public void onRenderedFirstFrame() { + listener.onRenderedFirstFrame(); + } + + // AudioListener methods + + @Override + public void onAudioSessionIdChanged(int audioSessionId) { + listener.onAudioSessionIdChanged(audioSessionId); + } + + @Override + public void onAudioAttributesChanged(AudioAttributes audioAttributes) { + listener.onAudioAttributesChanged(audioAttributes); + } + + @Override + public void onVolumeChanged(float volume) { + listener.onVolumeChanged(volume); + } + + @Override + public void onSkipSilenceEnabledChanged(boolean skipSilenceEnabled) { + listener.onSkipSilenceEnabledChanged(skipSilenceEnabled); + } + + // TextOutput methods. + + @Override + public void onCues(List cues) { + listener.onCues(cues); + } + + // MetadataOutput methods. + + @Override + public void onMetadata(Metadata metadata) { + listener.onMetadata(metadata); + } + + // DeviceListener callbacks + + @Override + public void onDeviceInfoChanged(DeviceInfo deviceInfo) { + listener.onDeviceInfoChanged(deviceInfo); + } + + @Override + public void onDeviceVolumeChanged(int volume, boolean muted) { + listener.onDeviceVolumeChanged(volume, muted); + } + } +} diff --git a/library/common/src/main/java/com/google/android/exoplayer2/IllegalSeekPositionException.java b/library/common/src/main/java/com/google/android/exoplayer2/IllegalSeekPositionException.java index 745e86983f1..71f57dec829 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/IllegalSeekPositionException.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/IllegalSeekPositionException.java @@ -21,17 +21,11 @@ */ public final class IllegalSeekPositionException extends IllegalStateException { - /** - * The {@link Timeline} in which the seek was attempted. - */ + /** The {@link Timeline} in which the seek was attempted. */ public final Timeline timeline; - /** - * The index of the window being seeked to. - */ + /** The index of the window being seeked to. */ public final int windowIndex; - /** - * The seek position in the specified window. - */ + /** The seek position in the specified window. */ public final long positionMs; /** @@ -44,5 +38,4 @@ public IllegalSeekPositionException(Timeline timeline, int windowIndex, long pos this.windowIndex = windowIndex; this.positionMs = positionMs; } - } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/MediaItem.java b/library/common/src/main/java/com/google/android/exoplayer2/MediaItem.java index bb92bc779ec..e8373532a1e 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/MediaItem.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/MediaItem.java @@ -565,9 +565,7 @@ public Builder setMediaMetadata(MediaMetadata mediaMetadata) { return this; } - /** - * Returns a new {@link MediaItem} instance with the current builder values. - */ + /** Returns a new {@link MediaItem} instance with the current builder values. */ public MediaItem build() { checkState(drmLicenseUri == null || drmUuid != null); @Nullable PlaybackProperties playbackProperties = null; @@ -1205,6 +1203,9 @@ private static String keyForField(@ClippingProperties.FieldNumber int field) { */ public static final String DEFAULT_MEDIA_ID = ""; + /** Empty {@link MediaItem}. */ + public static final MediaItem EMPTY = new MediaItem.Builder().build(); + /** Identifies the media item. */ public final String mediaId; diff --git a/library/common/src/main/java/com/google/android/exoplayer2/MediaMetadata.java b/library/common/src/main/java/com/google/android/exoplayer2/MediaMetadata.java index b299b86e525..e76edee1737 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/MediaMetadata.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/MediaMetadata.java @@ -18,6 +18,7 @@ import android.net.Uri; import android.os.Bundle; import androidx.annotation.IntDef; +import androidx.annotation.IntRange; import androidx.annotation.Nullable; import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.util.Util; @@ -48,12 +49,25 @@ public static final class Builder { @Nullable private Rating userRating; @Nullable private Rating overallRating; @Nullable private byte[] artworkData; + @Nullable @PictureType private Integer artworkDataType; @Nullable private Uri artworkUri; @Nullable private Integer trackNumber; @Nullable private Integer totalTrackCount; @Nullable @FolderType private Integer folderType; @Nullable private Boolean isPlayable; - @Nullable private Integer year; + @Nullable private Integer recordingYear; + @Nullable private Integer recordingMonth; + @Nullable private Integer recordingDay; + @Nullable private Integer releaseYear; + @Nullable private Integer releaseMonth; + @Nullable private Integer releaseDay; + @Nullable private CharSequence writer; + @Nullable private CharSequence composer; + @Nullable private CharSequence conductor; + @Nullable private Integer discNumber; + @Nullable private Integer totalDiscCount; + @Nullable private CharSequence genre; + @Nullable private CharSequence compilation; @Nullable private Bundle extras; public Builder() {} @@ -70,12 +84,25 @@ private Builder(MediaMetadata mediaMetadata) { this.userRating = mediaMetadata.userRating; this.overallRating = mediaMetadata.overallRating; this.artworkData = mediaMetadata.artworkData; + this.artworkDataType = mediaMetadata.artworkDataType; this.artworkUri = mediaMetadata.artworkUri; this.trackNumber = mediaMetadata.trackNumber; this.totalTrackCount = mediaMetadata.totalTrackCount; this.folderType = mediaMetadata.folderType; this.isPlayable = mediaMetadata.isPlayable; - this.year = mediaMetadata.year; + this.recordingYear = mediaMetadata.recordingYear; + this.recordingMonth = mediaMetadata.recordingMonth; + this.recordingDay = mediaMetadata.recordingDay; + this.releaseYear = mediaMetadata.releaseYear; + this.releaseMonth = mediaMetadata.releaseMonth; + this.releaseDay = mediaMetadata.releaseDay; + this.writer = mediaMetadata.writer; + this.composer = mediaMetadata.composer; + this.conductor = mediaMetadata.conductor; + this.discNumber = mediaMetadata.discNumber; + this.totalDiscCount = mediaMetadata.totalDiscCount; + this.genre = mediaMetadata.genre; + this.compilation = mediaMetadata.compilation; this.extras = mediaMetadata.extras; } @@ -143,9 +170,41 @@ public Builder setOverallRating(@Nullable Rating overallRating) { return this; } - /** Sets the artwork data as a compressed byte array. */ + /** + * @deprecated Use {@link #setArtworkData(byte[] data, Integer pictureType)} or {@link + * #maybeSetArtworkData(byte[] data, int pictureType)}, providing a {@link PictureType}. + */ + @Deprecated public Builder setArtworkData(@Nullable byte[] artworkData) { + return setArtworkData(artworkData, /* artworkDataType= */ null); + } + + /** + * Sets the artwork data as a compressed byte array with an associated {@link PictureType + * artworkDataType}. + */ + public Builder setArtworkData( + @Nullable byte[] artworkData, @Nullable @PictureType Integer artworkDataType) { this.artworkData = artworkData == null ? null : artworkData.clone(); + this.artworkDataType = artworkDataType; + return this; + } + + /** + * Sets the artwork data as a compressed byte array in the event that the associated {@link + * PictureType} is {@link #PICTURE_TYPE_FRONT_COVER}, the existing {@link PictureType} is not + * {@link #PICTURE_TYPE_FRONT_COVER}, or the current artworkData is not set. + * + *

        Use {@link #setArtworkData(byte[], Integer)} to set the artwork data without checking the + * {@link PictureType}. + */ + public Builder maybeSetArtworkData(byte[] artworkData, @PictureType int artworkDataType) { + if (this.artworkData == null + || Util.areEqual(artworkDataType, PICTURE_TYPE_FRONT_COVER) + || !Util.areEqual(this.artworkDataType, PICTURE_TYPE_FRONT_COVER)) { + this.artworkData = artworkData.clone(); + this.artworkDataType = artworkDataType; + } return this; } @@ -179,9 +238,104 @@ public Builder setIsPlayable(@Nullable Boolean isPlayable) { return this; } - /** Sets the year. */ + /** @deprecated Use {@link #setRecordingYear(Integer)} instead. */ + @Deprecated public Builder setYear(@Nullable Integer year) { - this.year = year; + return setRecordingYear(year); + } + + /** Sets the year of the recording date. */ + public Builder setRecordingYear(@Nullable Integer recordingYear) { + this.recordingYear = recordingYear; + return this; + } + + /** + * Sets the month of the recording date. + * + *

        Value should be between 1 and 12. + */ + public Builder setRecordingMonth( + @Nullable @IntRange(from = 1, to = 12) Integer recordingMonth) { + this.recordingMonth = recordingMonth; + return this; + } + + /** + * Sets the day of the recording date. + * + *

        Value should be between 1 and 31. + */ + public Builder setRecordingDay(@Nullable @IntRange(from = 1, to = 31) Integer recordingDay) { + this.recordingDay = recordingDay; + return this; + } + + /** Sets the year of the release date. */ + public Builder setReleaseYear(@Nullable Integer releaseYear) { + this.releaseYear = releaseYear; + return this; + } + + /** + * Sets the month of the release date. + * + *

        Value should be between 1 and 12. + */ + public Builder setReleaseMonth(@Nullable @IntRange(from = 1, to = 12) Integer releaseMonth) { + this.releaseMonth = releaseMonth; + return this; + } + + /** + * Sets the day of the release date. + * + *

        Value should be between 1 and 31. + */ + public Builder setReleaseDay(@Nullable @IntRange(from = 1, to = 31) Integer releaseDay) { + this.releaseDay = releaseDay; + return this; + } + + /** Sets the writer. */ + public Builder setWriter(@Nullable CharSequence writer) { + this.writer = writer; + return this; + } + + /** Sets the composer. */ + public Builder setComposer(@Nullable CharSequence composer) { + this.composer = composer; + return this; + } + + /** Sets the conductor. */ + public Builder setConductor(@Nullable CharSequence conductor) { + this.conductor = conductor; + return this; + } + + /** Sets the disc number. */ + public Builder setDiscNumber(@Nullable Integer discNumber) { + this.discNumber = discNumber; + return this; + } + + /** Sets the total number of discs. */ + public Builder setTotalDiscCount(@Nullable Integer totalDiscCount) { + this.totalDiscCount = totalDiscCount; + return this; + } + + /** Sets the genre. */ + public Builder setGenre(@Nullable CharSequence genre) { + this.genre = genre; + return this; + } + + /** Sets the compilation. */ + public Builder setCompilation(@Nullable CharSequence compilation) { + this.compilation = compilation; return this; } @@ -245,6 +399,7 @@ public MediaMetadata build() { @Documented @Retention(RetentionPolicy.SOURCE) @IntDef({ + FOLDER_TYPE_NONE, FOLDER_TYPE_MIXED, FOLDER_TYPE_TITLES, FOLDER_TYPE_ALBUMS, @@ -255,6 +410,8 @@ public MediaMetadata build() { }) public @interface FolderType {} + /** Type for an item that is not a folder. */ + public static final int FOLDER_TYPE_NONE = -1; /** Type for a folder containing media of mixed types. */ public static final int FOLDER_TYPE_MIXED = 0; /** Type for a folder containing only playable media. */ @@ -270,6 +427,61 @@ public MediaMetadata build() { /** Type for a folder containing media categorized by year. */ public static final int FOLDER_TYPE_YEARS = 6; + /** + * The picture type of the artwork. + * + *

        Values sourced from the ID3 v2.4 specification (See section 4.14 of + * https://id3.org/id3v2.4.0-frames). + */ + @Documented + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + PICTURE_TYPE_OTHER, + PICTURE_TYPE_FILE_ICON, + PICTURE_TYPE_FILE_ICON_OTHER, + PICTURE_TYPE_FRONT_COVER, + PICTURE_TYPE_BACK_COVER, + PICTURE_TYPE_LEAFLET_PAGE, + PICTURE_TYPE_MEDIA, + PICTURE_TYPE_LEAD_ARTIST_PERFORMER, + PICTURE_TYPE_ARTIST_PERFORMER, + PICTURE_TYPE_CONDUCTOR, + PICTURE_TYPE_BAND_ORCHESTRA, + PICTURE_TYPE_COMPOSER, + PICTURE_TYPE_LYRICIST, + PICTURE_TYPE_RECORDING_LOCATION, + PICTURE_TYPE_DURING_RECORDING, + PICTURE_TYPE_DURING_PERFORMANCE, + PICTURE_TYPE_MOVIE_VIDEO_SCREEN_CAPTURE, + PICTURE_TYPE_A_BRIGHT_COLORED_FISH, + PICTURE_TYPE_ILLUSTRATION, + PICTURE_TYPE_BAND_ARTIST_LOGO, + PICTURE_TYPE_PUBLISHER_STUDIO_LOGO + }) + public @interface PictureType {} + + public static final int PICTURE_TYPE_OTHER = 0x00; + public static final int PICTURE_TYPE_FILE_ICON = 0x01; + public static final int PICTURE_TYPE_FILE_ICON_OTHER = 0x02; + public static final int PICTURE_TYPE_FRONT_COVER = 0x03; + public static final int PICTURE_TYPE_BACK_COVER = 0x04; + public static final int PICTURE_TYPE_LEAFLET_PAGE = 0x05; + public static final int PICTURE_TYPE_MEDIA = 0x06; + public static final int PICTURE_TYPE_LEAD_ARTIST_PERFORMER = 0x07; + public static final int PICTURE_TYPE_ARTIST_PERFORMER = 0x08; + public static final int PICTURE_TYPE_CONDUCTOR = 0x09; + public static final int PICTURE_TYPE_BAND_ORCHESTRA = 0x0A; + public static final int PICTURE_TYPE_COMPOSER = 0x0B; + public static final int PICTURE_TYPE_LYRICIST = 0x0C; + public static final int PICTURE_TYPE_RECORDING_LOCATION = 0x0D; + public static final int PICTURE_TYPE_DURING_RECORDING = 0x0E; + public static final int PICTURE_TYPE_DURING_PERFORMANCE = 0x0F; + public static final int PICTURE_TYPE_MOVIE_VIDEO_SCREEN_CAPTURE = 0x10; + public static final int PICTURE_TYPE_A_BRIGHT_COLORED_FISH = 0x11; + public static final int PICTURE_TYPE_ILLUSTRATION = 0x12; + public static final int PICTURE_TYPE_BAND_ARTIST_LOGO = 0x13; + public static final int PICTURE_TYPE_PUBLISHER_STUDIO_LOGO = 0x14; + /** Empty {@link MediaMetadata}. */ public static final MediaMetadata EMPTY = new MediaMetadata.Builder().build(); @@ -299,6 +511,8 @@ public MediaMetadata build() { @Nullable public final Rating overallRating; /** Optional artwork data as a compressed byte array. */ @Nullable public final byte[] artworkData; + /** Optional {@link PictureType} of the artwork data. */ + @Nullable @PictureType public final Integer artworkDataType; /** Optional artwork {@link Uri}. */ @Nullable public final Uri artworkUri; /** Optional track number. */ @@ -309,8 +523,52 @@ public MediaMetadata build() { @Nullable @FolderType public final Integer folderType; /** Optional boolean for media playability. */ @Nullable public final Boolean isPlayable; - /** Optional year. */ - @Nullable public final Integer year; + /** @deprecated Use {@link #recordingYear} instead. */ + @Deprecated @Nullable public final Integer year; + /** Optional year of the recording date. */ + @Nullable public final Integer recordingYear; + /** + * Optional month of the recording date. + * + *

        Note that there is no guarantee that the month and day are a valid combination. + */ + @Nullable public final Integer recordingMonth; + /** + * Optional day of the recording date. + * + *

        Note that there is no guarantee that the month and day are a valid combination. + */ + @Nullable public final Integer recordingDay; + + /** Optional year of the release date. */ + @Nullable public final Integer releaseYear; + /** + * Optional month of the release date. + * + *

        Note that there is no guarantee that the month and day are a valid combination. + */ + @Nullable public final Integer releaseMonth; + /** + * Optional day of the release date. + * + *

        Note that there is no guarantee that the month and day are a valid combination. + */ + @Nullable public final Integer releaseDay; + /** Optional writer. */ + @Nullable public final CharSequence writer; + /** Optional composer. */ + @Nullable public final CharSequence composer; + /** Optional conductor. */ + @Nullable public final CharSequence conductor; + /** Optional disc number. */ + @Nullable public final Integer discNumber; + /** Optional total number of discs. */ + @Nullable public final Integer totalDiscCount; + /** Optional genre. */ + @Nullable public final CharSequence genre; + /** Optional compilation. */ + @Nullable public final CharSequence compilation; + /** * Optional extras {@link Bundle}. * @@ -331,12 +589,26 @@ private MediaMetadata(Builder builder) { this.userRating = builder.userRating; this.overallRating = builder.overallRating; this.artworkData = builder.artworkData; + this.artworkDataType = builder.artworkDataType; this.artworkUri = builder.artworkUri; this.trackNumber = builder.trackNumber; this.totalTrackCount = builder.totalTrackCount; this.folderType = builder.folderType; this.isPlayable = builder.isPlayable; - this.year = builder.year; + this.year = builder.recordingYear; + this.recordingYear = builder.recordingYear; + this.recordingMonth = builder.recordingMonth; + this.recordingDay = builder.recordingDay; + this.releaseYear = builder.releaseYear; + this.releaseMonth = builder.releaseMonth; + this.releaseDay = builder.releaseDay; + this.writer = builder.writer; + this.composer = builder.composer; + this.conductor = builder.conductor; + this.discNumber = builder.discNumber; + this.totalDiscCount = builder.totalDiscCount; + this.genre = builder.genre; + this.compilation = builder.compilation; this.extras = builder.extras; } @@ -365,12 +637,25 @@ public boolean equals(@Nullable Object obj) { && Util.areEqual(userRating, that.userRating) && Util.areEqual(overallRating, that.overallRating) && Arrays.equals(artworkData, that.artworkData) + && Util.areEqual(artworkDataType, that.artworkDataType) && Util.areEqual(artworkUri, that.artworkUri) && Util.areEqual(trackNumber, that.trackNumber) && Util.areEqual(totalTrackCount, that.totalTrackCount) && Util.areEqual(folderType, that.folderType) && Util.areEqual(isPlayable, that.isPlayable) - && Util.areEqual(year, that.year); + && Util.areEqual(recordingYear, that.recordingYear) + && Util.areEqual(recordingMonth, that.recordingMonth) + && Util.areEqual(recordingDay, that.recordingDay) + && Util.areEqual(releaseYear, that.releaseYear) + && Util.areEqual(releaseMonth, that.releaseMonth) + && Util.areEqual(releaseDay, that.releaseDay) + && Util.areEqual(writer, that.writer) + && Util.areEqual(composer, that.composer) + && Util.areEqual(conductor, that.conductor) + && Util.areEqual(discNumber, that.discNumber) + && Util.areEqual(totalDiscCount, that.totalDiscCount) + && Util.areEqual(genre, that.genre) + && Util.areEqual(compilation, that.compilation); } @Override @@ -387,12 +672,25 @@ public int hashCode() { userRating, overallRating, Arrays.hashCode(artworkData), + artworkDataType, artworkUri, trackNumber, totalTrackCount, folderType, isPlayable, - year); + recordingYear, + recordingMonth, + recordingDay, + releaseYear, + releaseMonth, + releaseDay, + writer, + composer, + conductor, + discNumber, + totalDiscCount, + genre, + compilation); } // Bundleable implementation. @@ -411,12 +709,25 @@ public int hashCode() { FIELD_USER_RATING, FIELD_OVERALL_RATING, FIELD_ARTWORK_DATA, + FIELD_ARTWORK_DATA_TYPE, FIELD_ARTWORK_URI, FIELD_TRACK_NUMBER, FIELD_TOTAL_TRACK_COUNT, FIELD_FOLDER_TYPE, FIELD_IS_PLAYABLE, - FIELD_YEAR, + FIELD_RECORDING_YEAR, + FIELD_RECORDING_MONTH, + FIELD_RECORDING_DAY, + FIELD_RELEASE_YEAR, + FIELD_RELEASE_MONTH, + FIELD_RELEASE_DAY, + FIELD_WRITER, + FIELD_COMPOSER, + FIELD_CONDUCTOR, + FIELD_DISC_NUMBER, + FIELD_TOTAL_DISC_COUNT, + FIELD_GENRE, + FIELD_COMPILATION, FIELD_EXTRAS }) private @interface FieldNumber {} @@ -437,7 +748,20 @@ public int hashCode() { private static final int FIELD_TOTAL_TRACK_COUNT = 13; private static final int FIELD_FOLDER_TYPE = 14; private static final int FIELD_IS_PLAYABLE = 15; - private static final int FIELD_YEAR = 16; + private static final int FIELD_RECORDING_YEAR = 16; + private static final int FIELD_RECORDING_MONTH = 17; + private static final int FIELD_RECORDING_DAY = 18; + private static final int FIELD_RELEASE_YEAR = 19; + private static final int FIELD_RELEASE_MONTH = 20; + private static final int FIELD_RELEASE_DAY = 21; + private static final int FIELD_WRITER = 22; + private static final int FIELD_COMPOSER = 23; + private static final int FIELD_CONDUCTOR = 24; + private static final int FIELD_DISC_NUMBER = 25; + private static final int FIELD_TOTAL_DISC_COUNT = 26; + private static final int FIELD_GENRE = 27; + private static final int FIELD_COMPILATION = 28; + private static final int FIELD_ARTWORK_DATA_TYPE = 29; private static final int FIELD_EXTRAS = 1000; @Override @@ -453,6 +777,11 @@ public Bundle toBundle() { bundle.putParcelable(keyForField(FIELD_MEDIA_URI), mediaUri); bundle.putByteArray(keyForField(FIELD_ARTWORK_DATA), artworkData); bundle.putParcelable(keyForField(FIELD_ARTWORK_URI), artworkUri); + bundle.putCharSequence(keyForField(FIELD_WRITER), writer); + bundle.putCharSequence(keyForField(FIELD_COMPOSER), composer); + bundle.putCharSequence(keyForField(FIELD_CONDUCTOR), conductor); + bundle.putCharSequence(keyForField(FIELD_GENRE), genre); + bundle.putCharSequence(keyForField(FIELD_COMPILATION), compilation); if (userRating != null) { bundle.putBundle(keyForField(FIELD_USER_RATING), userRating.toBundle()); @@ -472,8 +801,32 @@ public Bundle toBundle() { if (isPlayable != null) { bundle.putBoolean(keyForField(FIELD_IS_PLAYABLE), isPlayable); } - if (year != null) { - bundle.putInt(keyForField(FIELD_YEAR), year); + if (recordingYear != null) { + bundle.putInt(keyForField(FIELD_RECORDING_YEAR), recordingYear); + } + if (recordingMonth != null) { + bundle.putInt(keyForField(FIELD_RECORDING_MONTH), recordingMonth); + } + if (recordingDay != null) { + bundle.putInt(keyForField(FIELD_RECORDING_DAY), recordingDay); + } + if (releaseYear != null) { + bundle.putInt(keyForField(FIELD_RELEASE_YEAR), releaseYear); + } + if (releaseMonth != null) { + bundle.putInt(keyForField(FIELD_RELEASE_MONTH), releaseMonth); + } + if (releaseDay != null) { + bundle.putInt(keyForField(FIELD_RELEASE_DAY), releaseDay); + } + if (discNumber != null) { + bundle.putInt(keyForField(FIELD_DISC_NUMBER), discNumber); + } + if (totalDiscCount != null) { + bundle.putInt(keyForField(FIELD_TOTAL_DISC_COUNT), totalDiscCount); + } + if (artworkDataType != null) { + bundle.putInt(keyForField(FIELD_ARTWORK_DATA_TYPE), artworkDataType); } if (extras != null) { bundle.putBundle(keyForField(FIELD_EXTRAS), extras); @@ -495,8 +848,17 @@ private static MediaMetadata fromBundle(Bundle bundle) { .setSubtitle(bundle.getCharSequence(keyForField(FIELD_SUBTITLE))) .setDescription(bundle.getCharSequence(keyForField(FIELD_DESCRIPTION))) .setMediaUri(bundle.getParcelable(keyForField(FIELD_MEDIA_URI))) - .setArtworkData(bundle.getByteArray(keyForField(FIELD_ARTWORK_DATA))) + .setArtworkData( + bundle.getByteArray(keyForField(FIELD_ARTWORK_DATA)), + bundle.containsKey(keyForField(FIELD_ARTWORK_DATA_TYPE)) + ? bundle.getInt(keyForField(FIELD_ARTWORK_DATA_TYPE)) + : null) .setArtworkUri(bundle.getParcelable(keyForField(FIELD_ARTWORK_URI))) + .setWriter(bundle.getCharSequence(keyForField(FIELD_WRITER))) + .setComposer(bundle.getCharSequence(keyForField(FIELD_COMPOSER))) + .setConductor(bundle.getCharSequence(keyForField(FIELD_CONDUCTOR))) + .setGenre(bundle.getCharSequence(keyForField(FIELD_GENRE))) + .setCompilation(bundle.getCharSequence(keyForField(FIELD_COMPILATION))) .setExtras(bundle.getBundle(keyForField(FIELD_EXTRAS))); if (bundle.containsKey(keyForField(FIELD_USER_RATING))) { @@ -523,8 +885,29 @@ private static MediaMetadata fromBundle(Bundle bundle) { if (bundle.containsKey(keyForField(FIELD_IS_PLAYABLE))) { builder.setIsPlayable(bundle.getBoolean(keyForField(FIELD_IS_PLAYABLE))); } - if (bundle.containsKey(keyForField(FIELD_YEAR))) { - builder.setYear(bundle.getInt(keyForField(FIELD_YEAR))); + if (bundle.containsKey(keyForField(FIELD_RECORDING_YEAR))) { + builder.setRecordingYear(bundle.getInt(keyForField(FIELD_RECORDING_YEAR))); + } + if (bundle.containsKey(keyForField(FIELD_RECORDING_MONTH))) { + builder.setRecordingMonth(bundle.getInt(keyForField(FIELD_RECORDING_MONTH))); + } + if (bundle.containsKey(keyForField(FIELD_RECORDING_DAY))) { + builder.setRecordingDay(bundle.getInt(keyForField(FIELD_RECORDING_DAY))); + } + if (bundle.containsKey(keyForField(FIELD_RELEASE_YEAR))) { + builder.setReleaseYear(bundle.getInt(keyForField(FIELD_RELEASE_YEAR))); + } + if (bundle.containsKey(keyForField(FIELD_RELEASE_MONTH))) { + builder.setReleaseMonth(bundle.getInt(keyForField(FIELD_RELEASE_MONTH))); + } + if (bundle.containsKey(keyForField(FIELD_RELEASE_DAY))) { + builder.setReleaseDay(bundle.getInt(keyForField(FIELD_RELEASE_DAY))); + } + if (bundle.containsKey(keyForField(FIELD_DISC_NUMBER))) { + builder.setDiscNumber(bundle.getInt(keyForField(FIELD_DISC_NUMBER))); + } + if (bundle.containsKey(keyForField(FIELD_TOTAL_DISC_COUNT))) { + builder.setTotalDiscCount(bundle.getInt(keyForField(FIELD_TOTAL_DISC_COUNT))); } return builder.build(); diff --git a/library/common/src/main/java/com/google/android/exoplayer2/ParserException.java b/library/common/src/main/java/com/google/android/exoplayer2/ParserException.java index 716eceda941..1e6c3a88f2f 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/ParserException.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/ParserException.java @@ -15,35 +15,94 @@ */ package com.google.android.exoplayer2; +import androidx.annotation.Nullable; +import com.google.android.exoplayer2.C.DataType; import java.io.IOException; /** Thrown when an error occurs parsing media data and metadata. */ public class ParserException extends IOException { - public ParserException() { - super(); + /** + * Creates a new instance for which {@link #contentIsMalformed} is true and {@link #dataType} is + * {@link C#DATA_TYPE_UNKNOWN}. + * + * @param message See {@link #getMessage()}. + * @param cause See {@link #getCause()}. + * @return The created instance. + */ + public static ParserException createForMalformedDataOfUnknownType( + @Nullable String message, @Nullable Throwable cause) { + return new ParserException(message, cause, /* contentIsMalformed= */ true, C.DATA_TYPE_UNKNOWN); } /** - * @param message The detail message for the exception. + * Creates a new instance for which {@link #contentIsMalformed} is true and {@link #dataType} is + * {@link C#DATA_TYPE_MEDIA}. + * + * @param message See {@link #getMessage()}. + * @param cause See {@link #getCause()}. + * @return The created instance. */ - public ParserException(String message) { - super(message); + public static ParserException createForMalformedContainer( + @Nullable String message, @Nullable Throwable cause) { + return new ParserException(message, cause, /* contentIsMalformed= */ true, C.DATA_TYPE_MEDIA); } /** - * @param cause The cause for the exception. + * Creates a new instance for which {@link #contentIsMalformed} is true and {@link #dataType} is + * {@link C#DATA_TYPE_MANIFEST}. + * + * @param message See {@link #getMessage()}. + * @param cause See {@link #getCause()}. + * @return The created instance. */ - public ParserException(Throwable cause) { - super(cause); + public static ParserException createForMalformedManifest( + @Nullable String message, @Nullable Throwable cause) { + return new ParserException( + message, cause, /* contentIsMalformed= */ true, C.DATA_TYPE_MANIFEST); } /** - * @param message The detail message for the exception. - * @param cause The cause for the exception. + * Creates a new instance for which {@link #contentIsMalformed} is false and {@link #dataType} is + * {@link C#DATA_TYPE_MANIFEST}. + * + * @param message See {@link #getMessage()}. + * @param cause See {@link #getCause()}. + * @return The created instance. */ - public ParserException(String message, Throwable cause) { - super(message, cause); + public static ParserException createForManifestWithUnsupportedFeature( + @Nullable String message, @Nullable Throwable cause) { + return new ParserException( + message, cause, /* contentIsMalformed= */ false, C.DATA_TYPE_MANIFEST); + } + + /** + * Creates a new instance for which {@link #contentIsMalformed} is false and {@link #dataType} is + * {@link C#DATA_TYPE_MEDIA}. + * + * @param message See {@link #getMessage()}. + * @return The created instance. + */ + public static ParserException createForUnsupportedContainerFeature(@Nullable String message) { + return new ParserException( + message, /* cause= */ null, /* contentIsMalformed= */ false, C.DATA_TYPE_MEDIA); } + /** + * Whether the parsing error was caused by a bitstream not following the expected format. May be + * false when a parser encounters a legal condition which it does not support. + */ + public final boolean contentIsMalformed; + /** The {@link DataType data type} of the parsed bitstream. */ + public final int dataType; + + protected ParserException( + @Nullable String message, + @Nullable Throwable cause, + boolean contentIsMalformed, + @DataType int dataType) { + super(message, cause); + this.contentIsMalformed = contentIsMalformed; + this.dataType = dataType; + } } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/PlaybackException.java b/library/common/src/main/java/com/google/android/exoplayer2/PlaybackException.java new file mode 100644 index 00000000000..335dcf2612b --- /dev/null +++ b/library/common/src/main/java/com/google/android/exoplayer2/PlaybackException.java @@ -0,0 +1,491 @@ +/* + * 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 com.google.android.exoplayer2; + +import android.net.ConnectivityManager; +import android.os.Bundle; +import android.os.RemoteException; +import android.os.SystemClock; +import android.text.TextUtils; +import androidx.annotation.CallSuper; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; +import com.google.android.exoplayer2.util.Clock; +import com.google.android.exoplayer2.util.Util; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** Thrown when a non locally recoverable playback failure occurs. */ +public class PlaybackException extends Exception implements Bundleable { + + /** + * Codes that identify causes of player errors. + * + *

        This list of errors may be extended in future versions, and {@link Player} implementations + * may define custom error codes. + */ + @Documented + @Retention(RetentionPolicy.SOURCE) + @IntDef( + open = true, + value = { + ERROR_CODE_UNSPECIFIED, + ERROR_CODE_REMOTE_ERROR, + ERROR_CODE_BEHIND_LIVE_WINDOW, + ERROR_CODE_TIMEOUT, + ERROR_CODE_FAILED_RUNTIME_CHECK, + ERROR_CODE_IO_UNSPECIFIED, + ERROR_CODE_IO_NETWORK_CONNECTION_FAILED, + ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT, + ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE, + ERROR_CODE_IO_BAD_HTTP_STATUS, + ERROR_CODE_IO_FILE_NOT_FOUND, + ERROR_CODE_IO_NO_PERMISSION, + ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED, + ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE, + ERROR_CODE_PARSING_CONTAINER_MALFORMED, + ERROR_CODE_PARSING_MANIFEST_MALFORMED, + ERROR_CODE_PARSING_CONTAINER_UNSUPPORTED, + ERROR_CODE_PARSING_MANIFEST_UNSUPPORTED, + ERROR_CODE_DECODER_INIT_FAILED, + ERROR_CODE_DECODER_QUERY_FAILED, + ERROR_CODE_DECODING_FAILED, + ERROR_CODE_DECODING_FORMAT_EXCEEDS_CAPABILITIES, + ERROR_CODE_DECODING_FORMAT_UNSUPPORTED, + ERROR_CODE_AUDIO_TRACK_INIT_FAILED, + ERROR_CODE_AUDIO_TRACK_WRITE_FAILED, + ERROR_CODE_DRM_UNSPECIFIED, + ERROR_CODE_DRM_SCHEME_UNSUPPORTED, + ERROR_CODE_DRM_PROVISIONING_FAILED, + ERROR_CODE_DRM_CONTENT_ERROR, + ERROR_CODE_DRM_LICENSE_ACQUISITION_FAILED, + ERROR_CODE_DRM_DISALLOWED_OPERATION, + ERROR_CODE_DRM_SYSTEM_ERROR, + ERROR_CODE_DRM_DEVICE_REVOKED, + ERROR_CODE_DRM_LICENSE_EXPIRED + }) + public @interface ErrorCode {} + + // Miscellaneous errors (1xxx). + + /** Caused by an error whose cause could not be identified. */ + public static final int ERROR_CODE_UNSPECIFIED = 1000; + /** + * Caused by an unidentified error in a remote Player, which is a Player that runs on a different + * host or process. + */ + public static final int ERROR_CODE_REMOTE_ERROR = 1001; + /** Caused by the loading position falling behind the sliding window of available live content. */ + public static final int ERROR_CODE_BEHIND_LIVE_WINDOW = 1002; + /** Caused by a generic timeout. */ + public static final int ERROR_CODE_TIMEOUT = 1003; + /** + * Caused by a failed runtime check. + * + *

        This can happen when the application fails to comply with the player's API requirements (for + * example, by passing invalid arguments), or when the player reaches an invalid state. + */ + public static final int ERROR_CODE_FAILED_RUNTIME_CHECK = 1004; + + // Input/Output errors (2xxx). + + /** Caused by an Input/Output error which could not be identified. */ + public static final int ERROR_CODE_IO_UNSPECIFIED = 2000; + /** + * Caused by a network connection failure. + * + *

        The following is a non-exhaustive list of possible reasons: + * + *

          + *
        • There is no network connectivity (you can check this by querying {@link + * ConnectivityManager#getActiveNetwork}). + *
        • The URL's domain is misspelled or does not exist. + *
        • The target host is unreachable. + *
        • The server unexpectedly closes the connection. + *
        + */ + public static final int ERROR_CODE_IO_NETWORK_CONNECTION_FAILED = 2001; + /** Caused by a network timeout, meaning the server is taking too long to fulfill a request. */ + public static final int ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT = 2002; + /** + * Caused by a server returning a resource with an invalid "Content-Type" HTTP header value. + * + *

        For example, this can happen when the player is expecting a piece of media, but the server + * returns a paywall HTML page, with content type "text/html". + */ + public static final int ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE = 2003; + /** Caused by an HTTP server returning an unexpected HTTP response status code. */ + public static final int ERROR_CODE_IO_BAD_HTTP_STATUS = 2004; + /** Caused by a non-existent file. */ + public static final int ERROR_CODE_IO_FILE_NOT_FOUND = 2005; + /** + * Caused by lack of permission to perform an IO operation. For example, lack of permission to + * access internet or external storage. + */ + public static final int ERROR_CODE_IO_NO_PERMISSION = 2006; + /** + * Caused by the player trying to access cleartext HTTP traffic (meaning http:// rather than + * https://) when the app's Network Security Configuration does not permit it. + * + *

        See this corresponding + * troubleshooting topic. + */ + public static final int ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED = 2007; + /** Caused by reading data out of the data bound. */ + public static final int ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE = 2008; + + // Content parsing errors (3xxx). + + /** Caused by a parsing error associated with a media container format bitstream. */ + public static final int ERROR_CODE_PARSING_CONTAINER_MALFORMED = 3001; + /** + * Caused by a parsing error associated with a media manifest. Examples of a media manifest are a + * DASH or a SmoothStreaming manifest, or an HLS playlist. + */ + public static final int ERROR_CODE_PARSING_MANIFEST_MALFORMED = 3002; + /** + * Caused by attempting to extract a file with an unsupported media container format, or an + * unsupported media container feature. + */ + public static final int ERROR_CODE_PARSING_CONTAINER_UNSUPPORTED = 3003; + /** + * Caused by an unsupported feature in a media manifest. Examples of a media manifest are a DASH + * or a SmoothStreaming manifest, or an HLS playlist. + */ + public static final int ERROR_CODE_PARSING_MANIFEST_UNSUPPORTED = 3004; + + // Decoding errors (4xxx). + + /** Caused by a decoder initialization failure. */ + public static final int ERROR_CODE_DECODER_INIT_FAILED = 4001; + /** Caused by a decoder query failure. */ + public static final int ERROR_CODE_DECODER_QUERY_FAILED = 4002; + /** Caused by a failure while trying to decode media samples. */ + public static final int ERROR_CODE_DECODING_FAILED = 4003; + /** Caused by trying to decode content whose format exceeds the capabilities of the device. */ + public static final int ERROR_CODE_DECODING_FORMAT_EXCEEDS_CAPABILITIES = 4004; + /** Caused by trying to decode content whose format is not supported. */ + public static final int ERROR_CODE_DECODING_FORMAT_UNSUPPORTED = 4005; + + // AudioTrack errors (5xxx). + + /** Caused by an AudioTrack initialization failure. */ + public static final int ERROR_CODE_AUDIO_TRACK_INIT_FAILED = 5001; + /** Caused by an AudioTrack write operation failure. */ + public static final int ERROR_CODE_AUDIO_TRACK_WRITE_FAILED = 5002; + + // DRM errors (6xxx). + + /** Caused by an unspecified error related to DRM protection. */ + public static final int ERROR_CODE_DRM_UNSPECIFIED = 6000; + /** + * Caused by a chosen DRM protection scheme not being supported by the device. Examples of DRM + * protection schemes are ClearKey and Widevine. + */ + public static final int ERROR_CODE_DRM_SCHEME_UNSUPPORTED = 6001; + /** Caused by a failure while provisioning the device. */ + public static final int ERROR_CODE_DRM_PROVISIONING_FAILED = 6002; + /** + * Caused by attempting to play incompatible DRM-protected content. + * + *

        For example, this can happen when attempting to play a DRM protected stream using a scheme + * (like Widevine) for which there is no corresponding license acquisition data (like a pssh box). + */ + public static final int ERROR_CODE_DRM_CONTENT_ERROR = 6003; + /** Caused by a failure while trying to obtain a license. */ + public static final int ERROR_CODE_DRM_LICENSE_ACQUISITION_FAILED = 6004; + /** Caused by an operation being disallowed by a license policy. */ + public static final int ERROR_CODE_DRM_DISALLOWED_OPERATION = 6005; + /** Caused by an error in the DRM system. */ + public static final int ERROR_CODE_DRM_SYSTEM_ERROR = 6006; + /** Caused by the device having revoked DRM privileges. */ + public static final int ERROR_CODE_DRM_DEVICE_REVOKED = 6007; + /** Caused by an expired DRM license being loaded into an open DRM session. */ + public static final int ERROR_CODE_DRM_LICENSE_EXPIRED = 6008; + + /** + * Player implementations that want to surface custom errors can use error codes greater than this + * value, so as to avoid collision with other error codes defined in this class. + */ + public static final int CUSTOM_ERROR_CODE_BASE = 1000000; + + /** Returns the name of a given {@code errorCode}. */ + public static String getErrorCodeName(@ErrorCode int errorCode) { + switch (errorCode) { + case ERROR_CODE_UNSPECIFIED: + return "ERROR_CODE_UNSPECIFIED"; + case ERROR_CODE_REMOTE_ERROR: + return "ERROR_CODE_REMOTE_ERROR"; + case ERROR_CODE_BEHIND_LIVE_WINDOW: + return "ERROR_CODE_BEHIND_LIVE_WINDOW"; + case ERROR_CODE_TIMEOUT: + return "ERROR_CODE_TIMEOUT"; + case ERROR_CODE_FAILED_RUNTIME_CHECK: + return "ERROR_CODE_FAILED_RUNTIME_CHECK"; + case ERROR_CODE_IO_UNSPECIFIED: + return "ERROR_CODE_IO_UNSPECIFIED"; + case ERROR_CODE_IO_NETWORK_CONNECTION_FAILED: + return "ERROR_CODE_IO_NETWORK_CONNECTION_FAILED"; + case ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT: + return "ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT"; + case ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE: + return "ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE"; + case ERROR_CODE_IO_BAD_HTTP_STATUS: + return "ERROR_CODE_IO_BAD_HTTP_STATUS"; + case ERROR_CODE_IO_FILE_NOT_FOUND: + return "ERROR_CODE_IO_FILE_NOT_FOUND"; + case ERROR_CODE_IO_NO_PERMISSION: + return "ERROR_CODE_IO_NO_PERMISSION"; + case ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED: + return "ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED"; + case ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE: + return "ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE"; + case ERROR_CODE_PARSING_CONTAINER_MALFORMED: + return "ERROR_CODE_PARSING_CONTAINER_MALFORMED"; + case ERROR_CODE_PARSING_MANIFEST_MALFORMED: + return "ERROR_CODE_PARSING_MANIFEST_MALFORMED"; + case ERROR_CODE_PARSING_CONTAINER_UNSUPPORTED: + return "ERROR_CODE_PARSING_CONTAINER_UNSUPPORTED"; + case ERROR_CODE_PARSING_MANIFEST_UNSUPPORTED: + return "ERROR_CODE_PARSING_MANIFEST_UNSUPPORTED"; + case ERROR_CODE_DECODER_INIT_FAILED: + return "ERROR_CODE_DECODER_INIT_FAILED"; + case ERROR_CODE_DECODER_QUERY_FAILED: + return "ERROR_CODE_DECODER_QUERY_FAILED"; + case ERROR_CODE_DECODING_FAILED: + return "ERROR_CODE_DECODING_FAILED"; + case ERROR_CODE_DECODING_FORMAT_EXCEEDS_CAPABILITIES: + return "ERROR_CODE_DECODING_FORMAT_EXCEEDS_CAPABILITIES"; + case ERROR_CODE_DECODING_FORMAT_UNSUPPORTED: + return "ERROR_CODE_DECODING_FORMAT_UNSUPPORTED"; + case ERROR_CODE_AUDIO_TRACK_INIT_FAILED: + return "ERROR_CODE_AUDIO_TRACK_INIT_FAILED"; + case ERROR_CODE_AUDIO_TRACK_WRITE_FAILED: + return "ERROR_CODE_AUDIO_TRACK_WRITE_FAILED"; + case ERROR_CODE_DRM_UNSPECIFIED: + return "ERROR_CODE_DRM_UNSPECIFIED"; + case ERROR_CODE_DRM_SCHEME_UNSUPPORTED: + return "ERROR_CODE_DRM_SCHEME_UNSUPPORTED"; + case ERROR_CODE_DRM_PROVISIONING_FAILED: + return "ERROR_CODE_DRM_PROVISIONING_FAILED"; + case ERROR_CODE_DRM_CONTENT_ERROR: + return "ERROR_CODE_DRM_CONTENT_ERROR"; + case ERROR_CODE_DRM_LICENSE_ACQUISITION_FAILED: + return "ERROR_CODE_DRM_LICENSE_ACQUISITION_FAILED"; + case ERROR_CODE_DRM_DISALLOWED_OPERATION: + return "ERROR_CODE_DRM_DISALLOWED_OPERATION"; + case ERROR_CODE_DRM_SYSTEM_ERROR: + return "ERROR_CODE_DRM_SYSTEM_ERROR"; + case ERROR_CODE_DRM_DEVICE_REVOKED: + return "ERROR_CODE_DRM_DEVICE_REVOKED"; + case ERROR_CODE_DRM_LICENSE_EXPIRED: + return "ERROR_CODE_DRM_LICENSE_EXPIRED"; + default: + if (errorCode >= CUSTOM_ERROR_CODE_BASE) { + return "custom error code"; + } else { + return "invalid error code"; + } + } + } + + /** + * Equivalent to {@link PlaybackException#getErrorCodeName(int) + * PlaybackException.getErrorCodeName(this.errorCode)}. + */ + public final String getErrorCodeName() { + return getErrorCodeName(errorCode); + } + + /** An error code which identifies the cause of the playback failure. */ + @ErrorCode public final int errorCode; + + /** The value of {@link SystemClock#elapsedRealtime()} when this exception was created. */ + public final long timestampMs; + + /** + * Creates an instance. + * + * @param errorCode A number which identifies the cause of the error. May be one of the {@link + * ErrorCode ErrorCodes}. + * @param cause See {@link #getCause()}. + * @param message See {@link #getMessage()}. + */ + public PlaybackException( + @Nullable String message, @Nullable Throwable cause, @ErrorCode int errorCode) { + this(message, cause, errorCode, Clock.DEFAULT.elapsedRealtime()); + } + + /** Creates a new instance using the fields obtained from the given {@link Bundle}. */ + protected PlaybackException(Bundle bundle) { + this( + /* message= */ bundle.getString(keyForField(FIELD_STRING_MESSAGE)), + /* cause= */ getCauseFromBundle(bundle), + /* errorCode= */ bundle.getInt( + keyForField(FIELD_INT_ERROR_CODE), /* defaultValue= */ ERROR_CODE_UNSPECIFIED), + /* timestampMs= */ bundle.getLong( + keyForField(FIELD_LONG_TIMESTAMP_MS), + /* defaultValue= */ SystemClock.elapsedRealtime())); + } + + /** Creates a new instance using the given values. */ + protected PlaybackException( + @Nullable String message, + @Nullable Throwable cause, + @ErrorCode int errorCode, + long timestampMs) { + super(message, cause); + this.errorCode = errorCode; + this.timestampMs = timestampMs; + } + + /** + * Returns whether the error data associated to this exception equals the error data associated to + * {@code other}. + * + *

        Note that this method does not compare the exceptions' stacktraces. + */ + @CallSuper + public boolean errorInfoEquals(@Nullable PlaybackException other) { + if (this == other) { + return true; + } + if (other == null || getClass() != other.getClass()) { + return false; + } + + @Nullable Throwable thisCause = getCause(); + @Nullable Throwable thatCause = other.getCause(); + if (thisCause != null && thatCause != null) { + if (!Util.areEqual(thisCause.getMessage(), thatCause.getMessage())) { + return false; + } + if (!Util.areEqual(thisCause.getClass(), thatCause.getClass())) { + return false; + } + } else if (thisCause != null || thatCause != null) { + return false; + } + return errorCode == other.errorCode + && Util.areEqual(getMessage(), other.getMessage()) + && timestampMs == other.timestampMs; + } + + // Bundleable implementation. + + /** + * Identifiers for fields in a {@link Bundle} which represents a playback exception. Subclasses + * may use {@link #FIELD_CUSTOM_ID_BASE} to generate more keys using {@link #keyForField(int)}. + * + *

        Note: Changes to the Bundleable implementation must be backwards compatible, so as to avoid + * breaking communication across different Bundleable implementation versions. + */ + @Documented + @Retention(RetentionPolicy.SOURCE) + @IntDef( + open = true, + value = { + FIELD_INT_ERROR_CODE, + FIELD_LONG_TIMESTAMP_MS, + FIELD_STRING_MESSAGE, + FIELD_STRING_CAUSE_CLASS_NAME, + FIELD_STRING_CAUSE_MESSAGE, + }) + protected @interface FieldNumber {} + + private static final int FIELD_INT_ERROR_CODE = 0; + private static final int FIELD_LONG_TIMESTAMP_MS = 1; + private static final int FIELD_STRING_MESSAGE = 2; + private static final int FIELD_STRING_CAUSE_CLASS_NAME = 3; + private static final int FIELD_STRING_CAUSE_MESSAGE = 4; + + /** + * Defines a minimum field id value for subclasses to use when implementing {@link #toBundle()} + * and {@link Bundleable.Creator}. + * + *

        Subclasses should obtain their {@link Bundle Bundle's} field keys by applying a non-negative + * offset on this constant and passing the result to {@link #keyForField(int)}. + */ + protected static final int FIELD_CUSTOM_ID_BASE = 1000; + + /** Object that can create a {@link PlaybackException} from a {@link Bundle}. */ + @SuppressWarnings("unchecked") + public static final Creator CREATOR = PlaybackException::new; + + @CallSuper + @Override + public Bundle toBundle() { + Bundle bundle = new Bundle(); + bundle.putInt(keyForField(FIELD_INT_ERROR_CODE), errorCode); + bundle.putLong(keyForField(FIELD_LONG_TIMESTAMP_MS), timestampMs); + bundle.putString(keyForField(FIELD_STRING_MESSAGE), getMessage()); + @Nullable Throwable cause = getCause(); + if (cause != null) { + bundle.putString(keyForField(FIELD_STRING_CAUSE_CLASS_NAME), cause.getClass().getName()); + bundle.putString(keyForField(FIELD_STRING_CAUSE_MESSAGE), cause.getMessage()); + } + return bundle; + } + + /** + * Converts the given {@link FieldNumber} to a string which can be used as a field key when + * implementing {@link #toBundle()} and {@link Bundleable.Creator}. + */ + protected static String keyForField(@FieldNumber int field) { + return Integer.toString(field, Character.MAX_RADIX); + } + + // Creates a new {@link Throwable} with possibly {@code null} message. + @SuppressWarnings("nullness:argument") + private static Throwable createThrowable(Class clazz, @Nullable String message) + throws Exception { + return (Throwable) clazz.getConstructor(String.class).newInstance(message); + } + + // Creates a new {@link RemoteException} with possibly {@code null} message. + @SuppressWarnings("nullness:argument") + private static RemoteException createRemoteException(@Nullable String message) { + return new RemoteException(message); + } + + @Nullable + private static Throwable getCauseFromBundle(Bundle bundle) { + @Nullable String causeClassName = bundle.getString(keyForField(FIELD_STRING_CAUSE_CLASS_NAME)); + @Nullable String causeMessage = bundle.getString(keyForField(FIELD_STRING_CAUSE_MESSAGE)); + @Nullable Throwable cause = null; + if (!TextUtils.isEmpty(causeClassName)) { + try { + Class clazz = + Class.forName( + causeClassName, /* initialize= */ true, PlaybackException.class.getClassLoader()); + if (Throwable.class.isAssignableFrom(clazz)) { + cause = createThrowable(clazz, causeMessage); + } + } catch (Throwable e) { + // There was an error while creating the cause using reflection, do nothing here and let the + // finally block handle the issue. + } finally { + if (cause == null) { + // The bundle has fields to represent the cause, but we were unable to re-create the + // exception using reflection. We instantiate a RemoteException to reflect this problem. + cause = createRemoteException(causeMessage); + } + } + } + return cause; + } +} diff --git a/library/common/src/main/java/com/google/android/exoplayer2/PlaybackPreparer.java b/library/common/src/main/java/com/google/android/exoplayer2/PlaybackPreparer.java deleted file mode 100644 index 3ef38c8520a..00000000000 --- a/library/common/src/main/java/com/google/android/exoplayer2/PlaybackPreparer.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.android.exoplayer2; - -/** @deprecated Use {@link ControlDispatcher} instead. */ -@Deprecated -public interface PlaybackPreparer { - - /** @deprecated Use {@link ControlDispatcher#dispatchPrepare(Player)} instead. */ - @Deprecated - void preparePlayback(); -} diff --git a/library/common/src/main/java/com/google/android/exoplayer2/Player.java b/library/common/src/main/java/com/google/android/exoplayer2/Player.java index 0bb973d4efd..dfa80d40b49 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/Player.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/Player.java @@ -32,8 +32,9 @@ import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.text.Cue; import com.google.android.exoplayer2.text.TextOutput; +import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelectionArray; -import com.google.android.exoplayer2.util.ExoFlags; +import com.google.android.exoplayer2.util.FlagSet; import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.video.VideoListener; import com.google.android.exoplayer2.video.VideoSize; @@ -41,6 +42,7 @@ import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; import java.util.List; /** @@ -95,15 +97,6 @@ interface EventListener { */ default void onTimelineChanged(Timeline timeline, @TimelineChangeReason int reason) {} - /** - * @deprecated Use {@link #onTimelineChanged(Timeline, int)} instead. The manifest can be - * accessed by using {@link #getCurrentManifest()} or {@code timeline.getWindow(windowIndex, - * window).manifest} for a given window index. - */ - @Deprecated - default void onTimelineChanged( - Timeline timeline, @Nullable Object manifest, @TimelineChangeReason int reason) {} - /** * Called when playback transitions to a media item or starts repeating a media item according * to the current {@link #getRepeatMode() repeat mode}. @@ -136,30 +129,20 @@ default void onTracksChanged( TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {} /** - * Called when the static metadata changes. - * - *

        The provided {@code metadataList} is an immutable list of {@link Metadata} instances, - * where the elements correspond to the {@link #getCurrentTrackSelections() current track - * selections}, or an empty list if there are no track selections or the selected tracks contain - * no static metadata. - * - *

        The metadata is considered static in the sense that it comes from the tracks' declared - * Formats, rather than being timed (or dynamic) metadata, which is represented within a - * metadata track. - * - *

        {@link #onEvents(Player, Events)} will also be called to report this event along with - * other events that happen in the same {@link Looper} message queue iteration. - * - * @param metadataList The static metadata. + * @deprecated Use {@link Player#getMediaMetadata()} and {@link + * #onMediaMetadataChanged(MediaMetadata)} for access to structured metadata, or access the + * raw static metadata directly from the {@link TrackSelection#getFormat(int) track + * selections' formats}. */ + @Deprecated default void onStaticMetadataChanged(List metadataList) {} /** * Called when the combined {@link MediaMetadata} changes. * *

        The provided {@link MediaMetadata} is a combination of the {@link MediaItem#mediaMetadata} - * and the static and dynamic metadata sourced from {@link #onStaticMetadataChanged(List)} and - * {@link MetadataOutput#onMetadata(Metadata)}. + * and the static and dynamic metadata from the {@link TrackSelection#getFormat(int) track + * selections' formats} and {@link MetadataOutput#onMetadata(Metadata)}. * *

        {@link #onEvents(Player, Events)} will also be called to report this event along with * other events that happen in the same {@link Looper} message queue iteration. @@ -168,6 +151,9 @@ default void onStaticMetadataChanged(List metadataList) {} */ default void onMediaMetadataChanged(MediaMetadata mediaMetadata) {} + /** Called when the playlist {@link MediaMetadata} changes. */ + default void onPlaylistMetadataChanged(MediaMetadata mediaMetadata) {} + /** * Called when the player starts or stops loading the source. * @@ -206,9 +192,9 @@ default void onPlayerStateChanged(boolean playWhenReady, @State int playbackStat *

        {@link #onEvents(Player, Events)} will also be called to report this event along with * other events that happen in the same {@link Looper} message queue iteration. * - * @param state The new playback {@link State state}. + * @param playbackState The new playback {@link State state}. */ - default void onPlaybackStateChanged(@State int state) {} + default void onPlaybackStateChanged(@State int playbackState) {} /** * Called when the value returned from {@link #getPlayWhenReady()} changes. @@ -271,9 +257,25 @@ default void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {} *

        {@link #onEvents(Player, Events)} will also be called to report this event along with * other events that happen in the same {@link Looper} message queue iteration. * + *

        Implementations of Player may pass an instance of a subclass of {@link PlaybackException} + * to this method in order to include more information about the error. + * * @param error The error. */ - default void onPlayerError(ExoPlaybackException error) {} + default void onPlayerError(PlaybackException error) {} + + /** + * Called when the {@link PlaybackException} returned by {@link #getPlayerError()} changes. + * + *

        {@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + *

        Implementations of Player may pass an instance of a subclass of {@link PlaybackException} + * to this method in order to include more information about the error. + * + * @param error The new error, or null if the error is being cleared. + */ + default void onPlayerErrorChanged(@Nullable PlaybackException error) {} /** * @deprecated Use {@link #onPositionDiscontinuity(PositionInfo, PositionInfo, int)} instead. @@ -311,6 +313,37 @@ default void onPositionDiscontinuity( */ default void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {} + /** + * Called when the value of {@link #getSeekBackIncrement()} changes. + * + *

        {@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + * @param seekBackIncrementMs The {@link #seekBack()} increment, in milliseconds. + */ + default void onSeekBackIncrementChanged(long seekBackIncrementMs) {} + + /** + * Called when the value of {@link #getSeekForwardIncrement()} changes. + * + *

        {@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + * @param seekForwardIncrementMs The {@link #seekForward()} increment, in milliseconds. + */ + default void onSeekForwardIncrementChanged(long seekForwardIncrementMs) {} + + /** + * Called when the value of {@link #getMaxSeekToPreviousPosition()} changes. + * + *

        {@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + * @param maxSeekToPreviousPositionMs The maximum position for which {@link #seekToPrevious()} + * seeks to the previous position, in milliseconds. + */ + default void onMaxSeekToPreviousPositionChanged(int maxSeekToPreviousPositionMs) {} + /** * @deprecated Seeks are processed without delay. Listen to {@link * #onPositionDiscontinuity(PositionInfo, PositionInfo, int)} with reason {@link @@ -325,8 +358,7 @@ default void onSeekProcessed() {} *

        State changes and events that happen within one {@link Looper} message queue iteration are * reported together and only after all individual callbacks were triggered. * - *

        Only state changes represented by {@link EventFlags events} are reported through this - * method. + *

        Only state changes represented by {@link Event events} are reported through this method. * *

        Listeners should prefer this method over individual callbacks in the following cases: * @@ -353,37 +385,37 @@ default void onSeekProcessed() {} default void onEvents(Player player, Events events) {} } - /** A set of {@link EventFlags}. */ + /** A set of {@link Event events}. */ final class Events { - private final ExoFlags flags; + private final FlagSet flags; /** * Creates an instance. * - * @param flags The {@link ExoFlags} containing the {@link EventFlags} in the set. + * @param flags The {@link FlagSet} containing the {@link Event events}. */ - public Events(ExoFlags flags) { + public Events(FlagSet flags) { this.flags = flags; } /** - * Returns whether the given event occurred. + * Returns whether the given {@link Event} occurred. * - * @param event The {@link EventFlags event}. - * @return Whether the event occurred. + * @param event The {@link Event}. + * @return Whether the {@link Event} occurred. */ - public boolean contains(@EventFlags int event) { + public boolean contains(@Event int event) { return flags.contains(event); } /** - * Returns whether any of the given events occurred. + * Returns whether any of the given {@link Event events} occurred. * - * @param events The {@link EventFlags events}. - * @return Whether any of the events occurred. + * @param events The {@link Event events}. + * @return Whether any of the {@link Event events} occurred. */ - public boolean containsAny(@EventFlags int... events) { + public boolean containsAny(@Event int... events) { return flags.containsAny(events); } @@ -393,19 +425,36 @@ public int size() { } /** - * Returns the {@link EventFlags event} at the given index. + * Returns the {@link Event} at the given index. * *

        Although index-based access is possible, it doesn't imply a particular order of these * events. * * @param index The index. Must be between 0 (inclusive) and {@link #size()} (exclusive). - * @return The {@link EventFlags event} at the given index. + * @return The {@link Event} at the given index. * @throws IndexOutOfBoundsException If index is outside the allowed range. */ - @EventFlags + @Event public int get(int index) { return flags.get(index); } + + @Override + public int hashCode() { + return flags.hashCode(); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof Events)) { + return false; + } + Events other = (Events) obj; + return flags.equals(other.flags); + } } /** Position info describing a playback position involved in a discontinuity. */ @@ -570,16 +619,52 @@ private static String keyForField(@FieldNumber int field) { * *

        Instances are immutable. */ - final class Commands { + final class Commands implements Bundleable { /** A builder for {@link Commands} instances. */ public static final class Builder { - private final ExoFlags.Builder flagsBuilder; + @Command + private static final int[] SUPPORTED_COMMANDS = { + COMMAND_PLAY_PAUSE, + COMMAND_PREPARE_STOP, + COMMAND_SEEK_TO_DEFAULT_POSITION, + COMMAND_SEEK_IN_CURRENT_WINDOW, + COMMAND_SEEK_TO_PREVIOUS_WINDOW, + COMMAND_SEEK_TO_PREVIOUS, + COMMAND_SEEK_TO_NEXT_WINDOW, + COMMAND_SEEK_TO_NEXT, + COMMAND_SEEK_TO_WINDOW, + COMMAND_SEEK_BACK, + COMMAND_SEEK_FORWARD, + COMMAND_SET_SPEED_AND_PITCH, + COMMAND_SET_SHUFFLE_MODE, + COMMAND_SET_REPEAT_MODE, + COMMAND_GET_CURRENT_MEDIA_ITEM, + COMMAND_GET_TIMELINE, + COMMAND_GET_MEDIA_ITEMS_METADATA, + COMMAND_SET_MEDIA_ITEMS_METADATA, + COMMAND_CHANGE_MEDIA_ITEMS, + COMMAND_GET_AUDIO_ATTRIBUTES, + COMMAND_GET_VOLUME, + COMMAND_GET_DEVICE_VOLUME, + COMMAND_SET_VOLUME, + COMMAND_SET_DEVICE_VOLUME, + COMMAND_ADJUST_DEVICE_VOLUME, + COMMAND_SET_VIDEO_SURFACE, + COMMAND_GET_TEXT + }; + + private final FlagSet.Builder flagsBuilder; /** Creates a builder. */ public Builder() { - flagsBuilder = new ExoFlags.Builder(); + flagsBuilder = new FlagSet.Builder(); + } + + private Builder(Commands commands) { + flagsBuilder = new FlagSet.Builder(); + flagsBuilder.addAll(commands.flags); } /** @@ -631,6 +716,54 @@ public Builder addAll(Commands commands) { return this; } + /** + * Adds all existing {@link Command commands}. + * + * @return This builder. + * @throws IllegalStateException If {@link #build()} has already been called. + */ + public Builder addAllCommands() { + flagsBuilder.addAll(SUPPORTED_COMMANDS); + return this; + } + + /** + * Removes a {@link Command}. + * + * @param command A {@link Command}. + * @return This builder. + * @throws IllegalStateException If {@link #build()} has already been called. + */ + public Builder remove(@Command int command) { + flagsBuilder.remove(command); + return this; + } + + /** + * Removes a {@link Command} if the provided condition is true. Does nothing otherwise. + * + * @param command A {@link Command}. + * @param condition A condition. + * @return This builder. + * @throws IllegalStateException If {@link #build()} has already been called. + */ + public Builder removeIf(@Command int command, boolean condition) { + flagsBuilder.removeIf(command, condition); + return this; + } + + /** + * Removes {@link Command commands}. + * + * @param commands The {@link Command commands} to remove. + * @return This builder. + * @throws IllegalStateException If {@link #build()} has already been called. + */ + public Builder removeAll(@Command int... commands) { + flagsBuilder.removeAll(commands); + return this; + } + /** * Builds a {@link Commands} instance. * @@ -644,12 +777,17 @@ public Commands build() { /** An empty set of commands. */ public static final Commands EMPTY = new Builder().build(); - private final ExoFlags flags; + private final FlagSet flags; - private Commands(ExoFlags flags) { + private Commands(FlagSet flags) { this.flags = flags; } + /** Returns a {@link Builder} initialized with the values of this instance. */ + public Builder buildUpon() { + return new Builder(this); + } + /** Returns whether the set of commands contains the specified {@link Command}. */ public boolean contains(@Command int command) { return flags.contains(command); @@ -688,6 +826,46 @@ public boolean equals(@Nullable Object obj) { public int hashCode() { return flags.hashCode(); } + + // Bundleable implementation. + + @Documented + @Retention(RetentionPolicy.SOURCE) + @IntDef({FIELD_COMMANDS}) + private @interface FieldNumber {} + + private static final int FIELD_COMMANDS = 0; + + @Override + public Bundle toBundle() { + Bundle bundle = new Bundle(); + ArrayList commandsBundle = new ArrayList<>(); + for (int i = 0; i < flags.size(); i++) { + commandsBundle.add(flags.get(i)); + } + bundle.putIntegerArrayList(keyForField(FIELD_COMMANDS), commandsBundle); + return bundle; + } + + /** Object that can restore {@link Commands} from a {@link Bundle}. */ + public static final Creator CREATOR = Commands::fromBundle; + + private static Commands fromBundle(Bundle bundle) { + @Nullable + ArrayList commands = bundle.getIntegerArrayList(keyForField(FIELD_COMMANDS)); + if (commands == null) { + return Commands.EMPTY; + } + Builder builder = new Builder(); + for (int i = 0; i < commands.size(); i++) { + builder.add(commands.get(i)); + } + return builder.build(); + } + + private static String keyForField(@FieldNumber int field) { + return Integer.toString(field, Character.MAX_RADIX); + } } /** @@ -721,7 +899,7 @@ default void onIsLoadingChanged(boolean isLoading) {} default void onAvailableCommandsChanged(Commands availableCommands) {} @Override - default void onPlaybackStateChanged(@State int state) {} + default void onPlaybackStateChanged(@State int playbackState) {} @Override default void onPlayWhenReadyChanged( @@ -741,7 +919,10 @@ default void onRepeatModeChanged(@RepeatMode int repeatMode) {} default void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {} @Override - default void onPlayerError(ExoPlaybackException error) {} + default void onPlayerError(PlaybackException error) {} + + @Override + default void onPlayerErrorChanged(@Nullable PlaybackException error) {} @Override default void onPositionDiscontinuity( @@ -750,6 +931,12 @@ default void onPositionDiscontinuity( @Override default void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {} + @Override + default void onSeekForwardIncrementChanged(long seekForwardIncrementMs) {} + + @Override + default void onSeekBackIncrementChanged(long seekBackIncrementMs) {} + @Override default void onAudioSessionIdChanged(int audioSessionId) {} @@ -790,7 +977,7 @@ default void onMetadata(Metadata metadata) {} default void onMediaMetadataChanged(MediaMetadata mediaMetadata) {} @Override - default void onStaticMetadataChanged(List metadataList) {} + default void onPlaylistMetadataChanged(MediaMetadata mediaMetadata) {} } /** @@ -907,15 +1094,15 @@ default void onStaticMetadataChanged(List metadataList) {} }) @interface DiscontinuityReason {} /** - * Automatic playback transition from one period in the timeline to the next without explicit - * interaction by this player. The period index may be the same as it was before the discontinuity - * in case the current period is repeated. + * Automatic playback transition from one period in the timeline to the next. The period index may + * be the same as it was before the discontinuity in case the current period is repeated. * *

        This reason also indicates an automatic transition from the content period to an inserted ad - * period or vice versa. + * period or vice versa. Or a transition caused by another player (e.g. multiple controllers can + * control the same playback on a remote device). */ int DISCONTINUITY_REASON_AUTO_TRANSITION = 0; - /** Seek within the current period or to another period by this player. */ + /** Seek within the current period or to another period. */ int DISCONTINUITY_REASON_SEEK = 1; /** * Seek adjustment due to being unable to seek to the requested position or because the seek was @@ -939,7 +1126,13 @@ default void onStaticMetadataChanged(List metadataList) {} @interface TimelineChangeReason {} /** Timeline changed as a result of a change of the playlist items or the order of the items. */ int TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED = 0; - /** Timeline changed as a result of a dynamic update introduced by the played media. */ + /** + * Timeline changed as a result of a source update (e.g. result of a dynamic update by the played + * media). + * + *

        This reason also indicates a change caused by another player (e.g. multiple controllers can + * control the same playback on the remote device). + */ int TIMELINE_CHANGE_REASON_SOURCE_UPDATE = 1; /** @@ -958,7 +1151,12 @@ default void onStaticMetadataChanged(List metadataList) {} @interface MediaItemTransitionReason {} /** The media item has been repeated. */ int MEDIA_ITEM_TRANSITION_REASON_REPEAT = 0; - /** Playback has automatically transitioned to the next media item. */ + /** + * Playback has automatically transitioned to the next media item. + * + *

        This reason also indicates a transition caused by another player (e.g. multiple controllers + * can control the same playback on a remote device). + */ int MEDIA_ITEM_TRANSITION_REASON_AUTO = 1; /** A seek to another media item has occurred. */ int MEDIA_ITEM_TRANSITION_REASON_SEEK = 2; @@ -972,7 +1170,7 @@ default void onStaticMetadataChanged(List metadataList) {} /** * Events that can be reported via {@link Listener#onEvents(Player, Events)}. * - *

        One of the {@link Player}{@code .EVENT_*} flags. + *

        One of the {@link Player}{@code .EVENT_*} values. */ @Documented @Retention(RetentionPolicy.SOURCE) @@ -992,17 +1190,21 @@ default void onStaticMetadataChanged(List metadataList) {} EVENT_POSITION_DISCONTINUITY, EVENT_PLAYBACK_PARAMETERS_CHANGED, EVENT_AVAILABLE_COMMANDS_CHANGED, - EVENT_MEDIA_METADATA_CHANGED + EVENT_MEDIA_METADATA_CHANGED, + EVENT_PLAYLIST_METADATA_CHANGED, + EVENT_SEEK_BACK_INCREMENT_CHANGED, + EVENT_SEEK_FORWARD_INCREMENT_CHANGED, + EVENT_MAX_SEEK_TO_PREVIOUS_POSITION_CHANGED }) - @interface EventFlags {} + @interface Event {} /** {@link #getCurrentTimeline()} changed. */ int EVENT_TIMELINE_CHANGED = 0; /** {@link #getCurrentMediaItem()} changed or the player started repeating the current item. */ int EVENT_MEDIA_ITEM_TRANSITION = 1; /** {@link #getCurrentTrackGroups()} or {@link #getCurrentTrackSelections()} changed. */ int EVENT_TRACKS_CHANGED = 2; - /** {@link #getCurrentStaticMetadata()} changed. */ - int EVENT_STATIC_METADATA_CHANGED = 3; + /** @deprecated Use {@link #EVENT_MEDIA_METADATA_CHANGED} for structured metadata changes. */ + @Deprecated int EVENT_STATIC_METADATA_CHANGED = 3; /** {@link #isLoading()} ()} changed. */ int EVENT_IS_LOADING_CHANGED = 4; /** {@link #getPlaybackState()} changed. */ @@ -1030,15 +1232,25 @@ default void onStaticMetadataChanged(List metadataList) {} int EVENT_AVAILABLE_COMMANDS_CHANGED = 14; /** {@link #getMediaMetadata()} changed. */ int EVENT_MEDIA_METADATA_CHANGED = 15; + /** {@link #getPlaylistMetadata()} changed. */ + int EVENT_PLAYLIST_METADATA_CHANGED = 16; + /** {@link #getSeekBackIncrement()} changed. */ + int EVENT_SEEK_BACK_INCREMENT_CHANGED = 17; + /** {@link #getSeekForwardIncrement()} changed. */ + int EVENT_SEEK_FORWARD_INCREMENT_CHANGED = 18; + /** {@link #getMaxSeekToPreviousPosition()} changed. */ + int EVENT_MAX_SEEK_TO_PREVIOUS_POSITION_CHANGED = 19; /** * Commands that can be executed on a {@code Player}. One of {@link #COMMAND_PLAY_PAUSE}, {@link * #COMMAND_PREPARE_STOP}, {@link #COMMAND_SEEK_TO_DEFAULT_POSITION}, {@link - * #COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM}, {@link #COMMAND_SEEK_TO_NEXT_MEDIA_ITEM}, {@link - * #COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM}, {@link #COMMAND_SEEK_TO_MEDIA_ITEM}, {@link - * #COMMAND_SET_SPEED_AND_PITCH}, {@link #COMMAND_SET_SHUFFLE_MODE}, {@link - * #COMMAND_SET_REPEAT_MODE}, {@link #COMMAND_GET_CURRENT_MEDIA_ITEM}, {@link - * #COMMAND_GET_MEDIA_ITEMS}, {@link #COMMAND_GET_MEDIA_ITEMS_METADATA}, {@link + * #COMMAND_SEEK_IN_CURRENT_WINDOW}, {@link #COMMAND_SEEK_TO_PREVIOUS_WINDOW}, {@link + * #COMMAND_SEEK_TO_PREVIOUS}, {@link #COMMAND_SEEK_TO_NEXT_WINDOW}, {@link + * #COMMAND_SEEK_TO_NEXT}, {@link #COMMAND_SEEK_TO_WINDOW}, {@link #COMMAND_SEEK_BACK}, {@link + * #COMMAND_SEEK_FORWARD}, {@link #COMMAND_SET_SPEED_AND_PITCH}, {@link + * #COMMAND_SET_SHUFFLE_MODE}, {@link #COMMAND_SET_REPEAT_MODE}, {@link + * #COMMAND_GET_CURRENT_MEDIA_ITEM}, {@link #COMMAND_GET_TIMELINE}, {@link + * #COMMAND_GET_MEDIA_ITEMS_METADATA}, {@link #COMMAND_SET_MEDIA_ITEMS_METADATA}, {@link * #COMMAND_CHANGE_MEDIA_ITEMS}, {@link #COMMAND_GET_AUDIO_ATTRIBUTES}, {@link * #COMMAND_GET_VOLUME}, {@link #COMMAND_GET_DEVICE_VOLUME}, {@link #COMMAND_SET_VOLUME}, {@link * #COMMAND_SET_DEVICE_VOLUME}, {@link #COMMAND_ADJUST_DEVICE_VOLUME}, {@link @@ -1047,19 +1259,25 @@ default void onStaticMetadataChanged(List metadataList) {} @Documented @Retention(RetentionPolicy.SOURCE) @IntDef({ + COMMAND_INVALID, COMMAND_PLAY_PAUSE, COMMAND_PREPARE_STOP, COMMAND_SEEK_TO_DEFAULT_POSITION, - COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, - COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, - COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM, - COMMAND_SEEK_TO_MEDIA_ITEM, + COMMAND_SEEK_IN_CURRENT_WINDOW, + COMMAND_SEEK_TO_PREVIOUS_WINDOW, + COMMAND_SEEK_TO_PREVIOUS, + COMMAND_SEEK_TO_NEXT_WINDOW, + COMMAND_SEEK_TO_NEXT, + COMMAND_SEEK_TO_WINDOW, + COMMAND_SEEK_BACK, + COMMAND_SEEK_FORWARD, COMMAND_SET_SPEED_AND_PITCH, COMMAND_SET_SHUFFLE_MODE, COMMAND_SET_REPEAT_MODE, COMMAND_GET_CURRENT_MEDIA_ITEM, - COMMAND_GET_MEDIA_ITEMS, + COMMAND_GET_TIMELINE, COMMAND_GET_MEDIA_ITEMS_METADATA, + COMMAND_SET_MEDIA_ITEMS_METADATA, COMMAND_CHANGE_MEDIA_ITEMS, COMMAND_GET_AUDIO_ATTRIBUTES, COMMAND_GET_VOLUME, @@ -1078,43 +1296,56 @@ default void onStaticMetadataChanged(List metadataList) {} /** Command to seek to the default position of the current window. */ int COMMAND_SEEK_TO_DEFAULT_POSITION = 3; /** Command to seek anywhere into the current window. */ - int COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM = 4; - /** Command to seek to the default position of the next window. */ - int COMMAND_SEEK_TO_NEXT_MEDIA_ITEM = 5; + int COMMAND_SEEK_IN_CURRENT_WINDOW = 4; /** Command to seek to the default position of the previous window. */ - int COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM = 6; + int COMMAND_SEEK_TO_PREVIOUS_WINDOW = 5; + /** Command to seek to an earlier position in the current or previous window. */ + int COMMAND_SEEK_TO_PREVIOUS = 6; + /** Command to seek to the default position of the next window. */ + int COMMAND_SEEK_TO_NEXT_WINDOW = 7; + /** Command to seek to a later position in the current or next window. */ + int COMMAND_SEEK_TO_NEXT = 8; /** Command to seek anywhere in any window. */ - int COMMAND_SEEK_TO_MEDIA_ITEM = 7; + int COMMAND_SEEK_TO_WINDOW = 9; + /** Command to seek back by a fixed increment into the current window. */ + int COMMAND_SEEK_BACK = 10; + /** Command to seek forward by a fixed increment into the current window. */ + int COMMAND_SEEK_FORWARD = 11; /** Command to set the playback speed and pitch. */ - int COMMAND_SET_SPEED_AND_PITCH = 8; + int COMMAND_SET_SPEED_AND_PITCH = 12; /** Command to enable shuffling. */ - int COMMAND_SET_SHUFFLE_MODE = 9; + int COMMAND_SET_SHUFFLE_MODE = 13; /** Command to set the repeat mode. */ - int COMMAND_SET_REPEAT_MODE = 10; + int COMMAND_SET_REPEAT_MODE = 14; /** Command to get the {@link MediaItem} of the current window. */ - int COMMAND_GET_CURRENT_MEDIA_ITEM = 11; - /** Command to get the current timeline and its {@link MediaItem MediaItems}. */ - int COMMAND_GET_MEDIA_ITEMS = 12; + int COMMAND_GET_CURRENT_MEDIA_ITEM = 15; + /** Command to get the information about the current timeline. */ + int COMMAND_GET_TIMELINE = 16; /** Command to get the {@link MediaItem MediaItems} metadata. */ - int COMMAND_GET_MEDIA_ITEMS_METADATA = 13; + int COMMAND_GET_MEDIA_ITEMS_METADATA = 17; + /** Command to set the {@link MediaItem MediaItems} metadata. */ + int COMMAND_SET_MEDIA_ITEMS_METADATA = 18; /** Command to change the {@link MediaItem MediaItems} in the playlist. */ - int COMMAND_CHANGE_MEDIA_ITEMS = 14; + int COMMAND_CHANGE_MEDIA_ITEMS = 19; /** Command to get the player current {@link AudioAttributes}. */ - int COMMAND_GET_AUDIO_ATTRIBUTES = 15; + int COMMAND_GET_AUDIO_ATTRIBUTES = 20; /** Command to get the player volume. */ - int COMMAND_GET_VOLUME = 16; + int COMMAND_GET_VOLUME = 21; /** Command to get the device volume and whether it is muted. */ - int COMMAND_GET_DEVICE_VOLUME = 17; + int COMMAND_GET_DEVICE_VOLUME = 22; /** Command to set the player volume. */ - int COMMAND_SET_VOLUME = 18; + int COMMAND_SET_VOLUME = 23; /** Command to set the device volume and mute it. */ - int COMMAND_SET_DEVICE_VOLUME = 19; + int COMMAND_SET_DEVICE_VOLUME = 24; /** Command to increase and decrease the device volume and mute it. */ - int COMMAND_ADJUST_DEVICE_VOLUME = 20; + int COMMAND_ADJUST_DEVICE_VOLUME = 25; /** Command to set and clear the surface on which to render the video. */ - int COMMAND_SET_VIDEO_SURFACE = 21; + int COMMAND_SET_VIDEO_SURFACE = 26; /** Command to get the text that should currently be displayed by the player. */ - int COMMAND_GET_TEXT = 22; + int COMMAND_GET_TEXT = 27; + + /** Represents an invalid {@link Command}. */ + int COMMAND_INVALID = -1; /** * Returns the {@link Looper} associated with the application thread that's used to access the @@ -1123,9 +1354,11 @@ default void onStaticMetadataChanged(List metadataList) {} Looper getApplicationLooper(); /** - * Registers a listener to receive events from the player. The listener's methods will be called - * on the thread that was used to construct the player. However, if the thread used to construct - * the player does not have a {@link Looper}, then the listener will be called on the main thread. + * Registers a listener to receive events from the player. + * + *

        The listener's methods will be called on the thread that was used to construct the player. + * However, if the thread used to construct the player does not have a {@link Looper}, then the + * listener will be called on the main thread. * * @param listener The listener to register. * @deprecated Use {@link #addListener(Listener)} and {@link #removeListener(Listener)} instead. @@ -1136,6 +1369,10 @@ default void onStaticMetadataChanged(List metadataList) {} /** * Registers a listener to receive all events from the player. * + *

        The listener's methods will be called on the thread that was used to construct the player. + * However, if the thread used to construct the player does not have a {@link Looper}, then the + * listener will be called on the main thread. + * * @param listener The listener to register. */ void addListener(Listener listener); @@ -1293,12 +1530,12 @@ default void onStaticMetadataChanged(List metadataList) {} * *

        This method does not execute the command. * - *

        Executing a command that is not available (for example, calling {@link #next()} if {@link - * #COMMAND_SEEK_TO_NEXT_MEDIA_ITEM} is unavailable) will neither throw an exception nor generate - * a {@link #getPlayerError()} player error}. + *

        Executing a command that is not available (for example, calling {@link #seekToNextWindow()} + * if {@link #COMMAND_SEEK_TO_NEXT_WINDOW} is unavailable) will neither throw an exception nor + * generate a {@link #getPlayerError()} player error}. * - *

        {@link #COMMAND_SEEK_TO_NEXT_MEDIA_ITEM} and {@link #COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM} - * are unavailable if there is no such {@link MediaItem}. + *

        {@link #COMMAND_SEEK_TO_PREVIOUS_WINDOW} and {@link #COMMAND_SEEK_TO_NEXT_WINDOW} are + * unavailable if there is no such {@link MediaItem}. * * @param command A {@link Command}. * @return Whether the {@link Command} is available. @@ -1313,12 +1550,12 @@ default void onStaticMetadataChanged(List metadataList) {} * Listener#onAvailableCommandsChanged(Commands)} to get an update when the available commands * change. * - *

        Executing a command that is not available (for example, calling {@link #next()} if {@link - * #COMMAND_SEEK_TO_NEXT_MEDIA_ITEM} is unavailable) will neither throw an exception nor generate - * a {@link #getPlayerError()} player error}. + *

        Executing a command that is not available (for example, calling {@link #seekToNextWindow()} + * if {@link #COMMAND_SEEK_TO_NEXT_WINDOW} is unavailable) will neither throw an exception nor + * generate a {@link #getPlayerError()} player error}. * - *

        {@link #COMMAND_SEEK_TO_NEXT_MEDIA_ITEM} and {@link #COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM} - * are unavailable if there is no such {@link MediaItem}. + *

        {@link #COMMAND_SEEK_TO_PREVIOUS_WINDOW} and {@link #COMMAND_SEEK_TO_NEXT_WINDOW} are + * unavailable if there is no such {@link MediaItem}. * * @return The currently available {@link Commands}. * @see Listener#onAvailableCommandsChanged @@ -1365,22 +1602,17 @@ default void onStaticMetadataChanged(List metadataList) {} /** * Returns the error that caused playback to fail. This is the same error that will have been - * reported via {@link Listener#onPlayerError(ExoPlaybackException)} at the time of failure. It - * can be queried using this method until the player is re-prepared. + * reported via {@link Listener#onPlayerError(PlaybackException)} at the time of failure. It can + * be queried using this method until the player is re-prepared. * *

        Note that this method will always return {@code null} if {@link #getPlaybackState()} is not * {@link #STATE_IDLE}. * * @return The error, or {@code null}. - * @see Listener#onPlayerError(ExoPlaybackException) + * @see Listener#onPlayerError(PlaybackException) */ @Nullable - ExoPlaybackException getPlayerError(); - - /** @deprecated Use {@link #getPlayerError()} instead. */ - @Deprecated - @Nullable - ExoPlaybackException getPlaybackError(); + PlaybackException getPlayerError(); /** * Resumes playback as soon as {@link #getPlaybackState()} == {@link #STATE_READY}. Equivalent to @@ -1484,6 +1716,32 @@ default void onStaticMetadataChanged(List metadataList) {} */ void seekTo(int windowIndex, long positionMs); + /** + * Returns the {@link #seekBack()} increment. + * + * @return The seek back increment, in milliseconds. + * @see Listener#onSeekBackIncrementChanged(long) + */ + long getSeekBackIncrement(); + + /** Seeks back in the current window by {@link #getSeekBackIncrement()} milliseconds. */ + void seekBack(); + + /** + * Returns the {@link #seekForward()} increment. + * + * @return The seek forward increment, in milliseconds. + * @see Listener#onSeekForwardIncrementChanged(long) + */ + long getSeekForwardIncrement(); + + /** Seeks forward in the current window by {@link #getSeekForwardIncrement()} milliseconds. */ + void seekForward(); + + /** @deprecated Use {@link #hasPreviousWindow()} instead. */ + @Deprecated + boolean hasPrevious(); + /** * Returns whether a previous window exists, which may depend on the current repeat mode and * whether shuffle mode is enabled. @@ -1492,18 +1750,55 @@ default void onStaticMetadataChanged(List metadataList) {} * the current repeat mode is {@link #REPEAT_MODE_OFF}. See {@link #REPEAT_MODE_ONE} for more * details. */ - boolean hasPrevious(); + boolean hasPreviousWindow(); + + /** @deprecated Use {@link #seekToPreviousWindow()} instead. */ + @Deprecated + void previous(); /** * Seeks to the default position of the previous window, which may depend on the current repeat - * mode and whether shuffle mode is enabled. Does nothing if {@link #hasPrevious()} is {@code - * false}. + * mode and whether shuffle mode is enabled. Does nothing if {@link #hasPreviousWindow()} is + * {@code false}. * *

        Note: When the repeat mode is {@link #REPEAT_MODE_ONE}, this method behaves the same as when * the current repeat mode is {@link #REPEAT_MODE_OFF}. See {@link #REPEAT_MODE_ONE} for more * details. */ - void previous(); + void seekToPreviousWindow(); + + /** + * Returns the maximum position for which {@link #seekToPrevious()} seeks to the previous window, + * in milliseconds. + * + * @return The maximum seek to previous position, in milliseconds. + * @see Listener#onMaxSeekToPreviousPositionChanged(int) + */ + int getMaxSeekToPreviousPosition(); + + /** + * Seeks to an earlier position in the current or previous window (if available). More precisely: + * + *

          + *
        • If the timeline is empty or seeking is not possible, does nothing. + *
        • Otherwise, if the current window is {@link #isCurrentWindowLive() live} and {@link + * #isCurrentWindowSeekable() unseekable}, then: + *
            + *
          • If {@link #hasPreviousWindow() a previous window exists}, seeks to the default + * position of the previous window. + *
          • Otherwise, does nothing. + *
          + *
        • Otherwise, if {@link #hasPreviousWindow() a previous window exists} and the {@link + * #getCurrentPosition() current position} is less than {@link + * #getMaxSeekToPreviousPosition()}, seeks to the default position of the previous window. + *
        • Otherwise, seeks to 0 in the current window. + *
        + */ + void seekToPrevious(); + + /** @deprecated Use {@link #hasNextWindow()} instead. */ + @Deprecated + boolean hasNext(); /** * Returns whether a next window exists, which may depend on the current repeat mode and whether @@ -1513,17 +1808,35 @@ default void onStaticMetadataChanged(List metadataList) {} * the current repeat mode is {@link #REPEAT_MODE_OFF}. See {@link #REPEAT_MODE_ONE} for more * details. */ - boolean hasNext(); + boolean hasNextWindow(); + + /** @deprecated Use {@link #seekToNextWindow()} instead. */ + @Deprecated + void next(); /** * Seeks to the default position of the next window, which may depend on the current repeat mode - * and whether shuffle mode is enabled. Does nothing if {@link #hasNext()} is {@code false}. + * and whether shuffle mode is enabled. Does nothing if {@link #hasNextWindow()} is {@code false}. * *

        Note: When the repeat mode is {@link #REPEAT_MODE_ONE}, this method behaves the same as when * the current repeat mode is {@link #REPEAT_MODE_OFF}. See {@link #REPEAT_MODE_ONE} for more * details. */ - void next(); + void seekToNextWindow(); + + /** + * Seeks to a later position in the current or next window (if available). More precisely: + * + *

          + *
        • If the timeline is empty or seeking is not possible, does nothing. + *
        • Otherwise, if {@link #hasNextWindow() a next window exists}, seeks to the default + * position of the next window. + *
        • Otherwise, if the current window is {@link #isCurrentWindowLive() live} and has not + * ended, seeks to the live edge of the current window. + *
        • Otherwise, does nothing. + *
        + */ + void seekToNext(); /** * Attempts to set the playback parameters. Passing {@link PlaybackParameters#DEFAULT} resets the @@ -1601,18 +1914,12 @@ default void onStaticMetadataChanged(List metadataList) {} TrackSelectionArray getCurrentTrackSelections(); /** - * Returns the current static metadata for the track selections. - * - *

        The returned {@code metadataList} is an immutable list of {@link Metadata} instances, where - * the elements correspond to the {@link #getCurrentTrackSelections() current track selections}, - * or an empty list if there are no track selections or the selected tracks contain no static - * metadata. - * - *

        This metadata is considered static in that it comes from the tracks' declared Formats, - * rather than being timed (or dynamic) metadata, which is represented within a metadata track. - * - * @see Listener#onStaticMetadataChanged(List) + * @deprecated Use {@link #getMediaMetadata()} and {@link + * Listener#onMediaMetadataChanged(MediaMetadata)} for access to structured metadata, or + * access the raw static metadata directly from the {@link TrackSelection#getFormat(int) track + * selections' formats}. */ + @Deprecated List getCurrentStaticMetadata(); /** @@ -1620,11 +1927,20 @@ default void onStaticMetadataChanged(List metadataList) {} * supported. * *

        This {@link MediaMetadata} is a combination of the {@link MediaItem#mediaMetadata} and the - * static and dynamic metadata sourced from {@link Listener#onStaticMetadataChanged(List)} and - * {@link MetadataOutput#onMetadata(Metadata)}. + * static and dynamic metadata from the {@link TrackSelection#getFormat(int) track selections' + * formats} and {@link MetadataOutput#onMetadata(Metadata)}. */ MediaMetadata getMediaMetadata(); + /** + * Returns the playlist {@link MediaMetadata}, as set by {@link + * #setPlaylistMetadata(MediaMetadata)}, or {@link MediaMetadata#EMPTY} if not supported. + */ + MediaMetadata getPlaylistMetadata(); + + /** Sets the playlist {@link MediaMetadata}. */ + void setPlaylistMetadata(MediaMetadata mediaMetadata); + /** * Returns the current manifest. The type depends on the type of media being played. May be null. */ @@ -1649,9 +1965,9 @@ default void onStaticMetadataChanged(List metadataList) {} int getCurrentWindowIndex(); /** - * Returns the index of the window that will be played if {@link #next()} is called, which may - * depend on the current repeat mode and whether shuffle mode is enabled. Returns {@link - * C#INDEX_UNSET} if {@link #hasNext()} is {@code false}. + * Returns the index of the window that will be played if {@link #seekToNextWindow()} is called, + * which may depend on the current repeat mode and whether shuffle mode is enabled. Returns {@link + * C#INDEX_UNSET} if {@link #hasNextWindow()} is {@code false}. * *

        Note: When the repeat mode is {@link #REPEAT_MODE_ONE}, this method behaves the same as when * the current repeat mode is {@link #REPEAT_MODE_OFF}. See {@link #REPEAT_MODE_ONE} for more @@ -1660,9 +1976,9 @@ default void onStaticMetadataChanged(List metadataList) {} int getNextWindowIndex(); /** - * Returns the index of the window that will be played if {@link #previous()} is called, which may - * depend on the current repeat mode and whether shuffle mode is enabled. Returns {@link - * C#INDEX_UNSET} if {@link #hasPrevious()} is {@code false}. + * Returns the index of the window that will be played if {@link #seekToPreviousWindow()} is + * called, which may depend on the current repeat mode and whether shuffle mode is enabled. + * Returns {@link C#INDEX_UNSET} if {@link #hasPreviousWindow()} is {@code false}. * *

        Note: When the repeat mode is {@link #REPEAT_MODE_ONE}, this method behaves the same as when * the current repeat mode is {@link #REPEAT_MODE_OFF}. See {@link #REPEAT_MODE_ONE} for more @@ -1670,14 +1986,6 @@ default void onStaticMetadataChanged(List metadataList) {} */ int getPreviousWindowIndex(); - /** - * @deprecated Use {@link #getCurrentMediaItem()} and {@link MediaItem.PlaybackProperties#tag} - * instead. - */ - @Deprecated - @Nullable - Object getCurrentTag(); - /** * Returns the media item of the current window in the timeline. May be null if the timeline is * empty. diff --git a/library/common/src/main/java/com/google/android/exoplayer2/Timeline.java b/library/common/src/main/java/com/google/android/exoplayer2/Timeline.java index 10e91fc22f1..5e9ff6a65db 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/Timeline.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/Timeline.java @@ -58,7 +58,7 @@ * *

        The following examples illustrate timelines for various use cases. * - *

        Single media file or on-demand stream

        + *

        Single media file or on-demand stream

        * *

        Example timeline for a
  * single file @@ -68,7 +68,7 @@ * playback. The window's default position is typically at the start of the period (indicated by the * black dot in the figure above). * - *

        Playlist of media files or on-demand streams

        + *

        Playlist of media files or on-demand streams

        * *

        Example timeline for a
  * playlist of files @@ -79,7 +79,7 @@ * (e.g. their durations and whether the window is seekable) will often only become known when the * player starts buffering the corresponding file or stream. * - *

        Live stream with limited availability

        + *

        Live stream with limited availability

        * *

        Example timeline for
  * a live stream with limited availability @@ -92,7 +92,7 @@ * changes to the live window. Its default position is typically near to the live edge (indicated by * the black dot in the figure above). * - *

        Live stream with indefinite availability

        + *

        Live stream with indefinite availability

        * *

        Example timeline
  * for a live stream with indefinite availability @@ -102,7 +102,7 @@ * starts at the beginning of the period to indicate that all of the previously broadcast content * can still be played. * - *

        Live stream with multiple periods

        + *

        Live stream with multiple periods

        * *

        Example timeline
  * for a live stream with multiple periods @@ -112,7 +112,7 @@ * limited availability case, except that the window may span more than one period. Multiple * periods are also possible in the indefinite availability case. * - *

        On-demand stream followed by live stream

        + *

        On-demand stream followed by live stream

        * *

        Example timeline for an
  * on-demand stream followed by a live stream @@ -122,7 +122,7 @@ * of the on-demand stream ends, playback of the live stream will start from its default position * near the live edge. * - *

        On-demand stream with mid-roll ads

        + *

        On-demand stream with mid-roll ads

        * *

        Example
  * timeline for an on-demand stream with mid-roll ad groups @@ -229,9 +229,7 @@ public static final class Window implements Bundleable { */ public long defaultPositionUs; - /** - * The duration of this window in microseconds, or {@link C#TIME_UNSET} if unknown. - */ + /** The duration of this window in microseconds, or {@link C#TIME_UNSET} if unknown. */ public long durationUs; /** The index of the first period that belongs to this window. */ @@ -312,16 +310,12 @@ public long getDefaultPositionUs() { return defaultPositionUs; } - /** - * Returns the duration of the window in milliseconds, or {@link C#TIME_UNSET} if unknown. - */ + /** Returns the duration of the window in milliseconds, or {@link C#TIME_UNSET} if unknown. */ public long getDurationMs() { return C.usToMs(durationUs); } - /** - * Returns the duration of this window in microseconds, or {@link C#TIME_UNSET} if unknown. - */ + /** Returns the duration of this window in microseconds, or {@link C#TIME_UNSET} if unknown. */ public long getDurationUs() { return durationUs; } @@ -446,18 +440,11 @@ public int hashCode() { private static final int FIELD_LAST_PERIOD_INDEX = 12; private static final int FIELD_POSITION_IN_FIRST_PERIOD_US = 13; - /** - * {@inheritDoc} - * - *

        It omits the {@link #uid} and {@link #manifest} fields. The {@link #uid} of an instance - * restored by {@link #CREATOR} will be a fake {@link Object} and the {@link #manifest} of the - * instance will be {@code null}. - */ - // TODO(b/166765820): See if missing fields would be okay and add them to the Bundle otherwise. - @Override - public Bundle toBundle() { + private final Bundle toBundle(boolean excludeMediaItem) { Bundle bundle = new Bundle(); - bundle.putBundle(keyForField(FIELD_MEDIA_ITEM), mediaItem.toBundle()); + bundle.putBundle( + keyForField(FIELD_MEDIA_ITEM), + excludeMediaItem ? MediaItem.EMPTY.toBundle() : mediaItem.toBundle()); bundle.putLong(keyForField(FIELD_PRESENTATION_START_TIME_MS), presentationStartTimeMs); bundle.putLong(keyForField(FIELD_WINDOW_START_TIME_MS), windowStartTimeMs); bundle.putLong( @@ -477,6 +464,19 @@ public Bundle toBundle() { return bundle; } + /** + * {@inheritDoc} + * + *

        It omits the {@link #uid} and {@link #manifest} fields. The {@link #uid} of an instance + * restored by {@link #CREATOR} will be a fake {@link Object} and the {@link #manifest} of the + * instance will be {@code null}. + */ + // TODO(b/166765820): See if missing fields would be okay and add them to the Bundle otherwise. + @Override + public Bundle toBundle() { + return toBundle(/* excludeMediaItem= */ false); + } + /** * Object that can restore {@link Period} from a {@link Bundle}. * @@ -572,14 +572,10 @@ public static final class Period implements Bundleable { */ @Nullable public Object uid; - /** - * The index of the window to which this period belongs. - */ + /** The index of the window to which this period belongs. */ public int windowIndex; - /** - * The duration of this period in microseconds, or {@link C#TIME_UNSET} if unknown. - */ + /** The duration of this period in microseconds, or {@link C#TIME_UNSET} if unknown. */ public long durationUs; /** @@ -670,16 +666,12 @@ public Period set( return this; } - /** - * Returns the duration of the period in milliseconds, or {@link C#TIME_UNSET} if unknown. - */ + /** Returns the duration of the period in milliseconds, or {@link C#TIME_UNSET} if unknown. */ public long getDurationMs() { return C.usToMs(durationUs); } - /** - * Returns the duration of this period in microseconds, or {@link C#TIME_UNSET} if unknown. - */ + /** Returns the duration of this period in microseconds, or {@link C#TIME_UNSET} if unknown. */ public long getDurationUs() { return durationUs; } @@ -713,6 +705,14 @@ public int getAdGroupCount() { return adPlaybackState.adGroupCount; } + /** + * Returns the number of removed ad groups in the period. Ad groups with indices between {@code + * 0} (inclusive) and {@code removedAdGroupCount} (exclusive) will be empty. + */ + public int getRemovedAdGroupCount() { + return adPlaybackState.removedAdGroupCount; + } + /** * Returns the time of the ad group at index {@code adGroupIndex} in the period, in * microseconds. @@ -722,7 +722,7 @@ public int getAdGroupCount() { * Period}, in microseconds, or {@link C#TIME_END_OF_SOURCE} for a post-roll ad group. */ public long getAdGroupTimeUs(int adGroupIndex) { - return adPlaybackState.adGroupTimesUs[adGroupIndex]; + return adPlaybackState.getAdGroup(adGroupIndex).timeUs; } /** @@ -734,7 +734,7 @@ public long getAdGroupTimeUs(int adGroupIndex) { * if no ads should be played. */ public int getFirstAdIndexToPlay(int adGroupIndex) { - return adPlaybackState.adGroups[adGroupIndex].getFirstAdIndexToPlay(); + return adPlaybackState.getAdGroup(adGroupIndex).getFirstAdIndexToPlay(); } /** @@ -748,17 +748,19 @@ public int getFirstAdIndexToPlay(int adGroupIndex) { * if the ad group does not have any ads remaining to play. */ public int getNextAdIndexToPlay(int adGroupIndex, int lastPlayedAdIndex) { - return adPlaybackState.adGroups[adGroupIndex].getNextAdIndexToPlay(lastPlayedAdIndex); + return adPlaybackState.getAdGroup(adGroupIndex).getNextAdIndexToPlay(lastPlayedAdIndex); } /** - * Returns whether the ad group at index {@code adGroupIndex} has been played. + * Returns whether all ads in the ad group at index {@code adGroupIndex} have been played, + * skipped or failed. * * @param adGroupIndex The ad group index. - * @return Whether the ad group at index {@code adGroupIndex} has been played. + * @return Whether all ads in the ad group at index {@code adGroupIndex} have been played, + * skipped or failed. */ public boolean hasPlayedAdGroup(int adGroupIndex) { - return !adPlaybackState.adGroups[adGroupIndex].hasUnplayedAds(); + return !adPlaybackState.getAdGroup(adGroupIndex).hasUnplayedAds(); } /** @@ -787,26 +789,26 @@ public int getAdGroupIndexAfterPositionUs(long positionUs) { } /** - * Returns the number of ads in the ad group at index {@code adGroupIndex}, or - * {@link C#LENGTH_UNSET} if not yet known. + * Returns the number of ads in the ad group at index {@code adGroupIndex}, or {@link + * C#LENGTH_UNSET} if not yet known. * * @param adGroupIndex The ad group index. * @return The number of ads in the ad group, or {@link C#LENGTH_UNSET} if not yet known. */ public int getAdCountInAdGroup(int adGroupIndex) { - return adPlaybackState.adGroups[adGroupIndex].count; + return adPlaybackState.getAdGroup(adGroupIndex).count; } /** - * Returns the duration of the ad at index {@code adIndexInAdGroup} in the ad group at - * {@code adGroupIndex}, in microseconds, or {@link C#TIME_UNSET} if not yet known. + * Returns the duration of the ad at index {@code adIndexInAdGroup} in the ad group at {@code + * adGroupIndex}, in microseconds, or {@link C#TIME_UNSET} if not yet known. * * @param adGroupIndex The ad group index. * @param adIndexInAdGroup The ad index in the ad group. * @return The duration of the ad, or {@link C#TIME_UNSET} if not yet known. */ public long getAdDurationUs(int adGroupIndex, int adIndexInAdGroup) { - AdPlaybackState.AdGroup adGroup = adPlaybackState.adGroups[adGroupIndex]; + AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(adGroupIndex); return adGroup.count != C.LENGTH_UNSET ? adGroup.durationsUs[adIndexInAdGroup] : C.TIME_UNSET; } @@ -818,6 +820,28 @@ public long getAdResumePositionUs() { return adPlaybackState.adResumePositionUs; } + /** + * Returns whether the ad group at index {@code adGroupIndex} is server-side inserted and part + * of the content stream. + * + * @param adGroupIndex The ad group index. + * @return Whether this ad group is server-side inserted and part of the content stream. + */ + public boolean isServerSideInsertedAdGroup(int adGroupIndex) { + return adPlaybackState.getAdGroup(adGroupIndex).isServerSideInserted; + } + + /** + * Returns the offset in microseconds which should be added to the content stream when resuming + * playback after the specified ad group. + * + * @param adGroupIndex The ad group index. + * @return The offset that should be added to the content stream, in microseconds. + */ + public long getContentResumeOffsetUs(int adGroupIndex) { + return adPlaybackState.getAdGroup(adGroupIndex).contentResumeOffsetUs; + } + @Override public boolean equals(@Nullable Object obj) { if (this == obj) { @@ -959,16 +983,12 @@ public Object getUidOfPeriod(int periodIndex) { } }; - /** - * Returns whether the timeline is empty. - */ + /** Returns whether the timeline is empty. */ public final boolean isEmpty() { return getWindowCount() == 0; } - /** - * Returns the number of windows in the timeline. - */ + /** Returns the number of windows in the timeline. */ public abstract int getWindowCount(); /** @@ -984,13 +1004,15 @@ public int getNextWindowIndex( int windowIndex, @Player.RepeatMode int repeatMode, boolean shuffleModeEnabled) { switch (repeatMode) { case Player.REPEAT_MODE_OFF: - return windowIndex == getLastWindowIndex(shuffleModeEnabled) ? C.INDEX_UNSET + return windowIndex == getLastWindowIndex(shuffleModeEnabled) + ? C.INDEX_UNSET : windowIndex + 1; case Player.REPEAT_MODE_ONE: return windowIndex; case Player.REPEAT_MODE_ALL: return windowIndex == getLastWindowIndex(shuffleModeEnabled) - ? getFirstWindowIndex(shuffleModeEnabled) : windowIndex + 1; + ? getFirstWindowIndex(shuffleModeEnabled) + : windowIndex + 1; default: throw new IllegalStateException(); } @@ -1009,13 +1031,15 @@ public int getPreviousWindowIndex( int windowIndex, @Player.RepeatMode int repeatMode, boolean shuffleModeEnabled) { switch (repeatMode) { case Player.REPEAT_MODE_OFF: - return windowIndex == getFirstWindowIndex(shuffleModeEnabled) ? C.INDEX_UNSET + return windowIndex == getFirstWindowIndex(shuffleModeEnabled) + ? C.INDEX_UNSET : windowIndex - 1; case Player.REPEAT_MODE_ONE: return windowIndex; case Player.REPEAT_MODE_ALL: return windowIndex == getFirstWindowIndex(shuffleModeEnabled) - ? getLastWindowIndex(shuffleModeEnabled) : windowIndex - 1; + ? getLastWindowIndex(shuffleModeEnabled) + : windowIndex - 1; default: throw new IllegalStateException(); } @@ -1056,12 +1080,6 @@ public final Window getWindow(int windowIndex, Window window) { return getWindow(windowIndex, window, /* defaultPositionProjectionUs= */ 0); } - /** @deprecated Use {@link #getWindow(int, Window)} instead. Tags will always be set. */ - @Deprecated - public final Window getWindow(int windowIndex, Window window, boolean setTag) { - return getWindow(windowIndex, window, /* defaultPositionProjectionUs= */ 0); - } - /** * Populates a {@link Window} with data for the window at the specified index. * @@ -1074,9 +1092,7 @@ public final Window getWindow(int windowIndex, Window window, boolean setTag) { public abstract Window getWindow( int windowIndex, Window window, long defaultPositionProjectionUs); - /** - * Returns the number of periods in the timeline. - */ + /** Returns the number of periods in the timeline. */ public abstract int getPeriodCount(); /** @@ -1299,14 +1315,17 @@ public int hashCode() { *

        The {@link #getWindow(int, Window)} windows} and {@link #getPeriod(int, Period) periods} of * an instance restored by {@link #CREATOR} may have missing fields as described in {@link * Window#toBundle()} and {@link Period#toBundle()}. + * + * @param excludeMediaItems Whether to exclude all {@link Window#mediaItem media items} of windows + * in the timeline. */ - @Override - public final Bundle toBundle() { + public final Bundle toBundle(boolean excludeMediaItems) { List windowBundles = new ArrayList<>(); int windowCount = getWindowCount(); Window window = new Window(); for (int i = 0; i < windowCount; i++) { - windowBundles.add(getWindow(i, window, /* defaultPositionProjectionUs= */ 0).toBundle()); + windowBundles.add( + getWindow(i, window, /* defaultPositionProjectionUs= */ 0).toBundle(excludeMediaItems)); } List periodBundles = new ArrayList<>(); @@ -1335,6 +1354,18 @@ public final Bundle toBundle() { return bundle; } + /** + * {@inheritDoc} + * + *

        The {@link #getWindow(int, Window)} windows} and {@link #getPeriod(int, Period) periods} of + * an instance restored by {@link #CREATOR} may have missing fields as described in {@link + * Window#toBundle()} and {@link Period#toBundle()}. + */ + @Override + public final Bundle toBundle() { + return toBundle(/* excludeMediaItems= */ false); + } + /** * Object that can restore a {@link Timeline} from a {@link Bundle}. * @@ -1390,7 +1421,7 @@ private static int[] generateUnshuffledIndices(int n) { * A concrete class of {@link Timeline} to restore a {@link Timeline} instance from a {@link * Bundle} sent by another process via {@link IBinder}. */ - private static final class RemotableTimeline extends Timeline { + public static final class RemotableTimeline extends Timeline { private final ImmutableList windows; private final ImmutableList periods; @@ -1415,8 +1446,7 @@ public int getWindowCount() { } @Override - public Window getWindow( - int windowIndex, Window window, long ignoredDefaultPositionProjectionUs) { + public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) { Window w = windows.get(windowIndex); window.set( w.uid, @@ -1493,7 +1523,7 @@ public int getPeriodCount() { } @Override - public Period getPeriod(int periodIndex, Period period, boolean ignoredSetIds) { + public Period getPeriod(int periodIndex, Period period, boolean setIds) { Period p = periods.get(periodIndex); period.set( p.id, diff --git a/library/common/src/main/java/com/google/android/exoplayer2/audio/AacUtil.java b/library/common/src/main/java/com/google/android/exoplayer2/audio/AacUtil.java index c97893b4280..2684273b2ee 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/audio/AacUtil.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/audio/AacUtil.java @@ -229,7 +229,8 @@ public static Config parseAudioSpecificConfig(ParsableBitArray bitArray, boolean parseGaSpecificConfig(bitArray, audioObjectType, channelConfiguration); break; default: - throw new ParserException("Unsupported audio object type: " + audioObjectType); + throw ParserException.createForUnsupportedContainerFeature( + "Unsupported audio object type: " + audioObjectType); } switch (audioObjectType) { case 17: @@ -240,7 +241,8 @@ public static Config parseAudioSpecificConfig(ParsableBitArray bitArray, boolean case 23: int epConfig = bitArray.readBits(2); if (epConfig == 2 || epConfig == 3) { - throw new ParserException("Unsupported epConfig: " + epConfig); + throw ParserException.createForUnsupportedContainerFeature( + "Unsupported epConfig: " + epConfig); } break; default: @@ -250,7 +252,7 @@ public static Config parseAudioSpecificConfig(ParsableBitArray bitArray, boolean // For supported containers, bits_to_decode() is always 0. int channelCount = AUDIO_SPECIFIC_CONFIG_CHANNEL_COUNT_TABLE[channelConfiguration]; if (channelCount == AUDIO_SPECIFIC_CONFIG_CHANNEL_CONFIGURATION_INVALID) { - throw new ParserException(); + throw ParserException.createForMalformedContainer(/* message= */ null, /* cause= */ null); } return new Config(sampleRateHz, channelCount, codecs); } @@ -349,7 +351,7 @@ private static int getSamplingFrequency(ParsableBitArray bitArray) throws Parser } else if (frequencyIndex < 13) { samplingFrequency = AUDIO_SPECIFIC_CONFIG_SAMPLING_RATE_TABLE[frequencyIndex]; } else { - throw new ParserException(); + throw ParserException.createForMalformedContainer(/* message= */ null, /* cause= */ null); } return samplingFrequency; } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java b/library/common/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java index 8cbd53d1b73..dbb234c5d8b 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java @@ -66,21 +66,13 @@ public static final class SyncFrameInfo { * #STREAM_TYPE_UNDEFINED} otherwise. */ public final @StreamType int streamType; - /** - * The audio sampling rate in Hz. - */ + /** The audio sampling rate in Hz. */ public final int sampleRate; - /** - * The number of audio channels - */ + /** The number of audio channels */ public final int channelCount; - /** - * The size of the frame. - */ + /** The size of the frame. */ public final int frameSize; - /** - * Number of audio samples in the frame. - */ + /** Number of audio samples in the frame. */ public final int sampleCount; private SyncFrameInfo( @@ -97,16 +89,15 @@ private SyncFrameInfo( this.frameSize = frameSize; this.sampleCount = sampleCount; } - } /** - * A non-standard codec string for E-AC-3. Use of this constant allows for disambiguation between - * regular AC-3 ("ec-3") and E-AC-3 ("ec+3") streams from the codec string alone. The standard is - * to use "ec-3" for both, as per the MP4RA registered codec - * types. + * A non-standard codec string for E-AC3-JOC. Use of this constant allows for disambiguation + * between regular E-AC3 ("ec-3") and E-AC3-JOC ("ec+3") streams from the codec string alone. The + * standard is to use "ec-3" for both, as per the MP4RA + * registered codec types. */ - public static final String E_AC_3_CODEC_STRING = "ec+3"; + public static final String E_AC3_JOC_CODEC_STRING = "ec+3"; /** Maximum rate for an AC-3 audio stream, in bytes per second. */ public static final int AC3_MAX_RATE_BYTES_PER_SECOND = 640 * 1000 / 8; /** Maximum rate for an E-AC-3 audio stream, in bytes per second. */ @@ -125,27 +116,17 @@ private SyncFrameInfo( */ public static final int TRUEHD_SYNCFRAME_PREFIX_LENGTH = 10; - /** - * The number of new samples per (E-)AC-3 audio block. - */ + /** The number of new samples per (E-)AC-3 audio block. */ private static final int AUDIO_SAMPLES_PER_AUDIO_BLOCK = 256; /** Each syncframe has 6 blocks that provide 256 new audio samples. See subsection 4.1. */ private static final int AC3_SYNCFRAME_AUDIO_SAMPLE_COUNT = 6 * AUDIO_SAMPLES_PER_AUDIO_BLOCK; - /** - * Number of audio blocks per E-AC-3 syncframe, indexed by numblkscod. - */ + /** Number of audio blocks per E-AC-3 syncframe, indexed by numblkscod. */ private static final int[] BLOCKS_PER_SYNCFRAME_BY_NUMBLKSCOD = new int[] {1, 2, 3, 6}; - /** - * Sample rates, indexed by fscod. - */ + /** Sample rates, indexed by fscod. */ private static final int[] SAMPLE_RATE_BY_FSCOD = new int[] {48000, 44100, 32000}; - /** - * Sample rates, indexed by fscod2 (E-AC-3). - */ + /** Sample rates, indexed by fscod2 (E-AC-3). */ private static final int[] SAMPLE_RATE_BY_FSCOD2 = new int[] {24000, 22050, 16000}; - /** - * Channel counts, indexed by acmod. - */ + /** Channel counts, indexed by acmod. */ private static final int[] CHANNEL_COUNT_BY_ACMOD = new int[] {2, 1, 2, 3, 3, 4, 4, 5}; /** Nominal bitrates in kbps, indexed by frmsizecod / 2. (See table 4.13.) */ private static final int[] BITRATE_BY_HALF_FRMSIZECOD = @@ -323,7 +304,7 @@ public static SyncFrameInfo parseAc3SyncframeInfo(ParsableBitArray data) { } if (streamType == SyncFrameInfo.STREAM_TYPE_TYPE0) { if (data.readBit()) { // pgmscle - data.skipBits(6); //pgmscl + data.skipBits(6); // pgmscl } if (acmod == 0 && data.readBit()) { // pgmscl2e data.skipBits(6); // pgmscl2 @@ -569,7 +550,9 @@ public static int parseTrueHdSyncframeAudioSampleCount(ByteBuffer buffer, int of private static int getAc3SyncframeSize(int fscod, int frmsizecod) { int halfFrmsizecod = frmsizecod / 2; - if (fscod < 0 || fscod >= SAMPLE_RATE_BY_FSCOD.length || frmsizecod < 0 + if (fscod < 0 + || fscod >= SAMPLE_RATE_BY_FSCOD.length + || frmsizecod < 0 || halfFrmsizecod >= SYNCFRAME_SIZE_WORDS_BY_HALF_FRMSIZECOD_44_1.length) { // Invalid values provided. return C.LENGTH_UNSET; @@ -587,5 +570,4 @@ private static int getAc3SyncframeSize(int fscod, int frmsizecod) { } private Ac3Util() {} - } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/audio/AudioAttributes.java b/library/common/src/main/java/com/google/android/exoplayer2/audio/AudioAttributes.java index b91e642d14d..f503ab53c48 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/audio/AudioAttributes.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/audio/AudioAttributes.java @@ -41,9 +41,7 @@ public final class AudioAttributes implements Bundleable { public static final AudioAttributes DEFAULT = new Builder().build(); - /** - * Builder for {@link AudioAttributes}. - */ + /** Builder for {@link AudioAttributes}. */ public static final class Builder { private @C.AudioContentType int contentType; @@ -64,25 +62,19 @@ public Builder() { allowedCapturePolicy = C.ALLOW_CAPTURE_BY_ALL; } - /** - * @see android.media.AudioAttributes.Builder#setContentType(int) - */ + /** @see android.media.AudioAttributes.Builder#setContentType(int) */ public Builder setContentType(@C.AudioContentType int contentType) { this.contentType = contentType; return this; } - /** - * @see android.media.AudioAttributes.Builder#setFlags(int) - */ + /** @see android.media.AudioAttributes.Builder#setFlags(int) */ public Builder setFlags(@C.AudioFlags int flags) { this.flags = flags; return this; } - /** - * @see android.media.AudioAttributes.Builder#setUsage(int) - */ + /** @see android.media.AudioAttributes.Builder#setUsage(int) */ public Builder setUsage(@C.AudioUsage int usage) { this.usage = usage; return this; @@ -98,7 +90,6 @@ public Builder setAllowedCapturePolicy(@C.AudioAllowedCapturePolicy int allowedC public AudioAttributes build() { return new AudioAttributes(contentType, flags, usage, allowedCapturePolicy); } - } public final @C.AudioContentType int contentType; diff --git a/library/common/src/main/java/com/google/android/exoplayer2/audio/DtsUtil.java b/library/common/src/main/java/com/google/android/exoplayer2/audio/DtsUtil.java index 3a0f0e093d9..1a741d47d58 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/audio/DtsUtil.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/audio/DtsUtil.java @@ -44,24 +44,22 @@ public final class DtsUtil { private static final byte FIRST_BYTE_LE = (byte) (SYNC_VALUE_LE >>> 24); private static final byte FIRST_BYTE_14B_LE = (byte) (SYNC_VALUE_14B_LE >>> 24); - /** - * Maps AMODE to the number of channels. See ETSI TS 102 114 table 5.4. - */ - private static final int[] CHANNELS_BY_AMODE = new int[] {1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6, 6, - 7, 8, 8}; - - /** - * Maps SFREQ to the sampling frequency in Hz. See ETSI TS 102 144 table 5.5. - */ - private static final int[] SAMPLE_RATE_BY_SFREQ = new int[] {-1, 8000, 16000, 32000, -1, -1, - 11025, 22050, 44100, -1, -1, 12000, 24000, 48000, -1, -1}; - - /** - * Maps RATE to 2 * bitrate in kbit/s. See ETSI TS 102 144 table 5.7. - */ - private static final int[] TWICE_BITRATE_KBPS_BY_RATE = new int[] {64, 112, 128, 192, 224, 256, - 384, 448, 512, 640, 768, 896, 1024, 1152, 1280, 1536, 1920, 2048, 2304, 2560, 2688, 2816, - 2823, 2944, 3072, 3840, 4096, 6144, 7680}; + /** Maps AMODE to the number of channels. See ETSI TS 102 114 table 5.4. */ + private static final int[] CHANNELS_BY_AMODE = + new int[] {1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6, 6, 7, 8, 8}; + + /** Maps SFREQ to the sampling frequency in Hz. See ETSI TS 102 144 table 5.5. */ + private static final int[] SAMPLE_RATE_BY_SFREQ = + new int[] { + -1, 8000, 16000, 32000, -1, -1, 11025, 22050, 44100, -1, -1, 12000, 24000, 48000, -1, -1 + }; + + /** Maps RATE to 2 * bitrate in kbit/s. See ETSI TS 102 144 table 5.7. */ + private static final int[] TWICE_BITRATE_KBPS_BY_RATE = + new int[] { + 64, 112, 128, 192, 224, 256, 384, 448, 512, 640, 768, 896, 1024, 1152, 1280, 1536, 1920, + 2048, 2304, 2560, 2688, 2816, 2823, 2944, 3072, 3840, 4096, 6144, 7680 + }; /** * Returns whether a given integer matches a DTS sync word. Synchronization and storage modes are @@ -99,8 +97,10 @@ public static Format parseDtsFormat( int sfreq = frameBits.readBits(4); int sampleRate = SAMPLE_RATE_BY_SFREQ[sfreq]; int rate = frameBits.readBits(5); - int bitrate = rate >= TWICE_BITRATE_KBPS_BY_RATE.length ? Format.NO_VALUE - : TWICE_BITRATE_KBPS_BY_RATE[rate] * 1000 / 2; + int bitrate = + rate >= TWICE_BITRATE_KBPS_BY_RATE.length + ? Format.NO_VALUE + : TWICE_BITRATE_KBPS_BY_RATE[rate] * 1000 / 2; frameBits.skipBits(10); // MIX, DYNF, TIMEF, AUXF, HDCD, EXT_AUDIO_ID, EXT_AUDIO, ASPF channelCount += frameBits.readBits(2) > 0 ? 1 : 0; // LFF return new Format.Builder() @@ -230,5 +230,4 @@ private static boolean isLittleEndianFrameHeader(byte[] frameHeader) { } private DtsUtil() {} - } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/decoder/Buffer.java b/library/common/src/main/java/com/google/android/exoplayer2/decoder/Buffer.java index 6d74bf820e3..71ea215d2c3 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/decoder/Buffer.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/decoder/Buffer.java @@ -20,33 +20,24 @@ /** Base class for buffers with flags. */ public abstract class Buffer { - @C.BufferFlags - private int flags; + @C.BufferFlags private int flags; - /** - * Clears the buffer. - */ + /** Clears the buffer. */ public void clear() { flags = 0; } - /** - * Returns whether the {@link C#BUFFER_FLAG_DECODE_ONLY} flag is set. - */ + /** Returns whether the {@link C#BUFFER_FLAG_DECODE_ONLY} flag is set. */ public final boolean isDecodeOnly() { return getFlag(C.BUFFER_FLAG_DECODE_ONLY); } - /** - * Returns whether the {@link C#BUFFER_FLAG_END_OF_STREAM} flag is set. - */ + /** Returns whether the {@link C#BUFFER_FLAG_END_OF_STREAM} flag is set. */ public final boolean isEndOfStream() { return getFlag(C.BUFFER_FLAG_END_OF_STREAM); } - /** - * Returns whether the {@link C#BUFFER_FLAG_KEY_FRAME} flag is set. - */ + /** Returns whether the {@link C#BUFFER_FLAG_KEY_FRAME} flag is set. */ public final boolean isKeyFrame() { return getFlag(C.BUFFER_FLAG_KEY_FRAME); } @@ -69,8 +60,8 @@ public final void setFlags(@C.BufferFlags int flags) { /** * Adds the {@code flag} to this buffer's flags. * - * @param flag The flag to add to this buffer's flags, which should be one of the - * {@code C.BUFFER_FLAG_*} constants. + * @param flag The flag to add to this buffer's flags, which should be one of the {@code + * C.BUFFER_FLAG_*} constants. */ public final void addFlag(@C.BufferFlags int flag) { flags |= flag; @@ -94,5 +85,4 @@ public final void clearFlag(@C.BufferFlags int flag) { protected final boolean getFlag(@C.BufferFlags int flag) { return (flags & flag) == flag; } - } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/decoder/CryptoInfo.java b/library/common/src/main/java/com/google/android/exoplayer2/decoder/CryptoInfo.java index 80486feb91c..b4e04afe424 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/decoder/CryptoInfo.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/decoder/CryptoInfo.java @@ -63,13 +63,9 @@ public final class CryptoInfo { * @see android.media.MediaCodec.CryptoInfo#numSubSamples */ public int numSubSamples; - /** - * @see android.media.MediaCodec.CryptoInfo.Pattern - */ + /** @see android.media.MediaCodec.CryptoInfo.Pattern */ public int encryptedBlocks; - /** - * @see android.media.MediaCodec.CryptoInfo.Pattern - */ + /** @see android.media.MediaCodec.CryptoInfo.Pattern */ public int clearBlocks; private final android.media.MediaCodec.CryptoInfo frameworkCryptoInfo; @@ -80,11 +76,16 @@ public CryptoInfo() { patternHolder = Util.SDK_INT >= 24 ? new PatternHolderV24(frameworkCryptoInfo) : null; } - /** - * @see android.media.MediaCodec.CryptoInfo#set(int, int[], int[], byte[], byte[], int) - */ - public void set(int numSubSamples, int[] numBytesOfClearData, int[] numBytesOfEncryptedData, - byte[] key, byte[] iv, @C.CryptoMode int mode, int encryptedBlocks, int clearBlocks) { + /** @see android.media.MediaCodec.CryptoInfo#set(int, int[], int[], byte[], byte[], int) */ + public void set( + int numSubSamples, + int[] numBytesOfClearData, + int[] numBytesOfEncryptedData, + byte[] key, + byte[] iv, + @C.CryptoMode int mode, + int encryptedBlocks, + int clearBlocks) { this.numSubSamples = numSubSamples; this.numBytesOfClearData = numBytesOfClearData; this.numBytesOfEncryptedData = numBytesOfEncryptedData; @@ -157,7 +158,5 @@ private void set(int encryptedBlocks, int clearBlocks) { pattern.set(encryptedBlocks, clearBlocks); frameworkCryptoInfo.setPattern(pattern); } - } - } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/decoder/DecoderInputBuffer.java b/library/common/src/main/java/com/google/android/exoplayer2/decoder/DecoderInputBuffer.java index ff295657e10..71b3a68d192 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/decoder/DecoderInputBuffer.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/decoder/DecoderInputBuffer.java @@ -66,22 +66,14 @@ public InsufficientCapacityException(int currentCapacity, int requiredCapacity) BUFFER_REPLACEMENT_MODE_DIRECT }) public @interface BufferReplacementMode {} - /** - * Disallows buffer replacement. - */ + /** Disallows buffer replacement. */ public static final int BUFFER_REPLACEMENT_MODE_DISABLED = 0; - /** - * Allows buffer replacement using {@link ByteBuffer#allocate(int)}. - */ + /** Allows buffer replacement using {@link ByteBuffer#allocate(int)}. */ public static final int BUFFER_REPLACEMENT_MODE_NORMAL = 1; - /** - * Allows buffer replacement using {@link ByteBuffer#allocateDirect(int)}. - */ + /** Allows buffer replacement using {@link ByteBuffer#allocateDirect(int)}. */ public static final int BUFFER_REPLACEMENT_MODE_DIRECT = 2; - /** - * {@link CryptoInfo} for encrypted data. - */ + /** {@link CryptoInfo} for encrypted data. */ public final CryptoInfo cryptoInfo; /** The buffer's data, or {@code null} if no data has been set. */ @@ -95,9 +87,7 @@ public InsufficientCapacityException(int currentCapacity, int requiredCapacity) */ public boolean waitingForKeys; - /** - * The time at which the sample should be presented. - */ + /** The time at which the sample should be presented. */ public long timeUs; /** @@ -194,9 +184,7 @@ public void ensureSpaceForWrite(int length) { data = newData; } - /** - * Returns whether the {@link C#BUFFER_FLAG_ENCRYPTED} flag is set. - */ + /** Returns whether the {@link C#BUFFER_FLAG_ENCRYPTED} flag is set. */ public final boolean isEncrypted() { return getFlag(C.BUFFER_FLAG_ENCRYPTED); } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/drm/DrmInitData.java b/library/common/src/main/java/com/google/android/exoplayer2/drm/DrmInitData.java index 4113f4c27d1..5c366ef9e25 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/drm/DrmInitData.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/drm/DrmInitData.java @@ -87,14 +87,10 @@ public final class DrmInitData implements Comparator, Parcelable { /** The protection scheme type, or null if not applicable or unknown. */ @Nullable public final String schemeType; - /** - * Number of {@link SchemeData}s. - */ + /** Number of {@link SchemeData}s. */ public final int schemeDataCount; - /** - * @param schemeDatas Scheme initialization data for possibly multiple DRM schemes. - */ + /** @param schemeDatas Scheme initialization data for possibly multiple DRM schemes. */ public DrmInitData(List schemeDatas) { this(null, false, schemeDatas.toArray(new SchemeData[0])); } @@ -107,9 +103,7 @@ public DrmInitData(@Nullable String schemeType, List schemeDatas) { this(schemeType, false, schemeDatas.toArray(new SchemeData[0])); } - /** - * @param schemeDatas Scheme initialization data for possibly multiple DRM schemes. - */ + /** @param schemeDatas Scheme initialization data for possibly multiple DRM schemes. */ public DrmInitData(SchemeData... schemeDatas) { this(null, schemeDatas); } @@ -122,8 +116,8 @@ public DrmInitData(@Nullable String schemeType, SchemeData... schemeDatas) { this(schemeType, true, schemeDatas); } - private DrmInitData(@Nullable String schemeType, boolean cloneSchemeDatas, - SchemeData... schemeDatas) { + private DrmInitData( + @Nullable String schemeType, boolean cloneSchemeDatas, SchemeData... schemeDatas) { this.schemeType = schemeType; if (cloneSchemeDatas) { schemeDatas = schemeDatas.clone(); @@ -208,7 +202,8 @@ public boolean equals(@Nullable Object obj) { @Override public int compare(SchemeData first, SchemeData second) { - return C.UUID_NIL.equals(first.uuid) ? (C.UUID_NIL.equals(second.uuid) ? 0 : 1) + return C.UUID_NIL.equals(first.uuid) + ? (C.UUID_NIL.equals(second.uuid) ? 0 : 1) : first.uuid.compareTo(second.uuid); } @@ -228,17 +223,16 @@ public void writeToParcel(Parcel dest, int flags) { public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override - public DrmInitData createFromParcel(Parcel in) { - return new DrmInitData(in); - } - - @Override - public DrmInitData[] newArray(int size) { - return new DrmInitData[size]; - } + @Override + public DrmInitData createFromParcel(Parcel in) { + return new DrmInitData(in); + } - }; + @Override + public DrmInitData[] newArray(int size) { + return new DrmInitData[size]; + } + }; // Internal methods. @@ -252,9 +246,7 @@ private static boolean containsSchemeDataWithUuid( return false; } - /** - * Scheme initialization data. - */ + /** Scheme initialization data. */ public static final class SchemeData implements Parcelable { // Lazily initialized hashcode. @@ -324,9 +316,7 @@ public boolean canReplace(SchemeData other) { return hasData() && !other.hasData() && matches(other.uuid); } - /** - * Returns whether {@link #data} is non-null. - */ + /** Returns whether {@link #data} is non-null. */ public boolean hasData() { return data != null; } @@ -387,18 +377,15 @@ public void writeToParcel(Parcel dest, int flags) { public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override - public SchemeData createFromParcel(Parcel in) { - return new SchemeData(in); - } - - @Override - public SchemeData[] newArray(int size) { - return new SchemeData[size]; - } - - }; + @Override + public SchemeData createFromParcel(Parcel in) { + return new SchemeData(in); + } + @Override + public SchemeData[] newArray(int size) { + return new SchemeData[size]; + } + }; } - } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/metadata/Metadata.java b/library/common/src/main/java/com/google/android/exoplayer2/metadata/Metadata.java index 01ae3406098..ffa837deffe 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/metadata/Metadata.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/metadata/Metadata.java @@ -62,16 +62,12 @@ default void populateMediaMetadata(MediaMetadata.Builder builder) {} private final Entry[] entries; - /** - * @param entries The metadata entries. - */ + /** @param entries The metadata entries. */ public Metadata(Entry... entries) { this.entries = entries; } - /** - * @param entries The metadata entries. - */ + /** @param entries The metadata entries. */ public Metadata(List entries) { this.entries = entries.toArray(new Entry[0]); } @@ -83,9 +79,7 @@ public Metadata(List entries) { } } - /** - * Returns the number of metadata entries. - */ + /** Returns the number of metadata entries. */ public int length() { return entries.length; } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/metadata/MetadataInputBuffer.java b/library/common/src/main/java/com/google/android/exoplayer2/metadata/MetadataInputBuffer.java index 55e0b75f716..0ce9eb616b1 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/metadata/MetadataInputBuffer.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/metadata/MetadataInputBuffer.java @@ -22,13 +22,12 @@ public final class MetadataInputBuffer extends DecoderInputBuffer { /** - * An offset that must be added to the metadata's timestamps after it's been decoded, or - * {@link Format#OFFSET_SAMPLE_RELATIVE} if {@link #timeUs} should be added. + * An offset that must be added to the metadata's timestamps after it's been decoded, or {@link + * Format#OFFSET_SAMPLE_RELATIVE} if {@link #timeUs} should be added. */ public long subsampleOffsetUs; public MetadataInputBuffer() { super(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL); } - } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessage.java b/library/common/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessage.java index 0dd46bae224..8f8046d7e29 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessage.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessage.java @@ -57,24 +57,16 @@ public final class EventMessage implements Metadata.Entry { /** The message scheme. */ public final String schemeIdUri; - /** - * The value for the event. - */ + /** The value for the event. */ public final String value; - /** - * The duration of the event in milliseconds. - */ + /** The duration of the event in milliseconds. */ public final long durationMs; - /** - * The instance identifier. - */ + /** The instance identifier. */ public final long id; - /** - * The body of the message. - */ + /** The body of the message. */ public final byte[] messageData; // Lazily initialized hashcode. @@ -185,16 +177,14 @@ public void writeToParcel(Parcel dest, int flags) { public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override - public EventMessage createFromParcel(Parcel in) { - return new EventMessage(in); - } - - @Override - public EventMessage[] newArray(int size) { - return new EventMessage[size]; - } - - }; + @Override + public EventMessage createFromParcel(Parcel in) { + return new EventMessage(in); + } + @Override + public EventMessage[] newArray(int size) { + return new EventMessage[size]; + } + }; } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/metadata/flac/PictureFrame.java b/library/common/src/main/java/com/google/android/exoplayer2/metadata/flac/PictureFrame.java index ce134614ad1..8d62be52c67 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/metadata/flac/PictureFrame.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/metadata/flac/PictureFrame.java @@ -20,6 +20,7 @@ import android.os.Parcel; import android.os.Parcelable; import androidx.annotation.Nullable; +import com.google.android.exoplayer2.MediaMetadata; import com.google.android.exoplayer2.metadata.Metadata; import java.util.Arrays; @@ -73,6 +74,11 @@ public PictureFrame( this.pictureData = castNonNull(in.createByteArray()); } + @Override + public void populateMediaMetadata(MediaMetadata.Builder builder) { + builder.maybeSetArtworkData(pictureData, pictureType); + } + @Override public String toString() { return "Picture: mimeType=" + mimeType + ", description=" + description; diff --git a/library/common/src/main/java/com/google/android/exoplayer2/metadata/flac/VorbisComment.java b/library/common/src/main/java/com/google/android/exoplayer2/metadata/flac/VorbisComment.java index 9f44cdf393d..3ab60541a99 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/metadata/flac/VorbisComment.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/metadata/flac/VorbisComment.java @@ -20,6 +20,7 @@ import android.os.Parcel; import android.os.Parcelable; import androidx.annotation.Nullable; +import com.google.android.exoplayer2.MediaMetadata; import com.google.android.exoplayer2.metadata.Metadata; /** A vorbis comment. */ @@ -45,6 +46,29 @@ public VorbisComment(String key, String value) { this.value = castNonNull(in.readString()); } + @Override + public void populateMediaMetadata(MediaMetadata.Builder builder) { + switch (key) { + case "TITLE": + builder.setTitle(value); + break; + case "ARTIST": + builder.setArtist(value); + break; + case "ALBUM": + builder.setAlbumTitle(value); + break; + case "ALBUMARTIST": + builder.setAlbumArtist(value); + break; + case "DESCRIPTION": + builder.setDescription(value); + break; + default: + break; + } + } + @Override public String toString() { return "VC: " + key + "=" + value; diff --git a/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/ApicFrame.java b/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/ApicFrame.java index 25efeba0769..84d426c6b9f 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/ApicFrame.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/ApicFrame.java @@ -53,7 +53,7 @@ public ApicFrame( @Override public void populateMediaMetadata(MediaMetadata.Builder builder) { - builder.setArtworkData(pictureData); + builder.maybeSetArtworkData(pictureData, pictureType); } @Override @@ -65,7 +65,8 @@ public boolean equals(@Nullable Object obj) { return false; } ApicFrame other = (ApicFrame) obj; - return pictureType == other.pictureType && Util.areEqual(mimeType, other.mimeType) + return pictureType == other.pictureType + && Util.areEqual(mimeType, other.mimeType) && Util.areEqual(description, other.description) && Arrays.equals(pictureData, other.pictureData); } @@ -95,18 +96,17 @@ public void writeToParcel(Parcel dest, int flags) { dest.writeByteArray(pictureData); } - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { - @Override - public ApicFrame createFromParcel(Parcel in) { - return new ApicFrame(in); - } - - @Override - public ApicFrame[] newArray(int size) { - return new ApicFrame[size]; - } - - }; + @Override + public ApicFrame createFromParcel(Parcel in) { + return new ApicFrame(in); + } + @Override + public ApicFrame[] newArray(int size) { + return new ApicFrame[size]; + } + }; } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/BinaryFrame.java b/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/BinaryFrame.java index 995418f3b46..39305404cf6 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/BinaryFrame.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/BinaryFrame.java @@ -75,7 +75,5 @@ public BinaryFrame createFromParcel(Parcel in) { public BinaryFrame[] newArray(int size) { return new BinaryFrame[size]; } - }; - } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterFrame.java b/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterFrame.java index 120b9269f1c..e759a73aacd 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterFrame.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterFrame.java @@ -31,18 +31,20 @@ public final class ChapterFrame extends Id3Frame { public final String chapterId; public final int startTimeMs; public final int endTimeMs; - /** - * The byte offset of the start of the chapter, or {@link C#POSITION_UNSET} if not set. - */ + /** The byte offset of the start of the chapter, or {@link C#POSITION_UNSET} if not set. */ public final long startOffset; - /** - * The byte offset of the end of the chapter, or {@link C#POSITION_UNSET} if not set. - */ + /** The byte offset of the end of the chapter, or {@link C#POSITION_UNSET} if not set. */ public final long endOffset; + private final Id3Frame[] subFrames; - public ChapterFrame(String chapterId, int startTimeMs, int endTimeMs, long startOffset, - long endOffset, Id3Frame[] subFrames) { + public ChapterFrame( + String chapterId, + int startTimeMs, + int endTimeMs, + long startOffset, + long endOffset, + Id3Frame[] subFrames) { super(ID); this.chapterId = chapterId; this.startTimeMs = startTimeMs; @@ -66,16 +68,12 @@ public ChapterFrame(String chapterId, int startTimeMs, int endTimeMs, long start } } - /** - * Returns the number of sub-frames. - */ + /** Returns the number of sub-frames. */ public int getSubFrameCount() { return subFrames.length; } - /** - * Returns the sub-frame at {@code index}. - */ + /** Returns the sub-frame at {@code index}. */ public Id3Frame getSubFrame(int index) { return subFrames[index]; } @@ -126,18 +124,17 @@ public int describeContents() { return 0; } - public static final Creator CREATOR = new Creator() { - - @Override - public ChapterFrame createFromParcel(Parcel in) { - return new ChapterFrame(in); - } - - @Override - public ChapterFrame[] newArray(int size) { - return new ChapterFrame[size]; - } + public static final Creator CREATOR = + new Creator() { - }; + @Override + public ChapterFrame createFromParcel(Parcel in) { + return new ChapterFrame(in); + } + @Override + public ChapterFrame[] newArray(int size) { + return new ChapterFrame[size]; + } + }; } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterTocFrame.java b/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterTocFrame.java index 5e662c388c7..ee7bcd397e8 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterTocFrame.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterTocFrame.java @@ -33,7 +33,11 @@ public final class ChapterTocFrame extends Id3Frame { public final String[] children; private final Id3Frame[] subFrames; - public ChapterTocFrame(String elementId, boolean isRoot, boolean isOrdered, String[] children, + public ChapterTocFrame( + String elementId, + boolean isRoot, + boolean isOrdered, + String[] children, Id3Frame[] subFrames) { super(ID); this.elementId = elementId; @@ -56,16 +60,12 @@ public ChapterTocFrame(String elementId, boolean isRoot, boolean isOrdered, Stri } } - /** - * Returns the number of sub-frames. - */ + /** Returns the number of sub-frames. */ public int getSubFrameCount() { return subFrames.length; } - /** - * Returns the sub-frame at {@code index}. - */ + /** Returns the sub-frame at {@code index}. */ public Id3Frame getSubFrame(int index) { return subFrames[index]; } @@ -107,18 +107,17 @@ public void writeToParcel(Parcel dest, int flags) { } } - public static final Creator CREATOR = new Creator() { + public static final Creator CREATOR = + new Creator() { - @Override - public ChapterTocFrame createFromParcel(Parcel in) { - return new ChapterTocFrame(in); - } - - @Override - public ChapterTocFrame[] newArray(int size) { - return new ChapterTocFrame[size]; - } - - }; + @Override + public ChapterTocFrame createFromParcel(Parcel in) { + return new ChapterTocFrame(in); + } + @Override + public ChapterTocFrame[] newArray(int size) { + return new ChapterTocFrame[size]; + } + }; } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/CommentFrame.java b/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/CommentFrame.java index 8b2d14444d7..5d441e782f3 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/CommentFrame.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/CommentFrame.java @@ -54,7 +54,8 @@ public boolean equals(@Nullable Object obj) { return false; } CommentFrame other = (CommentFrame) obj; - return Util.areEqual(description, other.description) && Util.areEqual(language, other.language) + return Util.areEqual(description, other.description) + && Util.areEqual(language, other.language) && Util.areEqual(text, other.text); } @@ -93,7 +94,5 @@ public CommentFrame createFromParcel(Parcel in) { public CommentFrame[] newArray(int size) { return new CommentFrame[size]; } - }; - } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/GeobFrame.java b/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/GeobFrame.java index c0c8ad631f8..2c609db8d56 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/GeobFrame.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/GeobFrame.java @@ -58,8 +58,10 @@ public boolean equals(@Nullable Object obj) { return false; } GeobFrame other = (GeobFrame) obj; - return Util.areEqual(mimeType, other.mimeType) && Util.areEqual(filename, other.filename) - && Util.areEqual(description, other.description) && Arrays.equals(data, other.data); + return Util.areEqual(mimeType, other.mimeType) + && Util.areEqual(filename, other.filename) + && Util.areEqual(description, other.description) + && Arrays.equals(data, other.data); } @Override @@ -93,18 +95,17 @@ public void writeToParcel(Parcel dest, int flags) { dest.writeByteArray(data); } - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { - @Override - public GeobFrame createFromParcel(Parcel in) { - return new GeobFrame(in); - } - - @Override - public GeobFrame[] newArray(int size) { - return new GeobFrame[size]; - } - - }; + @Override + public GeobFrame createFromParcel(Parcel in) { + return new GeobFrame(in); + } + @Override + public GeobFrame[] newArray(int size) { + return new GeobFrame[size]; + } + }; } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java b/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java index 5bd0e1e3e83..0d97cef846a 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java @@ -35,9 +35,7 @@ /** Decodes ID3 tags. */ public final class Id3Decoder extends SimpleMetadataDecoder { - /** - * A predicate for determining whether individual frames should be decoded. - */ + /** A predicate for determining whether individual frames should be decoded. */ public interface FramePredicate { /** @@ -51,7 +49,6 @@ public interface FramePredicate { * @return Whether the frame should be decoded. */ boolean evaluate(int majorVersion, int id0, int id1, int id2, int id3); - } /** A predicate that indicates no frames should be decoded. */ @@ -62,9 +59,7 @@ public interface FramePredicate { /** The first three bytes of a well formed ID3 tag header. */ public static final int ID3_TAG = 0x00494433; - /** - * Length of an ID3 tag header. - */ + /** Length of an ID3 tag header. */ public static final int ID3_HEADER_LENGTH = 10; private static final int FRAME_FLAG_V3_IS_COMPRESSED = 0x0080; @@ -210,8 +205,11 @@ private static Id3Header decodeHeader(ParsableByteArray data) { return new Id3Header(majorVersion, isUnsynchronized, framesSize); } - private static boolean validateFrames(ParsableByteArray id3Data, int majorVersion, - int frameHeaderSize, boolean unsignedIntFrameSizeHack) { + private static boolean validateFrames( + ParsableByteArray id3Data, + int majorVersion, + int frameHeaderSize, + boolean unsignedIntFrameSizeHack) { int startPosition = id3Data.getPosition(); try { while (id3Data.bytesLeft() >= frameHeaderSize) { @@ -238,8 +236,11 @@ private static boolean validateFrames(ParsableByteArray id3Data, int majorVersio if ((frameSize & 0x808080L) != 0) { return false; } - frameSize = (frameSize & 0xFF) | (((frameSize >> 8) & 0xFF) << 7) - | (((frameSize >> 16) & 0xFF) << 14) | (((frameSize >> 24) & 0xFF) << 21); + frameSize = + (frameSize & 0xFF) + | (((frameSize >> 8) & 0xFF) << 7) + | (((frameSize >> 16) & 0xFF) << 14) + | (((frameSize >> 24) & 0xFF) << 21); } boolean hasGroupIdentifier = false; boolean hasDataLength = false; @@ -289,8 +290,11 @@ private static Id3Frame decodeFrame( if (majorVersion == 4) { frameSize = id3Data.readUnsignedIntToInt(); if (!unsignedIntFrameSizeHack) { - frameSize = (frameSize & 0xFF) | (((frameSize >> 8) & 0xFF) << 7) - | (((frameSize >> 16) & 0xFF) << 14) | (((frameSize >> 24) & 0xFF) << 21); + frameSize = + (frameSize & 0xFF) + | (((frameSize >> 8) & 0xFF) << 7) + | (((frameSize >> 16) & 0xFF) << 14) + | (((frameSize >> 24) & 0xFF) << 21); } } else if (majorVersion == 3) { frameSize = id3Data.readUnsignedIntToInt(); @@ -299,7 +303,11 @@ private static Id3Frame decodeFrame( } int flags = majorVersion >= 3 ? id3Data.readUnsignedShort() : 0; - if (frameId0 == 0 && frameId1 == 0 && frameId2 == 0 && frameId3 == 0 && frameSize == 0 + if (frameId0 == 0 + && frameId1 == 0 + && frameId2 == 0 + && frameId3 == 0 + && frameSize == 0 && flags == 0) { // We must be reading zero padding at the end of the tag. id3Data.setPosition(id3Data.limit()); @@ -360,13 +368,17 @@ private static Id3Frame decodeFrame( try { Id3Frame frame; - if (frameId0 == 'T' && frameId1 == 'X' && frameId2 == 'X' + if (frameId0 == 'T' + && frameId1 == 'X' + && frameId2 == 'X' && (majorVersion == 2 || frameId3 == 'X')) { frame = decodeTxxxFrame(id3Data, frameSize); } else if (frameId0 == 'T') { String id = getFrameId(majorVersion, frameId0, frameId1, frameId2, frameId3); frame = decodeTextInformationFrame(id3Data, frameSize, id); - } else if (frameId0 == 'W' && frameId1 == 'X' && frameId2 == 'X' + } else if (frameId0 == 'W' + && frameId1 == 'X' + && frameId2 == 'X' && (majorVersion == 2 || frameId3 == 'X')) { frame = decodeWxxxFrame(id3Data, frameSize); } else if (frameId0 == 'W') { @@ -374,21 +386,38 @@ private static Id3Frame decodeFrame( frame = decodeUrlLinkFrame(id3Data, frameSize, id); } else if (frameId0 == 'P' && frameId1 == 'R' && frameId2 == 'I' && frameId3 == 'V') { frame = decodePrivFrame(id3Data, frameSize); - } else if (frameId0 == 'G' && frameId1 == 'E' && frameId2 == 'O' + } else if (frameId0 == 'G' + && frameId1 == 'E' + && frameId2 == 'O' && (frameId3 == 'B' || majorVersion == 2)) { frame = decodeGeobFrame(id3Data, frameSize); - } else if (majorVersion == 2 ? (frameId0 == 'P' && frameId1 == 'I' && frameId2 == 'C') + } else if (majorVersion == 2 + ? (frameId0 == 'P' && frameId1 == 'I' && frameId2 == 'C') : (frameId0 == 'A' && frameId1 == 'P' && frameId2 == 'I' && frameId3 == 'C')) { frame = decodeApicFrame(id3Data, frameSize, majorVersion); - } else if (frameId0 == 'C' && frameId1 == 'O' && frameId2 == 'M' + } else if (frameId0 == 'C' + && frameId1 == 'O' + && frameId2 == 'M' && (frameId3 == 'M' || majorVersion == 2)) { frame = decodeCommentFrame(id3Data, frameSize); } else if (frameId0 == 'C' && frameId1 == 'H' && frameId2 == 'A' && frameId3 == 'P') { - frame = decodeChapterFrame(id3Data, frameSize, majorVersion, unsignedIntFrameSizeHack, - frameHeaderSize, framePredicate); + frame = + decodeChapterFrame( + id3Data, + frameSize, + majorVersion, + unsignedIntFrameSizeHack, + frameHeaderSize, + framePredicate); } else if (frameId0 == 'C' && frameId1 == 'T' && frameId2 == 'O' && frameId3 == 'C') { - frame = decodeChapterTOCFrame(id3Data, frameSize, majorVersion, unsignedIntFrameSizeHack, - frameHeaderSize, framePredicate); + frame = + decodeChapterTOCFrame( + id3Data, + frameSize, + majorVersion, + unsignedIntFrameSizeHack, + frameHeaderSize, + framePredicate); } else if (frameId0 == 'M' && frameId1 == 'L' && frameId2 == 'L' && frameId3 == 'T') { frame = decodeMlltFrame(id3Data, frameSize); } else { @@ -396,9 +425,12 @@ private static Id3Frame decodeFrame( frame = decodeBinaryFrame(id3Data, frameSize, id); } if (frame == null) { - Log.w(TAG, "Failed to decode frame: id=" - + getFrameId(majorVersion, frameId0, frameId1, frameId2, frameId3) + ", frameSize=" - + frameSize); + Log.w( + TAG, + "Failed to decode frame: id=" + + getFrameId(majorVersion, frameId0, frameId1, frameId2, frameId3) + + ", frameSize=" + + frameSize); } return frame; } catch (UnsupportedEncodingException e) { @@ -477,8 +509,8 @@ private static UrlLinkFrame decodeWxxxFrame(ParsableByteArray id3Data, int frame return new UrlLinkFrame("WXXX", description, url); } - private static UrlLinkFrame decodeUrlLinkFrame(ParsableByteArray id3Data, int frameSize, - String id) throws UnsupportedEncodingException { + private static UrlLinkFrame decodeUrlLinkFrame( + ParsableByteArray id3Data, int frameSize, String id) throws UnsupportedEncodingException { byte[] data = new byte[frameSize]; id3Data.readBytes(data, 0, frameSize); @@ -528,8 +560,9 @@ private static GeobFrame decodeGeobFrame(ParsableByteArray id3Data, int frameSiz return new GeobFrame(mimeType, filename, description, objectData); } - private static ApicFrame decodeApicFrame(ParsableByteArray id3Data, int frameSize, - int majorVersion) throws UnsupportedEncodingException { + private static ApicFrame decodeApicFrame( + ParsableByteArray id3Data, int frameSize, int majorVersion) + throws UnsupportedEncodingException { int encoding = id3Data.readUnsignedByte(); String charset = getCharsetName(encoding); @@ -556,8 +589,9 @@ private static ApicFrame decodeApicFrame(ParsableByteArray id3Data, int frameSiz int descriptionStartIndex = mimeTypeEndIndex + 2; int descriptionEndIndex = indexOfEos(data, descriptionStartIndex, encoding); - String description = new String(data, descriptionStartIndex, - descriptionEndIndex - descriptionStartIndex, charset); + String description = + new String( + data, descriptionStartIndex, descriptionEndIndex - descriptionStartIndex, charset); int pictureDataStartIndex = descriptionEndIndex + delimiterLength(encoding); byte[] pictureData = copyOfRangeIfValid(data, pictureDataStartIndex, data.length); @@ -622,8 +656,9 @@ private static ChapterFrame decodeChapterFrame( ArrayList subFrames = new ArrayList<>(); int limit = framePosition + frameSize; while (id3Data.getPosition() < limit) { - Id3Frame frame = decodeFrame(majorVersion, id3Data, unsignedIntFrameSizeHack, - frameHeaderSize, framePredicate); + Id3Frame frame = + decodeFrame( + majorVersion, id3Data, unsignedIntFrameSizeHack, frameHeaderSize, framePredicate); if (frame != null) { subFrames.add(frame); } @@ -707,8 +742,8 @@ private static MlltFrame decodeMlltFrame(ParsableByteArray id3Data, int frameSiz millisecondsDeviations); } - private static BinaryFrame decodeBinaryFrame(ParsableByteArray id3Data, int frameSize, - String id) { + private static BinaryFrame decodeBinaryFrame( + ParsableByteArray id3Data, int frameSize, String id) { byte[] frame = new byte[frameSize]; id3Data.readBytes(frame, 0, frameSize); @@ -716,8 +751,8 @@ private static BinaryFrame decodeBinaryFrame(ParsableByteArray id3Data, int fram } /** - * Performs in-place removal of unsynchronization for {@code length} bytes starting from - * {@link ParsableByteArray#getPosition()} + * Performs in-place removal of unsynchronization for {@code length} bytes starting from {@link + * ParsableByteArray#getPosition()} * * @param data Contains the data to be processed. * @param length The length of the data to be processed. @@ -756,9 +791,10 @@ private static String getCharsetName(int encodingByte) { } } - private static String getFrameId(int majorVersion, int frameId0, int frameId1, int frameId2, - int frameId3) { - return majorVersion == 2 ? String.format(Locale.US, "%c%c%c", frameId0, frameId1, frameId2) + private static String getFrameId( + int majorVersion, int frameId0, int frameId1, int frameId2, int frameId3) { + return majorVersion == 2 + ? String.format(Locale.US, "%c%c%c", frameId0, frameId1, frameId2) : String.format(Locale.US, "%c%c%c%c", frameId0, frameId1, frameId2, frameId3); } @@ -792,7 +828,8 @@ private static int indexOfZeroByte(byte[] data, int fromIndex) { private static int delimiterLength(int encodingByte) { return (encodingByte == ID3_TEXT_ENCODING_ISO_8859_1 || encodingByte == ID3_TEXT_ENCODING_UTF_8) - ? 1 : 2; + ? 1 + : 2; } /** @@ -841,7 +878,5 @@ public Id3Header(int majorVersion, boolean isUnsynchronized, int framesSize) { this.isUnsynchronized = isUnsynchronized; this.framesSize = framesSize; } - } - } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Frame.java b/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Frame.java index 24e11888798..e54de84f58c 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Frame.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Frame.java @@ -20,9 +20,7 @@ /** Base class for ID3 frames. */ public abstract class Id3Frame implements Metadata.Entry { - /** - * The frame ID. - */ + /** The frame ID. */ public final String id; public Id3Frame(String id) { @@ -38,5 +36,4 @@ public String toString() { public int describeContents() { return 0; } - } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/PrivFrame.java b/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/PrivFrame.java index 773e49e8467..567785ac161 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/PrivFrame.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/PrivFrame.java @@ -75,18 +75,17 @@ public void writeToParcel(Parcel dest, int flags) { dest.writeByteArray(privateData); } - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - - @Override - public PrivFrame createFromParcel(Parcel in) { - return new PrivFrame(in); - } - - @Override - public PrivFrame[] newArray(int size) { - return new PrivFrame[size]; - } - - }; - + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + + @Override + public PrivFrame createFromParcel(Parcel in) { + return new PrivFrame(in); + } + + @Override + public PrivFrame[] newArray(int size) { + return new PrivFrame[size]; + } + }; } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/TextInformationFrame.java b/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/TextInformationFrame.java index a8afe719b83..7bab6973310 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/TextInformationFrame.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/TextInformationFrame.java @@ -22,6 +22,8 @@ import androidx.annotation.Nullable; import com.google.android.exoplayer2.MediaMetadata; import com.google.android.exoplayer2.util.Util; +import java.util.ArrayList; +import java.util.List; /** Text information ID3 frame. */ public final class TextInformationFrame extends Id3Frame { @@ -76,11 +78,69 @@ public void populateMediaMetadata(MediaMetadata.Builder builder) { case "TYE": case "TYER": try { - builder.setYear(Integer.parseInt(value)); + builder.setRecordingYear(Integer.parseInt(value)); } catch (NumberFormatException e) { // Do nothing, invalid input. } break; + case "TDA": + case "TDAT": + try { + int month = Integer.parseInt(value.substring(2, 4)); + int day = Integer.parseInt(value.substring(0, 2)); + builder.setRecordingMonth(month).setRecordingDay(day); + } catch (NumberFormatException | StringIndexOutOfBoundsException e) { + // Do nothing, invalid input. + } + break; + case "TDRC": + List recordingDate = parseId3v2point4TimestampFrameForDate(value); + switch (recordingDate.size()) { + case 3: + builder.setRecordingDay(recordingDate.get(2)); + // fall through + case 2: + builder.setRecordingMonth(recordingDate.get(1)); + // fall through + case 1: + builder.setRecordingYear(recordingDate.get(0)); + // fall through + break; + default: + // Do nothing. + break; + } + break; + case "TDRL": + List releaseDate = parseId3v2point4TimestampFrameForDate(value); + switch (releaseDate.size()) { + case 3: + builder.setReleaseDay(releaseDate.get(2)); + // fall through + case 2: + builder.setReleaseMonth(releaseDate.get(1)); + // fall through + case 1: + builder.setReleaseYear(releaseDate.get(0)); + // fall through + break; + default: + // Do nothing. + break; + } + break; + case "TCM": + case "TCOM": + builder.setComposer(value); + break; + case "TP3": + case "TPE3": + builder.setConductor(value); + break; + case "TXT": + case "TEXT": + builder.setWriter(value); + break; default: break; } @@ -136,4 +196,28 @@ public TextInformationFrame[] newArray(int size) { return new TextInformationFrame[size]; } }; + + // Private methods + + private static List parseId3v2point4TimestampFrameForDate(String value) { + // Timestamp string format is ISO-8601, can be `yyyy-MM-ddTHH:mm:ss`, or reduced precision + // at each point, for example `yyyy-MM` or `yyyy-MM-ddTHH:mm`. + List dates = new ArrayList<>(); + try { + if (value.length() >= 10) { + dates.add(Integer.parseInt(value.substring(0, 4))); + dates.add(Integer.parseInt(value.substring(5, 7))); + dates.add(Integer.parseInt(value.substring(8, 10))); + } else if (value.length() >= 7) { + dates.add(Integer.parseInt(value.substring(0, 4))); + dates.add(Integer.parseInt(value.substring(5, 7))); + } else if (value.length() >= 4) { + dates.add(Integer.parseInt(value.substring(0, 4))); + } + } catch (NumberFormatException e) { + // Invalid output, return. + return new ArrayList<>(); + } + return dates; + } } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/UrlLinkFrame.java b/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/UrlLinkFrame.java index d9b73ab0118..6648d852faa 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/UrlLinkFrame.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/metadata/id3/UrlLinkFrame.java @@ -49,7 +49,8 @@ public boolean equals(@Nullable Object obj) { return false; } UrlLinkFrame other = (UrlLinkFrame) obj; - return id.equals(other.id) && Util.areEqual(description, other.description) + return id.equals(other.id) + && Util.areEqual(description, other.description) && Util.areEqual(url, other.url); } @@ -88,7 +89,5 @@ public UrlLinkFrame createFromParcel(Parcel in) { public UrlLinkFrame[] newArray(int size) { return new UrlLinkFrame[size]; } - }; - } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/source/TrackGroup.java b/library/common/src/main/java/com/google/android/exoplayer2/source/TrackGroup.java index 2df780ce932..0888f3fa966 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/source/TrackGroup.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/source/TrackGroup.java @@ -37,9 +37,7 @@ public final class TrackGroup implements Parcelable { // Lazily initialized hashcode. private int hashCode; - /** - * @param formats The track formats. At least one {@link Format} must be provided. - */ + /** @param formats The track formats. At least one {@link Format} must be provided. */ public TrackGroup(Format... formats) { Assertions.checkState(formats.length > 0); this.formats = formats; diff --git a/library/common/src/main/java/com/google/android/exoplayer2/source/ads/AdPlaybackState.java b/library/common/src/main/java/com/google/android/exoplayer2/source/ads/AdPlaybackState.java index 5b207492d9a..cc6e6f13324 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/source/ads/AdPlaybackState.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/source/ads/AdPlaybackState.java @@ -16,6 +16,7 @@ package com.google.android.exoplayer2.source.ads; import static com.google.android.exoplayer2.util.Assertions.checkArgument; +import static com.google.android.exoplayer2.util.Assertions.checkState; import static java.lang.Math.max; import android.net.Uri; @@ -49,6 +50,11 @@ public final class AdPlaybackState implements Bundleable { */ public static final class AdGroup implements Bundleable { + /** + * The time of the ad group in the {@link com.google.android.exoplayer2.Timeline.Period}, in + * microseconds, or {@link C#TIME_END_OF_SOURCE} to indicate a postroll ad. + */ + public final long timeUs; /** The number of ads in the ad group, or {@link C#LENGTH_UNSET} if unknown. */ public final int count; /** The URI of each ad in the ad group. */ @@ -57,23 +63,48 @@ public static final class AdGroup implements Bundleable { @AdState public final int[] states; /** The durations of each ad in the ad group, in microseconds. */ public final long[] durationsUs; + /** + * The offset in microseconds which should be added to the content stream when resuming playback + * after the ad group. + */ + public final long contentResumeOffsetUs; + /** Whether this ad group is server-side inserted and part of the content stream. */ + public final boolean isServerSideInserted; - /** Creates a new ad group with an unspecified number of ads. */ - public AdGroup() { + /** + * Creates a new ad group with an unspecified number of ads. + * + * @param timeUs The time of the ad group in the {@link + * com.google.android.exoplayer2.Timeline.Period}, in microseconds, or {@link + * C#TIME_END_OF_SOURCE} to indicate a postroll ad. + */ + public AdGroup(long timeUs) { this( + timeUs, /* count= */ C.LENGTH_UNSET, /* states= */ new int[0], /* uris= */ new Uri[0], - /* durationsUs= */ new long[0]); + /* durationsUs= */ new long[0], + /* contentResumeOffsetUs= */ 0, + /* isServerSideInserted= */ false); } private AdGroup( - int count, @AdState int[] states, @NullableType Uri[] uris, long[] durationsUs) { + long timeUs, + int count, + @AdState int[] states, + @NullableType Uri[] uris, + long[] durationsUs, + long contentResumeOffsetUs, + boolean isServerSideInserted) { checkArgument(states.length == uris.length); + this.timeUs = timeUs; this.count = count; this.states = states; this.uris = uris; this.durationsUs = durationsUs; + this.contentResumeOffsetUs = contentResumeOffsetUs; + this.isServerSideInserted = isServerSideInserted; } /** @@ -91,7 +122,8 @@ public int getFirstAdIndexToPlay() { public int getNextAdIndexToPlay(int lastPlayedAdIndex) { int nextAdIndexToPlay = lastPlayedAdIndex + 1; while (nextAdIndexToPlay < states.length) { - if (states[nextAdIndexToPlay] == AD_STATE_UNAVAILABLE + if (isServerSideInserted + || states[nextAdIndexToPlay] == AD_STATE_UNAVAILABLE || states[nextAdIndexToPlay] == AD_STATE_AVAILABLE) { break; } @@ -100,11 +132,26 @@ public int getNextAdIndexToPlay(int lastPlayedAdIndex) { return nextAdIndexToPlay; } - /** Returns whether the ad group has at least one ad that still needs to be played. */ - public boolean hasUnplayedAds() { + /** Returns whether the ad group has at least one ad that should be played. */ + public boolean shouldPlayAdGroup() { return count == C.LENGTH_UNSET || getFirstAdIndexToPlay() < count; } + /** + * Returns whether the ad group has at least one ad that is neither played, skipped, nor failed. + */ + public boolean hasUnplayedAds() { + if (count == C.LENGTH_UNSET) { + return true; + } + for (int i = 0; i < count; i++) { + if (states[i] == AD_STATE_UNAVAILABLE || states[i] == AD_STATE_AVAILABLE) { + return true; + } + } + return false; + } + @Override public boolean equals(@Nullable Object o) { if (this == o) { @@ -114,28 +161,42 @@ public boolean equals(@Nullable Object o) { return false; } AdGroup adGroup = (AdGroup) o; - return count == adGroup.count + return timeUs == adGroup.timeUs + && count == adGroup.count && Arrays.equals(uris, adGroup.uris) && Arrays.equals(states, adGroup.states) - && Arrays.equals(durationsUs, adGroup.durationsUs); + && Arrays.equals(durationsUs, adGroup.durationsUs) + && contentResumeOffsetUs == adGroup.contentResumeOffsetUs + && isServerSideInserted == adGroup.isServerSideInserted; } @Override public int hashCode() { int result = count; + result = 31 * result + (int) (timeUs ^ (timeUs >>> 32)); result = 31 * result + Arrays.hashCode(uris); result = 31 * result + Arrays.hashCode(states); result = 31 * result + Arrays.hashCode(durationsUs); + result = 31 * result + (int) (contentResumeOffsetUs ^ (contentResumeOffsetUs >>> 32)); + result = 31 * result + (isServerSideInserted ? 1 : 0); return result; } + /** Returns a new instance with the {@link #timeUs} set to the specified value. */ + @CheckResult + public AdGroup withTimeUs(long timeUs) { + return new AdGroup( + timeUs, count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted); + } + /** Returns a new instance with the ad count set to {@code count}. */ @CheckResult public AdGroup withAdCount(int count) { @AdState int[] states = copyStatesWithSpaceForAdCount(this.states, count); long[] durationsUs = copyDurationsUsWithSpaceForAdCount(this.durationsUs, count); @NullableType Uri[] uris = Arrays.copyOf(this.uris, count); - return new AdGroup(count, states, uris, durationsUs); + return new AdGroup( + timeUs, count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted); } /** @@ -152,7 +213,8 @@ public AdGroup withAdUri(Uri uri, int index) { @NullableType Uri[] uris = Arrays.copyOf(this.uris, states.length); uris[index] = uri; states[index] = AD_STATE_AVAILABLE; - return new AdGroup(count, states, uris, durationsUs); + return new AdGroup( + timeUs, count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted); } /** @@ -179,7 +241,8 @@ public AdGroup withAdState(@AdState int state, int index) { Uri[] uris = this.uris.length == states.length ? this.uris : Arrays.copyOf(this.uris, states.length); states[index] = state; - return new AdGroup(count, states, uris, durationsUs); + return new AdGroup( + timeUs, count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted); } /** Returns a new instance with the specified ad durations, in microseconds. */ @@ -190,7 +253,22 @@ public AdGroup withAdDurationsUs(long[] durationsUs) { } else if (count != C.LENGTH_UNSET && durationsUs.length > uris.length) { durationsUs = Arrays.copyOf(durationsUs, uris.length); } - return new AdGroup(count, states, uris, durationsUs); + return new AdGroup( + timeUs, count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted); + } + + /** Returns an instance with the specified {@link #contentResumeOffsetUs}. */ + @CheckResult + public AdGroup withContentResumeOffsetUs(long contentResumeOffsetUs) { + return new AdGroup( + timeUs, count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted); + } + + /** Returns an instance with the specified value for {@link #isServerSideInserted}. */ + @CheckResult + public AdGroup withIsServerSideInserted(boolean isServerSideInserted) { + return new AdGroup( + timeUs, count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted); } /** @@ -201,10 +279,13 @@ public AdGroup withAdDurationsUs(long[] durationsUs) { public AdGroup withAllAdsSkipped() { if (count == C.LENGTH_UNSET) { return new AdGroup( + timeUs, /* count= */ 0, /* states= */ new int[0], /* uris= */ new Uri[0], - /* durationsUs= */ new long[0]); + /* durationsUs= */ new long[0], + contentResumeOffsetUs, + isServerSideInserted); } int count = this.states.length; @AdState int[] states = Arrays.copyOf(this.states, count); @@ -213,7 +294,8 @@ public AdGroup withAllAdsSkipped() { states[i] = AD_STATE_SKIPPED; } } - return new AdGroup(count, states, uris, durationsUs); + return new AdGroup( + timeUs, count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted); } @CheckResult @@ -238,24 +320,38 @@ private static long[] copyDurationsUsWithSpaceForAdCount(long[] durationsUs, int @Documented @Retention(RetentionPolicy.SOURCE) - @IntDef({FIELD_COUNT, FIELD_URIS, FIELD_STATES, FIELD_DURATIONS_US}) + @IntDef({ + FIELD_TIME_US, + FIELD_COUNT, + FIELD_URIS, + FIELD_STATES, + FIELD_DURATIONS_US, + FIELD_CONTENT_RESUME_OFFSET_US, + FIELD_IS_SERVER_SIDE_INSERTED, + }) private @interface FieldNumber {} - private static final int FIELD_COUNT = 0; - private static final int FIELD_URIS = 1; - private static final int FIELD_STATES = 2; - private static final int FIELD_DURATIONS_US = 3; + private static final int FIELD_TIME_US = 0; + private static final int FIELD_COUNT = 1; + private static final int FIELD_URIS = 2; + private static final int FIELD_STATES = 3; + private static final int FIELD_DURATIONS_US = 4; + private static final int FIELD_CONTENT_RESUME_OFFSET_US = 5; + private static final int FIELD_IS_SERVER_SIDE_INSERTED = 6; // putParcelableArrayList actually supports null elements. - @SuppressWarnings("nullness:argument.type.incompatible") + @SuppressWarnings("nullness:argument") @Override public Bundle toBundle() { Bundle bundle = new Bundle(); + bundle.putLong(keyForField(FIELD_TIME_US), timeUs); bundle.putInt(keyForField(FIELD_COUNT), count); bundle.putParcelableArrayList( keyForField(FIELD_URIS), new ArrayList<@NullableType Uri>(Arrays.asList(uris))); bundle.putIntArray(keyForField(FIELD_STATES), states); bundle.putLongArray(keyForField(FIELD_DURATIONS_US), durationsUs); + bundle.putLong(keyForField(FIELD_CONTENT_RESUME_OFFSET_US), contentResumeOffsetUs); + bundle.putBoolean(keyForField(FIELD_IS_SERVER_SIDE_INSERTED), isServerSideInserted); return bundle; } @@ -263,8 +359,9 @@ public Bundle toBundle() { public static final Creator CREATOR = AdGroup::fromBundle; // getParcelableArrayList may have null elements. - @SuppressWarnings("nullness:type.argument.type.incompatible") + @SuppressWarnings("nullness:type.argument") private static AdGroup fromBundle(Bundle bundle) { + long timeUs = bundle.getLong(keyForField(FIELD_TIME_US)); int count = bundle.getInt(keyForField(FIELD_COUNT), /* defaultValue= */ C.LENGTH_UNSET); @Nullable ArrayList<@NullableType Uri> uriList = bundle.getParcelableArrayList(keyForField(FIELD_URIS)); @@ -272,11 +369,16 @@ private static AdGroup fromBundle(Bundle bundle) { @AdState int[] states = bundle.getIntArray(keyForField(FIELD_STATES)); @Nullable long[] durationsUs = bundle.getLongArray(keyForField(FIELD_DURATIONS_US)); + long contentResumeOffsetUs = bundle.getLong(keyForField(FIELD_CONTENT_RESUME_OFFSET_US)); + boolean isServerSideInserted = bundle.getBoolean(keyForField(FIELD_IS_SERVER_SIDE_INSERTED)); return new AdGroup( + timeUs, count, states == null ? new int[0] : states, uriList == null ? new Uri[0] : uriList.toArray(new Uri[0]), - durationsUs == null ? new long[0] : durationsUs); + durationsUs == null ? new long[0] : durationsUs, + contentResumeOffsetUs, + isServerSideInserted); } private static String keyForField(@AdGroup.FieldNumber int field) { @@ -314,10 +416,12 @@ private static String keyForField(@AdGroup.FieldNumber int field) { public static final AdPlaybackState NONE = new AdPlaybackState( /* adsId= */ null, - /* adGroupTimesUs= */ new long[0], - /* adGroups= */ null, + /* adGroups= */ new AdGroup[0], /* adResumePositionUs= */ 0L, - /* contentDurationUs= */ C.TIME_UNSET); + /* contentDurationUs= */ C.TIME_UNSET, + /* removedAdGroupCount= */ 0); + + private static final AdGroup REMOVED_AD_GROUP = new AdGroup(/* timeUs= */ 0).withAdCount(0); /** * The opaque identifier for ads with which this instance is associated, or {@code null} if unset. @@ -326,20 +430,20 @@ private static String keyForField(@AdGroup.FieldNumber int field) { /** The number of ad groups. */ public final int adGroupCount; - /** - * The times of ad groups, in microseconds, relative to the start of the {@link - * com.google.android.exoplayer2.Timeline.Period} they belong to. A final element with the value - * {@link C#TIME_END_OF_SOURCE} indicates a postroll ad. - */ - public final long[] adGroupTimesUs; - /** The ad groups. */ - public final AdGroup[] adGroups; /** The position offset in the first unplayed ad at which to begin playback, in microseconds. */ public final long adResumePositionUs; /** * The duration of the content period in microseconds, if known. {@link C#TIME_UNSET} otherwise. */ public final long contentDurationUs; + /** + * The number of ad groups the have been removed. Ad groups with indices between {@code 0} + * (inclusive) and {@code removedAdGroupCount} (exclusive) will be empty and must not be modified + * by any of the {@code with*} methods. + */ + public final int removedAdGroupCount; + + private final AdGroup[] adGroups; /** * Creates a new ad playback state with the specified ad group times. @@ -352,31 +456,31 @@ private static String keyForField(@AdGroup.FieldNumber int field) { public AdPlaybackState(Object adsId, long... adGroupTimesUs) { this( adsId, - adGroupTimesUs, - /* adGroups= */ null, + createEmptyAdGroups(adGroupTimesUs), /* adResumePositionUs= */ 0, - /* contentDurationUs= */ C.TIME_UNSET); + /* contentDurationUs= */ C.TIME_UNSET, + /* removedAdGroupCount= */ 0); } private AdPlaybackState( @Nullable Object adsId, - long[] adGroupTimesUs, - @Nullable AdGroup[] adGroups, + AdGroup[] adGroups, long adResumePositionUs, - long contentDurationUs) { - checkArgument(adGroups == null || adGroups.length == adGroupTimesUs.length); + long contentDurationUs, + int removedAdGroupCount) { this.adsId = adsId; - this.adGroupTimesUs = adGroupTimesUs; this.adResumePositionUs = adResumePositionUs; this.contentDurationUs = contentDurationUs; - adGroupCount = adGroupTimesUs.length; - if (adGroups == null) { - adGroups = new AdGroup[adGroupCount]; - for (int i = 0; i < adGroupCount; i++) { - adGroups[i] = new AdGroup(); - } - } + adGroupCount = adGroups.length + removedAdGroupCount; this.adGroups = adGroups; + this.removedAdGroupCount = removedAdGroupCount; + } + + /** Returns the specified {@link AdGroup}. */ + public AdGroup getAdGroup(int adGroupIndex) { + return adGroupIndex < removedAdGroupCount + ? REMOVED_AD_GROUP + : adGroups[adGroupIndex - removedAdGroupCount]; } /** @@ -394,11 +498,11 @@ private AdPlaybackState( public int getAdGroupIndexForPositionUs(long positionUs, long periodDurationUs) { // Use a linear search as the array elements may not be increasing due to TIME_END_OF_SOURCE. // In practice we expect there to be few ad groups so the search shouldn't be expensive. - int index = adGroupTimesUs.length - 1; + int index = adGroupCount - 1; while (index >= 0 && isPositionBeforeAdGroup(positionUs, periodDurationUs, index)) { index--; } - return index >= 0 && adGroups[index].hasUnplayedAds() ? index : C.INDEX_UNSET; + return index >= 0 && getAdGroup(index).hasUnplayedAds() ? index : C.INDEX_UNSET; } /** @@ -419,27 +523,69 @@ public int getAdGroupIndexAfterPositionUs(long positionUs, long periodDurationUs } // Use a linear search as the array elements may not be increasing due to TIME_END_OF_SOURCE. // In practice we expect there to be few ad groups so the search shouldn't be expensive. - int index = 0; - while (index < adGroupTimesUs.length - && ((adGroupTimesUs[index] != C.TIME_END_OF_SOURCE && adGroupTimesUs[index] <= positionUs) - || !adGroups[index].hasUnplayedAds())) { + int index = removedAdGroupCount; + while (index < adGroupCount + && ((getAdGroup(index).timeUs != C.TIME_END_OF_SOURCE + && getAdGroup(index).timeUs <= positionUs) + || !getAdGroup(index).shouldPlayAdGroup())) { index++; } - return index < adGroupTimesUs.length ? index : C.INDEX_UNSET; + return index < adGroupCount ? index : C.INDEX_UNSET; } /** Returns whether the specified ad has been marked as in {@link #AD_STATE_ERROR}. */ public boolean isAdInErrorState(int adGroupIndex, int adIndexInAdGroup) { - if (adGroupIndex >= adGroups.length) { + if (adGroupIndex >= adGroupCount) { return false; } - AdGroup adGroup = adGroups[adGroupIndex]; + AdGroup adGroup = getAdGroup(adGroupIndex); if (adGroup.count == C.LENGTH_UNSET || adIndexInAdGroup >= adGroup.count) { return false; } return adGroup.states[adIndexInAdGroup] == AdPlaybackState.AD_STATE_ERROR; } + /** + * Returns an instance with the specified ad group time. + * + * @param adGroupIndex The index of the ad group. + * @param adGroupTimeUs The new ad group time, in microseconds, or {@link C#TIME_END_OF_SOURCE} to + * indicate a postroll ad. + * @return The updated ad playback state. + */ + @CheckResult + public AdPlaybackState withAdGroupTimeUs(int adGroupIndex, long adGroupTimeUs) { + int adjustedIndex = adGroupIndex - removedAdGroupCount; + AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length); + adGroups[adjustedIndex] = this.adGroups[adjustedIndex].withTimeUs(adGroupTimeUs); + return new AdPlaybackState( + adsId, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount); + } + + /** + * Returns an instance with a new ad group. + * + * @param adGroupIndex The insertion index of the new group. + * @param adGroupTimeUs The ad group time, in microseconds, or {@link C#TIME_END_OF_SOURCE} to + * indicate a postroll ad. + * @return The updated ad playback state. + */ + @CheckResult + public AdPlaybackState withNewAdGroup(int adGroupIndex, long adGroupTimeUs) { + int adjustedIndex = adGroupIndex - removedAdGroupCount; + AdGroup newAdGroup = new AdGroup(adGroupTimeUs); + AdGroup[] adGroups = Util.nullSafeArrayAppend(this.adGroups, newAdGroup); + System.arraycopy( + /* src= */ adGroups, + /* srcPos= */ adjustedIndex, + /* dest= */ adGroups, + /* destPos= */ adjustedIndex + 1, + /* length= */ this.adGroups.length - adjustedIndex); + adGroups[adjustedIndex] = newAdGroup; + return new AdPlaybackState( + adsId, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount); + } + /** * Returns an instance with the number of ads in {@code adGroupIndex} resolved to {@code adCount}. * The ad count must be greater than zero. @@ -447,49 +593,56 @@ public boolean isAdInErrorState(int adGroupIndex, int adIndexInAdGroup) { @CheckResult public AdPlaybackState withAdCount(int adGroupIndex, int adCount) { checkArgument(adCount > 0); - if (adGroups[adGroupIndex].count == adCount) { + int adjustedIndex = adGroupIndex - removedAdGroupCount; + if (adGroups[adjustedIndex].count == adCount) { return this; } AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length); - adGroups[adGroupIndex] = this.adGroups[adGroupIndex].withAdCount(adCount); + adGroups[adjustedIndex] = this.adGroups[adjustedIndex].withAdCount(adCount); return new AdPlaybackState( - adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs); + adsId, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount); } /** Returns an instance with the specified ad URI. */ @CheckResult public AdPlaybackState withAdUri(int adGroupIndex, int adIndexInAdGroup, Uri uri) { + int adjustedIndex = adGroupIndex - removedAdGroupCount; AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length); - adGroups[adGroupIndex] = adGroups[adGroupIndex].withAdUri(uri, adIndexInAdGroup); + adGroups[adjustedIndex] = adGroups[adjustedIndex].withAdUri(uri, adIndexInAdGroup); return new AdPlaybackState( - adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs); + adsId, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount); } /** Returns an instance with the specified ad marked as played. */ @CheckResult public AdPlaybackState withPlayedAd(int adGroupIndex, int adIndexInAdGroup) { + int adjustedIndex = adGroupIndex - removedAdGroupCount; AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length); - adGroups[adGroupIndex] = adGroups[adGroupIndex].withAdState(AD_STATE_PLAYED, adIndexInAdGroup); + adGroups[adjustedIndex] = + adGroups[adjustedIndex].withAdState(AD_STATE_PLAYED, adIndexInAdGroup); return new AdPlaybackState( - adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs); + adsId, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount); } /** Returns an instance with the specified ad marked as skipped. */ @CheckResult public AdPlaybackState withSkippedAd(int adGroupIndex, int adIndexInAdGroup) { + int adjustedIndex = adGroupIndex - removedAdGroupCount; AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length); - adGroups[adGroupIndex] = adGroups[adGroupIndex].withAdState(AD_STATE_SKIPPED, adIndexInAdGroup); + adGroups[adjustedIndex] = + adGroups[adjustedIndex].withAdState(AD_STATE_SKIPPED, adIndexInAdGroup); return new AdPlaybackState( - adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs); + adsId, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount); } /** Returns an instance with the specified ad marked as having a load error. */ @CheckResult public AdPlaybackState withAdLoadError(int adGroupIndex, int adIndexInAdGroup) { + int adjustedIndex = adGroupIndex - removedAdGroupCount; AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length); - adGroups[adGroupIndex] = adGroups[adGroupIndex].withAdState(AD_STATE_ERROR, adIndexInAdGroup); + adGroups[adjustedIndex] = adGroups[adjustedIndex].withAdState(AD_STATE_ERROR, adIndexInAdGroup); return new AdPlaybackState( - adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs); + adsId, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount); } /** @@ -498,21 +651,40 @@ public AdPlaybackState withAdLoadError(int adGroupIndex, int adIndexInAdGroup) { */ @CheckResult public AdPlaybackState withSkippedAdGroup(int adGroupIndex) { + int adjustedIndex = adGroupIndex - removedAdGroupCount; AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length); - adGroups[adGroupIndex] = adGroups[adGroupIndex].withAllAdsSkipped(); + adGroups[adjustedIndex] = adGroups[adjustedIndex].withAllAdsSkipped(); return new AdPlaybackState( - adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs); + adsId, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount); } - /** Returns an instance with the specified ad durations, in microseconds. */ + /** + * Returns an instance with the specified ad durations, in microseconds. + * + *

        Must only be used if {@link #removedAdGroupCount} is 0. + */ @CheckResult public AdPlaybackState withAdDurationsUs(long[][] adDurationUs) { + checkState(removedAdGroupCount == 0); AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length); for (int adGroupIndex = 0; adGroupIndex < adGroupCount; adGroupIndex++) { adGroups[adGroupIndex] = adGroups[adGroupIndex].withAdDurationsUs(adDurationUs[adGroupIndex]); } return new AdPlaybackState( - adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs); + adsId, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount); + } + + /** + * Returns an instance with the specified ad durations, in microseconds, in the specified ad + * group. + */ + @CheckResult + public AdPlaybackState withAdDurationsUs(int adGroupIndex, long... adDurationsUs) { + int adjustedIndex = adGroupIndex - removedAdGroupCount; + AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length); + adGroups[adjustedIndex] = adGroups[adjustedIndex].withAdDurationsUs(adDurationsUs); + return new AdPlaybackState( + adsId, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount); } /** @@ -525,7 +697,7 @@ public AdPlaybackState withAdResumePositionUs(long adResumePositionUs) { return this; } else { return new AdPlaybackState( - adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs); + adsId, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount); } } @@ -536,8 +708,67 @@ public AdPlaybackState withContentDurationUs(long contentDurationUs) { return this; } else { return new AdPlaybackState( - adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs); + adsId, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount); + } + } + + /** + * Returns an instance with the specified number of {@link #removedAdGroupCount removed ad + * groups}. + * + *

        Ad groups with indices between {@code 0} (inclusive) and {@code removedAdGroupCount} + * (exclusive) will be empty and must not be modified by any of the {@code with*} methods. + */ + @CheckResult + public AdPlaybackState withRemovedAdGroupCount(int removedAdGroupCount) { + if (this.removedAdGroupCount == removedAdGroupCount) { + return this; + } else { + checkArgument(removedAdGroupCount > this.removedAdGroupCount); + AdGroup[] adGroups = new AdGroup[adGroupCount - removedAdGroupCount]; + System.arraycopy( + /* src= */ this.adGroups, + /* srcPos= */ removedAdGroupCount - this.removedAdGroupCount, + /* dest= */ adGroups, + /* destPos= */ 0, + /* length= */ adGroups.length); + return new AdPlaybackState( + adsId, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount); + } + } + + /** + * Returns an instance with the specified {@link AdGroup#contentResumeOffsetUs}, in microseconds, + * for the specified ad group. + */ + @CheckResult + public AdPlaybackState withContentResumeOffsetUs(int adGroupIndex, long contentResumeOffsetUs) { + int adjustedIndex = adGroupIndex - removedAdGroupCount; + if (adGroups[adjustedIndex].contentResumeOffsetUs == contentResumeOffsetUs) { + return this; + } + AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length); + adGroups[adjustedIndex] = + adGroups[adjustedIndex].withContentResumeOffsetUs(contentResumeOffsetUs); + return new AdPlaybackState( + adsId, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount); + } + + /** + * Returns an instance with the specified value for {@link AdGroup#isServerSideInserted} in the + * specified ad group. + */ + @CheckResult + public AdPlaybackState withIsServerSideInserted(int adGroupIndex, boolean isServerSideInserted) { + int adjustedIndex = adGroupIndex - removedAdGroupCount; + if (adGroups[adjustedIndex].isServerSideInserted == isServerSideInserted) { + return this; } + AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length); + adGroups[adjustedIndex] = + adGroups[adjustedIndex].withIsServerSideInserted(isServerSideInserted); + return new AdPlaybackState( + adsId, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount); } @Override @@ -553,7 +784,7 @@ public boolean equals(@Nullable Object o) { && adGroupCount == that.adGroupCount && adResumePositionUs == that.adResumePositionUs && contentDurationUs == that.contentDurationUs - && Arrays.equals(adGroupTimesUs, that.adGroupTimesUs) + && removedAdGroupCount == that.removedAdGroupCount && Arrays.equals(adGroups, that.adGroups); } @@ -563,7 +794,7 @@ public int hashCode() { result = 31 * result + (adsId == null ? 0 : adsId.hashCode()); result = 31 * result + (int) adResumePositionUs; result = 31 * result + (int) contentDurationUs; - result = 31 * result + Arrays.hashCode(adGroupTimesUs); + result = 31 * result + removedAdGroupCount; result = 31 * result + Arrays.hashCode(adGroups); return result; } @@ -578,7 +809,7 @@ public String toString() { sb.append(", adGroups=["); for (int i = 0; i < adGroups.length; i++) { sb.append("adGroup(timeUs="); - sb.append(adGroupTimesUs[i]); + sb.append(adGroups[i].timeUs); sb.append(", ads=["); for (int j = 0; j < adGroups[i].states.length; j++) { sb.append("ad(state="); @@ -624,7 +855,7 @@ private boolean isPositionBeforeAdGroup( // The end of the content is at (but not before) any postroll ad, and after any other ads. return false; } - long adGroupPositionUs = adGroupTimesUs[adGroupIndex]; + long adGroupPositionUs = getAdGroup(adGroupIndex).timeUs; if (adGroupPositionUs == C.TIME_END_OF_SOURCE) { return periodDurationUs == C.TIME_UNSET || positionUs < periodDurationUs; } else { @@ -637,17 +868,17 @@ private boolean isPositionBeforeAdGroup( @Documented @Retention(RetentionPolicy.SOURCE) @IntDef({ - FIELD_AD_GROUP_TIMES_US, FIELD_AD_GROUPS, FIELD_AD_RESUME_POSITION_US, - FIELD_CONTENT_DURATION_US + FIELD_CONTENT_DURATION_US, + FIELD_REMOVED_AD_GROUP_COUNT }) private @interface FieldNumber {} - private static final int FIELD_AD_GROUP_TIMES_US = 1; - private static final int FIELD_AD_GROUPS = 2; - private static final int FIELD_AD_RESUME_POSITION_US = 3; - private static final int FIELD_CONTENT_DURATION_US = 4; + private static final int FIELD_AD_GROUPS = 1; + private static final int FIELD_AD_RESUME_POSITION_US = 2; + private static final int FIELD_CONTENT_DURATION_US = 3; + private static final int FIELD_REMOVED_AD_GROUP_COUNT = 4; /** * {@inheritDoc} @@ -659,7 +890,6 @@ private boolean isPositionBeforeAdGroup( @Override public Bundle toBundle() { Bundle bundle = new Bundle(); - bundle.putLongArray(keyForField(FIELD_AD_GROUP_TIMES_US), adGroupTimesUs); ArrayList adGroupBundleList = new ArrayList<>(); for (AdGroup adGroup : adGroups) { adGroupBundleList.add(adGroup.toBundle()); @@ -667,6 +897,7 @@ public Bundle toBundle() { bundle.putParcelableArrayList(keyForField(FIELD_AD_GROUPS), adGroupBundleList); bundle.putLong(keyForField(FIELD_AD_RESUME_POSITION_US), adResumePositionUs); bundle.putLong(keyForField(FIELD_CONTENT_DURATION_US), contentDurationUs); + bundle.putInt(keyForField(FIELD_REMOVED_AD_GROUP_COUNT), removedAdGroupCount); return bundle; } @@ -678,13 +909,12 @@ public Bundle toBundle() { public static final Bundleable.Creator CREATOR = AdPlaybackState::fromBundle; private static AdPlaybackState fromBundle(Bundle bundle) { - @Nullable long[] adGroupTimesUs = bundle.getLongArray(keyForField(FIELD_AD_GROUP_TIMES_US)); @Nullable ArrayList adGroupBundleList = bundle.getParcelableArrayList(keyForField(FIELD_AD_GROUPS)); @Nullable AdGroup[] adGroups; if (adGroupBundleList == null) { - adGroups = null; + adGroups = new AdGroup[0]; } else { adGroups = new AdGroup[adGroupBundleList.size()]; for (int i = 0; i < adGroupBundleList.size(); i++) { @@ -695,15 +925,20 @@ private static AdPlaybackState fromBundle(Bundle bundle) { bundle.getLong(keyForField(FIELD_AD_RESUME_POSITION_US), /* defaultValue= */ 0); long contentDurationUs = bundle.getLong(keyForField(FIELD_CONTENT_DURATION_US), /* defaultValue= */ C.TIME_UNSET); + int removedAdGroupCount = bundle.getInt(keyForField(FIELD_REMOVED_AD_GROUP_COUNT)); return new AdPlaybackState( - /* adsId= */ null, - adGroupTimesUs == null ? new long[0] : adGroupTimesUs, - adGroups, - adResumePositionUs, - contentDurationUs); + /* adsId= */ null, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount); } private static String keyForField(@FieldNumber int field) { return Integer.toString(field, Character.MAX_RADIX); } + + private static AdGroup[] createEmptyAdGroups(long[] adGroupTimesUs) { + AdGroup[] adGroups = new AdGroup[adGroupTimesUs.length]; + for (int i = 0; i < adGroups.length; i++) { + adGroups[i] = new AdGroup(adGroupTimesUs[i]); + } + return adGroups; + } } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/text/Cue.java b/library/common/src/main/java/com/google/android/exoplayer2/text/Cue.java index 7735b808de2..66ab2f3682f 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/text/Cue.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/text/Cue.java @@ -17,23 +17,28 @@ import android.graphics.Bitmap; import android.graphics.Color; +import android.os.Bundle; import android.text.Layout; import android.text.Layout.Alignment; import android.text.Spanned; import android.text.SpannedString; +import android.text.TextUtils; import androidx.annotation.ColorInt; import androidx.annotation.IntDef; import androidx.annotation.Nullable; +import com.google.android.exoplayer2.Bundleable; import com.google.android.exoplayer2.util.Assertions; +import com.google.common.base.Objects; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import org.checkerframework.dataflow.qual.Pure; /** Contains information about a specific cue, including textual content and formatting data. */ // This class shouldn't be sub-classed. If a subtitle format needs additional fields, either they // should be generic enough to be added here, or the format-specific decoder should pass the // information around in a sidecar object. -public final class Cue { +public final class Cue implements Bundleable { /** The empty cue. */ public static final Cue EMPTY = new Cue.Builder().setText("").build(); @@ -60,9 +65,7 @@ public final class Cue { */ public static final int ANCHOR_TYPE_START = 0; - /** - * Anchors the middle of the cue box. - */ + /** Anchors the middle of the cue box. */ public static final int ANCHOR_TYPE_MIDDLE = 1; /** @@ -80,14 +83,10 @@ public final class Cue { @IntDef({TYPE_UNSET, LINE_TYPE_FRACTION, LINE_TYPE_NUMBER}) public @interface LineType {} - /** - * Value for {@link #lineType} when {@link #line} is a fractional position. - */ + /** Value for {@link #lineType} when {@link #line} is a fractional position. */ public static final int LINE_TYPE_FRACTION = 0; - /** - * Value for {@link #lineType} when {@link #line} is a line number. - */ + /** Value for {@link #lineType} when {@link #line} is a line number. */ public static final int LINE_TYPE_NUMBER = 1; /** @@ -249,14 +248,10 @@ public final class Cue { */ public final float bitmapHeight; - /** - * Specifies whether or not the {@link #windowColor} property is set. - */ + /** Specifies whether or not the {@link #windowColor} property is set. */ public final boolean windowColorSet; - /** - * The fill color of the window. - */ + /** The fill color of the window. */ public final int windowColor; /** @@ -490,6 +485,58 @@ public Builder buildUpon() { return new Cue.Builder(this); } + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + Cue that = (Cue) obj; + return TextUtils.equals(text, that.text) + && textAlignment == that.textAlignment + && multiRowAlignment == that.multiRowAlignment + && (bitmap == null + ? that.bitmap == null + : (that.bitmap != null && bitmap.sameAs(that.bitmap))) + && line == that.line + && lineType == that.lineType + && lineAnchor == that.lineAnchor + && position == that.position + && positionAnchor == that.positionAnchor + && size == that.size + && bitmapHeight == that.bitmapHeight + && windowColorSet == that.windowColorSet + && windowColor == that.windowColor + && textSizeType == that.textSizeType + && textSize == that.textSize + && verticalType == that.verticalType + && shearDegrees == that.shearDegrees; + } + + @Override + public int hashCode() { + return Objects.hashCode( + text, + textAlignment, + multiRowAlignment, + bitmap, + line, + lineType, + lineAnchor, + position, + positionAnchor, + size, + bitmapHeight, + windowColorSet, + windowColor, + textSizeType, + textSize, + verticalType, + shearDegrees); + } + /** A builder for {@link Cue} objects. */ public static final class Builder { @Nullable private CharSequence text; @@ -566,6 +613,7 @@ public Builder setText(CharSequence text) { * * @see Cue#text */ + @Pure @Nullable public CharSequence getText() { return text; @@ -586,6 +634,7 @@ public Builder setBitmap(Bitmap bitmap) { * * @see Cue#bitmap */ + @Pure @Nullable public Bitmap getBitmap() { return bitmap; @@ -608,6 +657,7 @@ public Builder setTextAlignment(@Nullable Layout.Alignment textAlignment) { * * @see Cue#textAlignment */ + @Pure @Nullable public Alignment getTextAlignment() { return textAlignment; @@ -644,6 +694,7 @@ public Builder setLine(float line, @LineType int lineType) { * * @see Cue#line */ + @Pure public float getLine() { return line; } @@ -653,6 +704,7 @@ public float getLine() { * * @see Cue#lineType */ + @Pure @LineType public int getLineType() { return lineType; @@ -673,6 +725,7 @@ public Builder setLineAnchor(@AnchorType int lineAnchor) { * * @see Cue#lineAnchor */ + @Pure @AnchorType public int getLineAnchor() { return lineAnchor; @@ -695,6 +748,7 @@ public Builder setPosition(float position) { * * @see Cue#position */ + @Pure public float getPosition() { return position; } @@ -714,6 +768,7 @@ public Builder setPositionAnchor(@AnchorType int positionAnchor) { * * @see Cue#positionAnchor */ + @Pure @AnchorType public int getPositionAnchor() { return positionAnchor; @@ -736,6 +791,7 @@ public Builder setTextSize(float textSize, @TextSizeType int textSizeType) { * * @see Cue#textSizeType */ + @Pure @TextSizeType public int getTextSizeType() { return textSizeType; @@ -746,6 +802,7 @@ public int getTextSizeType() { * * @see Cue#textSize */ + @Pure public float getTextSize() { return textSize; } @@ -767,6 +824,7 @@ public Builder setSize(float size) { * * @see Cue#size */ + @Pure public float getSize() { return size; } @@ -786,6 +844,7 @@ public Builder setBitmapHeight(float bitmapHeight) { * * @see Cue#bitmapHeight */ + @Pure public float getBitmapHeight() { return bitmapHeight; } @@ -824,6 +883,7 @@ public boolean isWindowColorSet() { * * @see Cue#windowColor */ + @Pure @ColorInt public int getWindowColor() { return windowColor; @@ -850,6 +910,7 @@ public Builder setShearDegrees(float shearDegrees) { * * @see Cue#verticalType */ + @Pure @VerticalType public int getVerticalType() { return verticalType; @@ -877,4 +938,138 @@ public Cue build() { shearDegrees); } } + + // Bundleable implementation. + + @Documented + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + FIELD_TEXT, + FIELD_TEXT_ALIGNMENT, + FIELD_MULTI_ROW_ALIGNMENT, + FIELD_BITMAP, + FIELD_LINE, + FIELD_LINE_TYPE, + FIELD_LINE_ANCHOR, + FIELD_POSITION, + FIELD_POSITION_ANCHOR, + FIELD_TEXT_SIZE_TYPE, + FIELD_TEXT_SIZE, + FIELD_SIZE, + FIELD_BITMAP_HEIGHT, + FIELD_WINDOW_COLOR, + FIELD_WINDOW_COLOR_SET, + FIELD_VERTICAL_TYPE, + FIELD_SHEAR_DEGREES + }) + private @interface FieldNumber {} + + private static final int FIELD_TEXT = 0; + private static final int FIELD_TEXT_ALIGNMENT = 1; + private static final int FIELD_MULTI_ROW_ALIGNMENT = 2; + private static final int FIELD_BITMAP = 3; + private static final int FIELD_LINE = 4; + private static final int FIELD_LINE_TYPE = 5; + private static final int FIELD_LINE_ANCHOR = 6; + private static final int FIELD_POSITION = 7; + private static final int FIELD_POSITION_ANCHOR = 8; + private static final int FIELD_TEXT_SIZE_TYPE = 9; + private static final int FIELD_TEXT_SIZE = 10; + private static final int FIELD_SIZE = 11; + private static final int FIELD_BITMAP_HEIGHT = 12; + private static final int FIELD_WINDOW_COLOR = 13; + private static final int FIELD_WINDOW_COLOR_SET = 14; + private static final int FIELD_VERTICAL_TYPE = 15; + private static final int FIELD_SHEAR_DEGREES = 16; + + @Override + public Bundle toBundle() { + Bundle bundle = new Bundle(); + bundle.putCharSequence(keyForField(FIELD_TEXT), text); + bundle.putSerializable(keyForField(FIELD_TEXT_ALIGNMENT), textAlignment); + bundle.putSerializable(keyForField(FIELD_MULTI_ROW_ALIGNMENT), multiRowAlignment); + bundle.putParcelable(keyForField(FIELD_BITMAP), bitmap); + bundle.putFloat(keyForField(FIELD_LINE), line); + bundle.putInt(keyForField(FIELD_LINE_TYPE), lineType); + bundle.putInt(keyForField(FIELD_LINE_ANCHOR), lineAnchor); + bundle.putFloat(keyForField(FIELD_POSITION), position); + bundle.putInt(keyForField(FIELD_POSITION_ANCHOR), positionAnchor); + bundle.putInt(keyForField(FIELD_TEXT_SIZE_TYPE), textSizeType); + bundle.putFloat(keyForField(FIELD_TEXT_SIZE), textSize); + bundle.putFloat(keyForField(FIELD_SIZE), size); + bundle.putFloat(keyForField(FIELD_BITMAP_HEIGHT), bitmapHeight); + bundle.putBoolean(keyForField(FIELD_WINDOW_COLOR_SET), windowColorSet); + bundle.putInt(keyForField(FIELD_WINDOW_COLOR), windowColor); + bundle.putInt(keyForField(FIELD_VERTICAL_TYPE), verticalType); + bundle.putFloat(keyForField(FIELD_SHEAR_DEGREES), shearDegrees); + return bundle; + } + + public static final Creator CREATOR = Cue::fromBundle; + + private static final Cue fromBundle(Bundle bundle) { + Builder builder = new Builder(); + @Nullable CharSequence text = bundle.getCharSequence(keyForField(FIELD_TEXT)); + if (text != null) { + builder.setText(text); + } + @Nullable + Alignment textAlignment = (Alignment) bundle.getSerializable(keyForField(FIELD_TEXT_ALIGNMENT)); + if (textAlignment != null) { + builder.setTextAlignment(textAlignment); + } + @Nullable + Alignment multiRowAlignment = + (Alignment) bundle.getSerializable(keyForField(FIELD_MULTI_ROW_ALIGNMENT)); + if (multiRowAlignment != null) { + builder.setMultiRowAlignment(multiRowAlignment); + } + @Nullable Bitmap bitmap = bundle.getParcelable(keyForField(FIELD_BITMAP)); + if (bitmap != null) { + builder.setBitmap(bitmap); + } + if (bundle.containsKey(keyForField(FIELD_LINE)) + && bundle.containsKey(keyForField(FIELD_LINE_TYPE))) { + builder.setLine( + bundle.getFloat(keyForField(FIELD_LINE)), bundle.getInt(keyForField(FIELD_LINE_TYPE))); + } + if (bundle.containsKey(keyForField(FIELD_LINE_ANCHOR))) { + builder.setLineAnchor(bundle.getInt(keyForField(FIELD_LINE_ANCHOR))); + } + if (bundle.containsKey(keyForField(FIELD_POSITION))) { + builder.setPosition(bundle.getFloat(keyForField(FIELD_POSITION))); + } + if (bundle.containsKey(keyForField(FIELD_POSITION_ANCHOR))) { + builder.setPositionAnchor(bundle.getInt(keyForField(FIELD_POSITION_ANCHOR))); + } + if (bundle.containsKey(keyForField(FIELD_TEXT_SIZE)) + && bundle.containsKey(keyForField(FIELD_TEXT_SIZE_TYPE))) { + builder.setTextSize( + bundle.getFloat(keyForField(FIELD_TEXT_SIZE)), + bundle.getInt(keyForField(FIELD_TEXT_SIZE_TYPE))); + } + if (bundle.containsKey(keyForField(FIELD_SIZE))) { + builder.setSize(bundle.getFloat(keyForField(FIELD_SIZE))); + } + if (bundle.containsKey(keyForField(FIELD_BITMAP_HEIGHT))) { + builder.setBitmapHeight(bundle.getFloat(keyForField(FIELD_BITMAP_HEIGHT))); + } + if (bundle.containsKey(keyForField(FIELD_WINDOW_COLOR))) { + builder.setWindowColor(bundle.getInt(keyForField(FIELD_WINDOW_COLOR))); + } + if (!bundle.getBoolean(keyForField(FIELD_WINDOW_COLOR_SET), /* defaultValue= */ false)) { + builder.clearWindowColor(); + } + if (bundle.containsKey(keyForField(FIELD_VERTICAL_TYPE))) { + builder.setVerticalType(bundle.getInt(keyForField(FIELD_VERTICAL_TYPE))); + } + if (bundle.containsKey(keyForField(FIELD_SHEAR_DEGREES))) { + builder.setShearDegrees(bundle.getFloat(keyForField(FIELD_SHEAR_DEGREES))); + } + return builder.build(); + } + + private static String keyForField(@FieldNumber int field) { + return Integer.toString(field, Character.MAX_RADIX); + } } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.java b/library/common/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.java new file mode 100644 index 00000000000..bb8fce5fa40 --- /dev/null +++ b/library/common/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.java @@ -0,0 +1,855 @@ +/* + * 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 com.google.android.exoplayer2.trackselection; + +import static com.google.android.exoplayer2.util.Assertions.checkNotNull; + +import android.content.Context; +import android.graphics.Point; +import android.os.Looper; +import android.os.Parcel; +import android.os.Parcelable; +import android.view.accessibility.CaptioningManager; +import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; +import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.util.Util; +import com.google.common.collect.ImmutableList; +import java.util.ArrayList; +import java.util.Locale; + +/** Constraint parameters for track selection. */ +public class TrackSelectionParameters implements Parcelable { + + /** + * A builder for {@link TrackSelectionParameters}. See the {@link TrackSelectionParameters} + * documentation for explanations of the parameters that can be configured using this builder. + */ + public static class Builder { + // Video + private int maxVideoWidth; + private int maxVideoHeight; + private int maxVideoFrameRate; + private int maxVideoBitrate; + private int minVideoWidth; + private int minVideoHeight; + private int minVideoFrameRate; + private int minVideoBitrate; + private int viewportWidth; + private int viewportHeight; + private boolean viewportOrientationMayChange; + private ImmutableList preferredVideoMimeTypes; + // Audio + private ImmutableList preferredAudioLanguages; + @C.RoleFlags private int preferredAudioRoleFlags; + private int maxAudioChannelCount; + private int maxAudioBitrate; + private ImmutableList preferredAudioMimeTypes; + // Text + private ImmutableList preferredTextLanguages; + @C.RoleFlags private int preferredTextRoleFlags; + private boolean selectUndeterminedTextLanguage; + // General + private boolean forceLowestBitrate; + private boolean forceHighestSupportedBitrate; + + /** + * @deprecated {@link Context} constraints will not be set using this constructor. Use {@link + * #Builder(Context)} instead. + */ + @Deprecated + public Builder() { + // Video + maxVideoWidth = Integer.MAX_VALUE; + maxVideoHeight = Integer.MAX_VALUE; + maxVideoFrameRate = Integer.MAX_VALUE; + maxVideoBitrate = Integer.MAX_VALUE; + viewportWidth = Integer.MAX_VALUE; + viewportHeight = Integer.MAX_VALUE; + viewportOrientationMayChange = true; + preferredVideoMimeTypes = ImmutableList.of(); + // Audio + preferredAudioLanguages = ImmutableList.of(); + preferredAudioRoleFlags = 0; + maxAudioChannelCount = Integer.MAX_VALUE; + maxAudioBitrate = Integer.MAX_VALUE; + preferredAudioMimeTypes = ImmutableList.of(); + // Text + preferredTextLanguages = ImmutableList.of(); + preferredTextRoleFlags = 0; + selectUndeterminedTextLanguage = false; + // General + forceLowestBitrate = false; + forceHighestSupportedBitrate = false; + } + + /** + * Creates a builder with default initial values. + * + * @param context Any context. + */ + @SuppressWarnings({"deprecation", "method.invocation"}) // Methods invoked are setter only. + public Builder(Context context) { + this(); + setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings(context); + setViewportSizeToPhysicalDisplaySize(context, /* viewportOrientationMayChange= */ true); + } + + /** + * @param initialValues The {@link TrackSelectionParameters} from which the initial values of + * the builder are obtained. + */ + protected Builder(TrackSelectionParameters initialValues) { + // Video + maxVideoWidth = initialValues.maxVideoWidth; + maxVideoHeight = initialValues.maxVideoHeight; + maxVideoFrameRate = initialValues.maxVideoFrameRate; + maxVideoBitrate = initialValues.maxVideoBitrate; + minVideoWidth = initialValues.minVideoWidth; + minVideoHeight = initialValues.minVideoHeight; + minVideoFrameRate = initialValues.minVideoFrameRate; + minVideoBitrate = initialValues.minVideoBitrate; + viewportWidth = initialValues.viewportWidth; + viewportHeight = initialValues.viewportHeight; + viewportOrientationMayChange = initialValues.viewportOrientationMayChange; + preferredVideoMimeTypes = initialValues.preferredVideoMimeTypes; + // Audio + preferredAudioLanguages = initialValues.preferredAudioLanguages; + preferredAudioRoleFlags = initialValues.preferredAudioRoleFlags; + maxAudioChannelCount = initialValues.maxAudioChannelCount; + maxAudioBitrate = initialValues.maxAudioBitrate; + preferredAudioMimeTypes = initialValues.preferredAudioMimeTypes; + // Text + preferredTextLanguages = initialValues.preferredTextLanguages; + preferredTextRoleFlags = initialValues.preferredTextRoleFlags; + selectUndeterminedTextLanguage = initialValues.selectUndeterminedTextLanguage; + // General + forceLowestBitrate = initialValues.forceLowestBitrate; + forceHighestSupportedBitrate = initialValues.forceHighestSupportedBitrate; + } + + // Video + + /** + * Equivalent to {@link #setMaxVideoSize setMaxVideoSize(1279, 719)}. + * + * @return This builder. + */ + public Builder setMaxVideoSizeSd() { + return setMaxVideoSize(1279, 719); + } + + /** + * Equivalent to {@link #setMaxVideoSize setMaxVideoSize(Integer.MAX_VALUE, Integer.MAX_VALUE)}. + * + * @return This builder. + */ + public Builder clearVideoSizeConstraints() { + return setMaxVideoSize(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + /** + * Sets the maximum allowed video width and height. + * + * @param maxVideoWidth Maximum allowed video width in pixels. + * @param maxVideoHeight Maximum allowed video height in pixels. + * @return This builder. + */ + public Builder setMaxVideoSize(int maxVideoWidth, int maxVideoHeight) { + this.maxVideoWidth = maxVideoWidth; + this.maxVideoHeight = maxVideoHeight; + return this; + } + + /** + * Sets the maximum allowed video frame rate. + * + * @param maxVideoFrameRate Maximum allowed video frame rate in hertz. + * @return This builder. + */ + public Builder setMaxVideoFrameRate(int maxVideoFrameRate) { + this.maxVideoFrameRate = maxVideoFrameRate; + return this; + } + + /** + * Sets the maximum allowed video bitrate. + * + * @param maxVideoBitrate Maximum allowed video bitrate in bits per second. + * @return This builder. + */ + public Builder setMaxVideoBitrate(int maxVideoBitrate) { + this.maxVideoBitrate = maxVideoBitrate; + return this; + } + + /** + * Sets the minimum allowed video width and height. + * + * @param minVideoWidth Minimum allowed video width in pixels. + * @param minVideoHeight Minimum allowed video height in pixels. + * @return This builder. + */ + public Builder setMinVideoSize(int minVideoWidth, int minVideoHeight) { + this.minVideoWidth = minVideoWidth; + this.minVideoHeight = minVideoHeight; + return this; + } + + /** + * Sets the minimum allowed video frame rate. + * + * @param minVideoFrameRate Minimum allowed video frame rate in hertz. + * @return This builder. + */ + public Builder setMinVideoFrameRate(int minVideoFrameRate) { + this.minVideoFrameRate = minVideoFrameRate; + return this; + } + + /** + * Sets the minimum allowed video bitrate. + * + * @param minVideoBitrate Minimum allowed video bitrate in bits per second. + * @return This builder. + */ + public Builder setMinVideoBitrate(int minVideoBitrate) { + this.minVideoBitrate = minVideoBitrate; + return this; + } + + /** + * Equivalent to calling {@link #setViewportSize(int, int, boolean)} with the viewport size + * obtained from {@link Util#getCurrentDisplayModeSize(Context)}. + * + * @param context Any context. + * @param viewportOrientationMayChange Whether the viewport orientation may change during + * playback. + * @return This builder. + */ + public Builder setViewportSizeToPhysicalDisplaySize( + Context context, boolean viewportOrientationMayChange) { + // Assume the viewport is fullscreen. + Point viewportSize = Util.getCurrentDisplayModeSize(context); + return setViewportSize(viewportSize.x, viewportSize.y, viewportOrientationMayChange); + } + + /** + * Equivalent to {@link #setViewportSize setViewportSize(Integer.MAX_VALUE, Integer.MAX_VALUE, + * true)}. + * + * @return This builder. + */ + public Builder clearViewportSizeConstraints() { + return setViewportSize(Integer.MAX_VALUE, Integer.MAX_VALUE, true); + } + + /** + * Sets the viewport size to constrain adaptive video selections so that only tracks suitable + * for the viewport are selected. + * + * @param viewportWidth Viewport width in pixels. + * @param viewportHeight Viewport height in pixels. + * @param viewportOrientationMayChange Whether the viewport orientation may change during + * playback. + * @return This builder. + */ + public Builder setViewportSize( + int viewportWidth, int viewportHeight, boolean viewportOrientationMayChange) { + this.viewportWidth = viewportWidth; + this.viewportHeight = viewportHeight; + this.viewportOrientationMayChange = viewportOrientationMayChange; + return this; + } + + /** + * Sets the preferred sample MIME type for video tracks. + * + * @param mimeType The preferred MIME type for video tracks, or {@code null} to clear a + * previously set preference. + * @return This builder. + */ + public Builder setPreferredVideoMimeType(@Nullable String mimeType) { + return mimeType == null ? setPreferredVideoMimeTypes() : setPreferredVideoMimeTypes(mimeType); + } + + /** + * Sets the preferred sample MIME types for video tracks. + * + * @param mimeTypes The preferred MIME types for video tracks in order of preference, or an + * empty list for no preference. + * @return This builder. + */ + public Builder setPreferredVideoMimeTypes(String... mimeTypes) { + preferredVideoMimeTypes = ImmutableList.copyOf(mimeTypes); + return this; + } + + // Audio + + /** + * Sets the preferred language for audio and forced text tracks. + * + * @param preferredAudioLanguage Preferred audio language as an IETF BCP 47 conformant tag, or + * {@code null} to select the default track, or the first track if there's no default. + * @return This builder. + */ + public Builder setPreferredAudioLanguage(@Nullable String preferredAudioLanguage) { + return preferredAudioLanguage == null + ? setPreferredAudioLanguages() + : setPreferredAudioLanguages(preferredAudioLanguage); + } + + /** + * Sets the preferred languages for audio and forced text tracks. + * + * @param preferredAudioLanguages Preferred audio languages as IETF BCP 47 conformant tags in + * order of preference, or an empty array to select the default track, or the first track if + * there's no default. + * @return This builder. + */ + public Builder setPreferredAudioLanguages(String... preferredAudioLanguages) { + ImmutableList.Builder listBuilder = ImmutableList.builder(); + for (String language : checkNotNull(preferredAudioLanguages)) { + listBuilder.add(Util.normalizeLanguageCode(checkNotNull(language))); + } + this.preferredAudioLanguages = listBuilder.build(); + return this; + } + + /** + * Sets the preferred {@link C.RoleFlags} for audio tracks. + * + * @param preferredAudioRoleFlags Preferred audio role flags. + * @return This builder. + */ + public Builder setPreferredAudioRoleFlags(@C.RoleFlags int preferredAudioRoleFlags) { + this.preferredAudioRoleFlags = preferredAudioRoleFlags; + return this; + } + + /** + * Sets the maximum allowed audio channel count. + * + * @param maxAudioChannelCount Maximum allowed audio channel count. + * @return This builder. + */ + public Builder setMaxAudioChannelCount(int maxAudioChannelCount) { + this.maxAudioChannelCount = maxAudioChannelCount; + return this; + } + + /** + * Sets the maximum allowed audio bitrate. + * + * @param maxAudioBitrate Maximum allowed audio bitrate in bits per second. + * @return This builder. + */ + public Builder setMaxAudioBitrate(int maxAudioBitrate) { + this.maxAudioBitrate = maxAudioBitrate; + return this; + } + + /** + * Sets the preferred sample MIME type for audio tracks. + * + * @param mimeType The preferred MIME type for audio tracks, or {@code null} to clear a + * previously set preference. + * @return This builder. + */ + public Builder setPreferredAudioMimeType(@Nullable String mimeType) { + return mimeType == null ? setPreferredAudioMimeTypes() : setPreferredAudioMimeTypes(mimeType); + } + + /** + * Sets the preferred sample MIME types for audio tracks. + * + * @param mimeTypes The preferred MIME types for audio tracks in order of preference, or an + * empty list for no preference. + * @return This builder. + */ + public Builder setPreferredAudioMimeTypes(String... mimeTypes) { + preferredAudioMimeTypes = ImmutableList.copyOf(mimeTypes); + return this; + } + + // Text + + /** + * Sets the preferred language and role flags for text tracks based on the accessibility + * settings of {@link CaptioningManager}. + * + *

        Does nothing for API levels < 19 or when the {@link CaptioningManager} is disabled. + * + * @param context A {@link Context}. + * @return This builder. + */ + public Builder setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings( + Context context) { + if (Util.SDK_INT >= 19) { + setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettingsV19(context); + } + return this; + } + + /** + * Sets the preferred language for text tracks. + * + * @param preferredTextLanguage Preferred text language as an IETF BCP 47 conformant tag, or + * {@code null} to select the default track if there is one, or no track otherwise. + * @return This builder. + */ + public Builder setPreferredTextLanguage(@Nullable String preferredTextLanguage) { + return preferredTextLanguage == null + ? setPreferredTextLanguages() + : setPreferredTextLanguages(preferredTextLanguage); + } + + /** + * Sets the preferred languages for text tracks. + * + * @param preferredTextLanguages Preferred text languages as IETF BCP 47 conformant tags in + * order of preference, or an empty array to select the default track if there is one, or no + * track otherwise. + * @return This builder. + */ + public Builder setPreferredTextLanguages(String... preferredTextLanguages) { + ImmutableList.Builder listBuilder = ImmutableList.builder(); + for (String language : checkNotNull(preferredTextLanguages)) { + listBuilder.add(Util.normalizeLanguageCode(checkNotNull(language))); + } + this.preferredTextLanguages = listBuilder.build(); + return this; + } + + /** + * Sets the preferred {@link C.RoleFlags} for text tracks. + * + * @param preferredTextRoleFlags Preferred text role flags. + * @return This builder. + */ + public Builder setPreferredTextRoleFlags(@C.RoleFlags int preferredTextRoleFlags) { + this.preferredTextRoleFlags = preferredTextRoleFlags; + return this; + } + + /** + * Sets whether a text track with undetermined language should be selected if no track with + * {@link #setPreferredTextLanguages(String...) a preferred language} is available, or if the + * preferred language is unset. + * + * @param selectUndeterminedTextLanguage Whether a text track with undetermined language should + * be selected if no preferred language track is available. + * @return This builder. + */ + public Builder setSelectUndeterminedTextLanguage(boolean selectUndeterminedTextLanguage) { + this.selectUndeterminedTextLanguage = selectUndeterminedTextLanguage; + return this; + } + + // General + + /** + * Sets whether to force selection of the single lowest bitrate audio and video tracks that + * comply with all other constraints. + * + * @param forceLowestBitrate Whether to force selection of the single lowest bitrate audio and + * video tracks. + * @return This builder. + */ + public Builder setForceLowestBitrate(boolean forceLowestBitrate) { + this.forceLowestBitrate = forceLowestBitrate; + return this; + } + + /** + * Sets whether to force selection of the highest bitrate audio and video tracks that comply + * with all other constraints. + * + * @param forceHighestSupportedBitrate Whether to force selection of the highest bitrate audio + * and video tracks. + * @return This builder. + */ + public Builder setForceHighestSupportedBitrate(boolean forceHighestSupportedBitrate) { + this.forceHighestSupportedBitrate = forceHighestSupportedBitrate; + return this; + } + + /** Builds a {@link TrackSelectionParameters} instance with the selected values. */ + public TrackSelectionParameters build() { + return new TrackSelectionParameters(this); + } + + @RequiresApi(19) + private void setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettingsV19( + Context context) { + if (Util.SDK_INT < 23 && Looper.myLooper() == null) { + // Android platform bug (pre-Marshmallow) that causes RuntimeExceptions when + // CaptioningService is instantiated from a non-Looper thread. See [internal: b/143779904]. + return; + } + CaptioningManager captioningManager = + (CaptioningManager) context.getSystemService(Context.CAPTIONING_SERVICE); + if (captioningManager == null || !captioningManager.isEnabled()) { + return; + } + preferredTextRoleFlags = C.ROLE_FLAG_CAPTION | C.ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND; + Locale preferredLocale = captioningManager.getLocale(); + if (preferredLocale != null) { + preferredTextLanguages = ImmutableList.of(Util.getLocaleLanguageTag(preferredLocale)); + } + } + } + + /** + * An instance with default values, except those obtained from the {@link Context}. + * + *

        If possible, use {@link #getDefaults(Context)} instead. + * + *

        This instance will not have the following settings: + * + *

          + *
        • {@link Builder#setViewportSizeToPhysicalDisplaySize(Context, boolean) Viewport + * constraints} configured for the primary display. + *
        • {@link Builder#setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings(Context) + * Preferred text language and role flags} configured to the accessibility settings of + * {@link CaptioningManager}. + *
        + */ + @SuppressWarnings("deprecation") + public static final TrackSelectionParameters DEFAULT_WITHOUT_CONTEXT = new Builder().build(); + /** + * @deprecated This instance is not configured using {@link Context} constraints. Use {@link + * #getDefaults(Context)} instead. + */ + @Deprecated public static final TrackSelectionParameters DEFAULT = DEFAULT_WITHOUT_CONTEXT; + + public static final Creator CREATOR = + new Creator() { + + @Override + public TrackSelectionParameters createFromParcel(Parcel in) { + return new TrackSelectionParameters(in); + } + + @Override + public TrackSelectionParameters[] newArray(int size) { + return new TrackSelectionParameters[size]; + } + }; + + /** Returns an instance configured with default values. */ + public static TrackSelectionParameters getDefaults(Context context) { + return new Builder(context).build(); + } + + // Video + /** + * Maximum allowed video width in pixels. The default value is {@link Integer#MAX_VALUE} (i.e. no + * constraint). + * + *

        To constrain adaptive video track selections to be suitable for a given viewport (the region + * of the display within which video will be played), use ({@link #viewportWidth}, {@link + * #viewportHeight} and {@link #viewportOrientationMayChange}) instead. + */ + public final int maxVideoWidth; + /** + * Maximum allowed video height in pixels. The default value is {@link Integer#MAX_VALUE} (i.e. no + * constraint). + * + *

        To constrain adaptive video track selections to be suitable for a given viewport (the region + * of the display within which video will be played), use ({@link #viewportWidth}, {@link + * #viewportHeight} and {@link #viewportOrientationMayChange}) instead. + */ + public final int maxVideoHeight; + /** + * Maximum allowed video frame rate in hertz. The default value is {@link Integer#MAX_VALUE} (i.e. + * no constraint). + */ + public final int maxVideoFrameRate; + /** + * Maximum allowed video bitrate in bits per second. The default value is {@link + * Integer#MAX_VALUE} (i.e. no constraint). + */ + public final int maxVideoBitrate; + /** Minimum allowed video width in pixels. The default value is 0 (i.e. no constraint). */ + public final int minVideoWidth; + /** Minimum allowed video height in pixels. The default value is 0 (i.e. no constraint). */ + public final int minVideoHeight; + /** Minimum allowed video frame rate in hertz. The default value is 0 (i.e. no constraint). */ + public final int minVideoFrameRate; + /** + * Minimum allowed video bitrate in bits per second. The default value is 0 (i.e. no constraint). + */ + public final int minVideoBitrate; + /** + * Viewport width in pixels. Constrains video track selections for adaptive content so that only + * tracks suitable for the viewport are selected. The default value is the physical width of the + * primary display, in pixels. + */ + public final int viewportWidth; + /** + * Viewport height in pixels. Constrains video track selections for adaptive content so that only + * tracks suitable for the viewport are selected. The default value is the physical height of the + * primary display, in pixels. + */ + public final int viewportHeight; + /** + * Whether the viewport orientation may change during playback. Constrains video track selections + * for adaptive content so that only tracks suitable for the viewport are selected. The default + * value is {@code true}. + */ + public final boolean viewportOrientationMayChange; + /** + * The preferred sample MIME types for video tracks in order of preference, or an empty list for + * no preference. The default is an empty list. + */ + public final ImmutableList preferredVideoMimeTypes; + // Audio + /** + * The preferred languages for audio and forced text tracks as IETF BCP 47 conformant tags in + * order of preference. An empty list selects the default track, or the first track if there's no + * default. The default value is an empty list. + */ + public final ImmutableList preferredAudioLanguages; + /** + * The preferred {@link C.RoleFlags} for audio tracks. {@code 0} selects the default track if + * there is one, or the first track if there's no default. The default value is {@code 0}. + */ + @C.RoleFlags public final int preferredAudioRoleFlags; + /** + * Maximum allowed audio channel count. The default value is {@link Integer#MAX_VALUE} (i.e. no + * constraint). + */ + public final int maxAudioChannelCount; + /** + * Maximum allowed audio bitrate in bits per second. The default value is {@link + * Integer#MAX_VALUE} (i.e. no constraint). + */ + public final int maxAudioBitrate; + /** + * The preferred sample MIME types for audio tracks in order of preference, or an empty list for + * no preference. The default is an empty list. + */ + public final ImmutableList preferredAudioMimeTypes; + // Text + /** + * The preferred languages for text tracks as IETF BCP 47 conformant tags in order of preference. + * An empty list selects the default track if there is one, or no track otherwise. The default + * value is an empty list, or the language of the accessibility {@link CaptioningManager} if + * enabled. + */ + public final ImmutableList preferredTextLanguages; + /** + * The preferred {@link C.RoleFlags} for text tracks. {@code 0} selects the default track if there + * is one, or no track otherwise. The default value is {@code 0}, or {@link C#ROLE_FLAG_SUBTITLE} + * | {@link C#ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND} if the accessibility {@link CaptioningManager} + * is enabled. + */ + @C.RoleFlags public final int preferredTextRoleFlags; + /** + * Whether a text track with undetermined language should be selected if no track with {@link + * #preferredTextLanguages} is available, or if {@link #preferredTextLanguages} is unset. The + * default value is {@code false}. + */ + public final boolean selectUndeterminedTextLanguage; + // General + /** + * Whether to force selection of the single lowest bitrate audio and video tracks that comply with + * all other constraints. The default value is {@code false}. + */ + public final boolean forceLowestBitrate; + /** + * Whether to force selection of the highest bitrate audio and video tracks that comply with all + * other constraints. The default value is {@code false}. + */ + public final boolean forceHighestSupportedBitrate; + + protected TrackSelectionParameters(Builder builder) { + // Video + this.maxVideoWidth = builder.maxVideoWidth; + this.maxVideoHeight = builder.maxVideoHeight; + this.maxVideoFrameRate = builder.maxVideoFrameRate; + this.maxVideoBitrate = builder.maxVideoBitrate; + this.minVideoWidth = builder.minVideoWidth; + this.minVideoHeight = builder.minVideoHeight; + this.minVideoFrameRate = builder.minVideoFrameRate; + this.minVideoBitrate = builder.minVideoBitrate; + this.viewportWidth = builder.viewportWidth; + this.viewportHeight = builder.viewportHeight; + this.viewportOrientationMayChange = builder.viewportOrientationMayChange; + this.preferredVideoMimeTypes = builder.preferredVideoMimeTypes; + // Audio + this.preferredAudioLanguages = builder.preferredAudioLanguages; + this.preferredAudioRoleFlags = builder.preferredAudioRoleFlags; + this.maxAudioChannelCount = builder.maxAudioChannelCount; + this.maxAudioBitrate = builder.maxAudioBitrate; + this.preferredAudioMimeTypes = builder.preferredAudioMimeTypes; + // Text + this.preferredTextLanguages = builder.preferredTextLanguages; + this.preferredTextRoleFlags = builder.preferredTextRoleFlags; + this.selectUndeterminedTextLanguage = builder.selectUndeterminedTextLanguage; + // General + this.forceLowestBitrate = builder.forceLowestBitrate; + this.forceHighestSupportedBitrate = builder.forceHighestSupportedBitrate; + } + + /* package */ TrackSelectionParameters(Parcel in) { + ArrayList preferredAudioLanguages = new ArrayList<>(); + in.readList(preferredAudioLanguages, /* loader= */ null); + this.preferredAudioLanguages = ImmutableList.copyOf(preferredAudioLanguages); + this.preferredAudioRoleFlags = in.readInt(); + ArrayList preferredTextLanguages1 = new ArrayList<>(); + in.readList(preferredTextLanguages1, /* loader= */ null); + this.preferredTextLanguages = ImmutableList.copyOf(preferredTextLanguages1); + this.preferredTextRoleFlags = in.readInt(); + this.selectUndeterminedTextLanguage = Util.readBoolean(in); + // Video + this.maxVideoWidth = in.readInt(); + this.maxVideoHeight = in.readInt(); + this.maxVideoFrameRate = in.readInt(); + this.maxVideoBitrate = in.readInt(); + this.minVideoWidth = in.readInt(); + this.minVideoHeight = in.readInt(); + this.minVideoFrameRate = in.readInt(); + this.minVideoBitrate = in.readInt(); + this.viewportWidth = in.readInt(); + this.viewportHeight = in.readInt(); + this.viewportOrientationMayChange = Util.readBoolean(in); + ArrayList preferredVideoMimeTypes = new ArrayList<>(); + in.readList(preferredVideoMimeTypes, /* loader= */ null); + this.preferredVideoMimeTypes = ImmutableList.copyOf(preferredVideoMimeTypes); + // Audio + this.maxAudioChannelCount = in.readInt(); + this.maxAudioBitrate = in.readInt(); + ArrayList preferredAudioMimeTypes = new ArrayList<>(); + in.readList(preferredAudioMimeTypes, /* loader= */ null); + this.preferredAudioMimeTypes = ImmutableList.copyOf(preferredAudioMimeTypes); + // General + this.forceLowestBitrate = Util.readBoolean(in); + this.forceHighestSupportedBitrate = Util.readBoolean(in); + } + + /** Creates a new {@link Builder}, copying the initial values from this instance. */ + public Builder buildUpon() { + return new Builder(this); + } + + @Override + @SuppressWarnings("EqualsGetClass") + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + TrackSelectionParameters other = (TrackSelectionParameters) obj; + // Video + return maxVideoWidth == other.maxVideoWidth + && maxVideoHeight == other.maxVideoHeight + && maxVideoFrameRate == other.maxVideoFrameRate + && maxVideoBitrate == other.maxVideoBitrate + && minVideoWidth == other.minVideoWidth + && minVideoHeight == other.minVideoHeight + && minVideoFrameRate == other.minVideoFrameRate + && minVideoBitrate == other.minVideoBitrate + && viewportOrientationMayChange == other.viewportOrientationMayChange + && viewportWidth == other.viewportWidth + && viewportHeight == other.viewportHeight + && preferredVideoMimeTypes.equals(other.preferredVideoMimeTypes) + // Audio + && preferredAudioLanguages.equals(other.preferredAudioLanguages) + && preferredAudioRoleFlags == other.preferredAudioRoleFlags + && maxAudioChannelCount == other.maxAudioChannelCount + && maxAudioBitrate == other.maxAudioBitrate + && preferredAudioMimeTypes.equals(other.preferredAudioMimeTypes) + && preferredTextLanguages.equals(other.preferredTextLanguages) + && preferredTextRoleFlags == other.preferredTextRoleFlags + && selectUndeterminedTextLanguage == other.selectUndeterminedTextLanguage + // General + && forceLowestBitrate == other.forceLowestBitrate + && forceHighestSupportedBitrate == other.forceHighestSupportedBitrate; + } + + @Override + public int hashCode() { + int result = 1; + // Video + result = 31 * result + maxVideoWidth; + result = 31 * result + maxVideoHeight; + result = 31 * result + maxVideoFrameRate; + result = 31 * result + maxVideoBitrate; + result = 31 * result + minVideoWidth; + result = 31 * result + minVideoHeight; + result = 31 * result + minVideoFrameRate; + result = 31 * result + minVideoBitrate; + result = 31 * result + (viewportOrientationMayChange ? 1 : 0); + result = 31 * result + viewportWidth; + result = 31 * result + viewportHeight; + result = 31 * result + preferredVideoMimeTypes.hashCode(); + // Audio + result = 31 * result + preferredAudioLanguages.hashCode(); + result = 31 * result + preferredAudioRoleFlags; + result = 31 * result + maxAudioChannelCount; + result = 31 * result + maxAudioBitrate; + result = 31 * result + preferredAudioMimeTypes.hashCode(); + // Text + result = 31 * result + preferredTextLanguages.hashCode(); + result = 31 * result + preferredTextRoleFlags; + result = 31 * result + (selectUndeterminedTextLanguage ? 1 : 0); + // General + result = 31 * result + (forceLowestBitrate ? 1 : 0); + result = 31 * result + (forceHighestSupportedBitrate ? 1 : 0); + return result; + } + + // Parcelable implementation. + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeList(preferredAudioLanguages); + dest.writeInt(preferredAudioRoleFlags); + dest.writeList(preferredTextLanguages); + dest.writeInt(preferredTextRoleFlags); + Util.writeBoolean(dest, selectUndeterminedTextLanguage); + // Video + dest.writeInt(maxVideoWidth); + dest.writeInt(maxVideoHeight); + dest.writeInt(maxVideoFrameRate); + dest.writeInt(maxVideoBitrate); + dest.writeInt(minVideoWidth); + dest.writeInt(minVideoHeight); + dest.writeInt(minVideoFrameRate); + dest.writeInt(minVideoBitrate); + dest.writeInt(viewportWidth); + dest.writeInt(viewportHeight); + Util.writeBoolean(dest, viewportOrientationMayChange); + dest.writeList(preferredVideoMimeTypes); + // Audio + dest.writeInt(maxAudioChannelCount); + dest.writeInt(maxAudioBitrate); + dest.writeList(preferredAudioMimeTypes); + // General + Util.writeBoolean(dest, forceLowestBitrate); + Util.writeBoolean(dest, forceHighestSupportedBitrate); + } +} diff --git a/library/common/src/main/java/com/google/android/exoplayer2/upstream/DataReader.java b/library/common/src/main/java/com/google/android/exoplayer2/upstream/DataReader.java index eeddc9984e6..4b96a3ddfb9 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/upstream/DataReader.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/upstream/DataReader.java @@ -28,7 +28,7 @@ public interface DataReader { * Otherwise, the call will block until at least one byte of data has been read and the number of * bytes read is returned. * - * @param target A target array into which data should be written. + * @param buffer A target array into which data should be written. * @param offset The offset into the target array at which to write. * @param length The maximum number of bytes to read from the input. * @return The number of bytes read, or {@link C#RESULT_END_OF_INPUT} if the input has ended. This @@ -36,5 +36,5 @@ public interface DataReader { * reached, the method was interrupted, or the operation was aborted early for another reason. * @throws IOException If an error occurs reading from the input. */ - int read(byte[] target, int offset, int length) throws IOException; + int read(byte[] buffer, int offset, int length) throws IOException; } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/upstream/DataSource.java b/library/common/src/main/java/com/google/android/exoplayer2/upstream/DataSource.java index c1570028095..c6ac0a261a3 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/upstream/DataSource.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/upstream/DataSource.java @@ -26,14 +26,10 @@ /** Reads data from URI-identified resources. */ public interface DataSource extends DataReader { - /** - * A factory for {@link DataSource} instances. - */ + /** A factory for {@link DataSource} instances. */ interface Factory { - /** - * Creates a {@link DataSource} instance. - */ + /** Creates a {@link DataSource} instance. */ DataSource createDataSource(); } @@ -83,7 +79,8 @@ interface Factory { * * @return The {@link Uri} from which data is being read, or null if the source is not open. */ - @Nullable Uri getUri(); + @Nullable + Uri getUri(); /** * When the source is open, returns the response headers associated with the last {@link #open} diff --git a/library/common/src/main/java/com/google/android/exoplayer2/upstream/DataSourceException.java b/library/common/src/main/java/com/google/android/exoplayer2/upstream/DataSourceException.java index c3ccdb88d9b..073f0a46a9b 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/upstream/DataSourceException.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/upstream/DataSourceException.java @@ -16,21 +16,23 @@ package com.google.android.exoplayer2.upstream; import androidx.annotation.Nullable; +import com.google.android.exoplayer2.PlaybackException; import java.io.IOException; /** Used to specify reason of a DataSource error. */ -public final class DataSourceException extends IOException { +public class DataSourceException extends IOException { /** * Returns whether the given {@link IOException} was caused by a {@link DataSourceException} whose - * {@link #reason} is {@link #POSITION_OUT_OF_RANGE} in its cause stack. + * {@link #reason} is {@link PlaybackException#ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE} in its + * cause stack. */ public static boolean isCausedByPositionOutOfRange(IOException e) { @Nullable Throwable cause = e; while (cause != null) { if (cause instanceof DataSourceException) { int reason = ((DataSourceException) cause).reason; - if (reason == DataSourceException.POSITION_OUT_OF_RANGE) { + if (reason == PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE) { return true; } } @@ -42,20 +44,66 @@ public static boolean isCausedByPositionOutOfRange(IOException e) { /** * Indicates that the {@link DataSpec#position starting position} of the request was outside the * bounds of the data. + * + * @deprecated Use {@link PlaybackException#ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE}. + */ + @Deprecated + public static final int POSITION_OUT_OF_RANGE = + PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE; + + /** + * The reason of this {@link DataSourceException}, should be one of the {@code ERROR_CODE_IO_*} in + * {@link PlaybackException.ErrorCode}. + */ + @PlaybackException.ErrorCode public final int reason; + + /** + * Constructs a DataSourceException. + * + * @param reason Reason of the error, should be one of the {@code ERROR_CODE_IO_*} in {@link + * PlaybackException.ErrorCode}. + */ + public DataSourceException(@PlaybackException.ErrorCode int reason) { + this.reason = reason; + } + + /** + * Constructs a DataSourceException. + * + * @param cause The error cause. + * @param reason Reason of the error, should be one of the {@code ERROR_CODE_IO_*} in {@link + * PlaybackException.ErrorCode}. */ - public static final int POSITION_OUT_OF_RANGE = 0; + public DataSourceException(@Nullable Throwable cause, @PlaybackException.ErrorCode int reason) { + super(cause); + this.reason = reason; + } /** - * The reason of this {@link DataSourceException}. It can only be {@link #POSITION_OUT_OF_RANGE}. + * Constructs a DataSourceException. + * + * @param message The error message. + * @param reason Reason of the error, should be one of the {@code ERROR_CODE_IO_*} in {@link + * PlaybackException.ErrorCode}. */ - public final int reason; + public DataSourceException(@Nullable String message, @PlaybackException.ErrorCode int reason) { + super(message); + this.reason = reason; + } /** * Constructs a DataSourceException. * - * @param reason Reason of the error. It can only be {@link #POSITION_OUT_OF_RANGE}. + * @param message The error message. + * @param cause The error cause. + * @param reason Reason of the error, should be one of the {@code ERROR_CODE_IO_*} in {@link + * PlaybackException.ErrorCode}. */ - public DataSourceException(int reason) { + public DataSourceException( + @Nullable String message, + @Nullable Throwable cause, + @PlaybackException.ErrorCode int reason) { + super(message, cause); this.reason = reason; } } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java b/library/common/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java index d484779d365..dde08355178 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java @@ -360,9 +360,7 @@ public static String getStringForHttpMethod(@HttpMethod int httpMethod) { /** The position of the data when read from {@link #uri}. */ public final long position; - /** - * The length of the data, or {@link C#LENGTH_UNSET}. - */ + /** The length of the data, or {@link C#LENGTH_UNSET}. */ public final long length; /** diff --git a/library/common/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.java b/library/common/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.java index 88193c2646e..d2c6b5e993b 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.java @@ -24,10 +24,10 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.upstream.DataSpec.HttpMethod; import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Util; -import com.google.common.base.Ascii; import com.google.common.base.Predicate; import com.google.common.net.HttpHeaders; import java.io.IOException; @@ -36,8 +36,8 @@ import java.io.OutputStream; import java.lang.reflect.Method; import java.net.HttpURLConnection; +import java.net.MalformedURLException; import java.net.NoRouteToHostException; -import java.net.ProtocolException; import java.net.URL; import java.util.Collections; import java.util.HashMap; @@ -69,6 +69,7 @@ public static final class Factory implements HttpDataSource.Factory { private int connectTimeoutMs; private int readTimeoutMs; private boolean allowCrossProtocolRedirects; + private boolean keepPostFor302Redirects; /** Creates an instance. */ public Factory() { @@ -175,6 +176,15 @@ public Factory setTransferListener(@Nullable TransferListener transferListener) return this; } + /** + * Sets whether we should keep the POST method and body when we have HTTP 302 redirects for a + * POST request. + */ + public Factory setKeepPostFor302Redirects(boolean keepPostFor302Redirects) { + this.keepPostFor302Redirects = keepPostFor302Redirects; + return this; + } + @Override public DefaultHttpDataSource createDataSource() { DefaultHttpDataSource dataSource = @@ -184,7 +194,8 @@ public DefaultHttpDataSource createDataSource() { readTimeoutMs, allowCrossProtocolRedirects, defaultRequestProperties, - contentTypePredicate); + contentTypePredicate, + keepPostFor302Redirects); if (transferListener != null) { dataSource.addTransferListener(transferListener); } @@ -194,9 +205,7 @@ public DefaultHttpDataSource createDataSource() { /** The default connection timeout, in milliseconds. */ public static final int DEFAULT_CONNECT_TIMEOUT_MILLIS = 8 * 1000; - /** - * The default read timeout, in milliseconds. - */ + /** The default read timeout, in milliseconds. */ public static final int DEFAULT_READ_TIMEOUT_MILLIS = 8 * 1000; private static final String TAG = "DefaultHttpDataSource"; @@ -211,6 +220,7 @@ public DefaultHttpDataSource createDataSource() { @Nullable private final String userAgent; @Nullable private final RequestProperties defaultRequestProperties; private final RequestProperties requestProperties; + private final boolean keepPostFor302Redirects; @Nullable private Predicate contentTypePredicate; @Nullable private DataSpec dataSpec; @@ -262,7 +272,8 @@ public DefaultHttpDataSource( readTimeoutMillis, allowCrossProtocolRedirects, defaultRequestProperties, - /* contentTypePredicate= */ null); + /* contentTypePredicate= */ null, + /* keepPostFor302Redirects= */ false); } private DefaultHttpDataSource( @@ -271,7 +282,8 @@ private DefaultHttpDataSource( int readTimeoutMillis, boolean allowCrossProtocolRedirects, @Nullable RequestProperties defaultRequestProperties, - @Nullable Predicate contentTypePredicate) { + @Nullable Predicate contentTypePredicate, + boolean keepPostFor302Redirects) { super(/* isNetwork= */ true); this.userAgent = userAgent; this.connectTimeoutMillis = connectTimeoutMillis; @@ -280,6 +292,7 @@ private DefaultHttpDataSource( this.defaultRequestProperties = defaultRequestProperties; this.contentTypePredicate = contentTypePredicate; this.requestProperties = new RequestProperties(); + this.keepPostFor302Redirects = keepPostFor302Redirects; } /** @@ -325,9 +338,7 @@ public void clearAllRequestProperties() { requestProperties.clear(); } - /** - * Opens the source to read the specified data. - */ + /** Opens the source to read the specified data. */ @Override public long open(DataSpec dataSpec) throws HttpDataSourceException { this.dataSpec = dataSpec; @@ -335,27 +346,17 @@ public long open(DataSpec dataSpec) throws HttpDataSourceException { bytesToRead = 0; transferInitializing(dataSpec); - try { - connection = makeConnection(dataSpec); - } catch (IOException e) { - @Nullable String message = e.getMessage(); - if (message != null - && Ascii.toLowerCase(message).matches("cleartext http traffic.*not permitted.*")) { - throw new CleartextNotPermittedException(e, dataSpec); - } - throw new HttpDataSourceException( - "Unable to connect", e, dataSpec, HttpDataSourceException.TYPE_OPEN); - } - - HttpURLConnection connection = this.connection; String responseMessage; + HttpURLConnection connection; try { + this.connection = makeConnection(dataSpec); + connection = this.connection; responseCode = connection.getResponseCode(); responseMessage = connection.getResponseMessage(); } catch (IOException e) { closeConnectionQuietly(); - throw new HttpDataSourceException( - "Unable to connect", e, dataSpec, HttpDataSourceException.TYPE_OPEN); + throw HttpDataSourceException.createForIOException( + e, dataSpec, HttpDataSourceException.TYPE_OPEN); } // Check for a valid response code. @@ -380,13 +381,13 @@ public long open(DataSpec dataSpec) throws HttpDataSourceException { errorResponseBody = Util.EMPTY_BYTE_ARRAY; } closeConnectionQuietly(); - InvalidResponseCodeException exception = - new InvalidResponseCodeException( - responseCode, responseMessage, headers, dataSpec, errorResponseBody); - if (responseCode == 416) { - exception.initCause(new DataSourceException(DataSourceException.POSITION_OUT_OF_RANGE)); - } - throw exception; + @Nullable + IOException cause = + responseCode == 416 + ? new DataSourceException(PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE) + : null; + throw new InvalidResponseCodeException( + responseCode, responseMessage, cause, headers, dataSpec, errorResponseBody); } // Check for a valid content type. @@ -411,8 +412,8 @@ public long open(DataSpec dataSpec) throws HttpDataSourceException { HttpUtil.getContentLength( connection.getHeaderField(HttpHeaders.CONTENT_LENGTH), connection.getHeaderField(HttpHeaders.CONTENT_RANGE)); - bytesToRead = contentLength != C.LENGTH_UNSET ? (contentLength - bytesToSkip) - : C.LENGTH_UNSET; + bytesToRead = + contentLength != C.LENGTH_UNSET ? (contentLength - bytesToSkip) : C.LENGTH_UNSET; } } else { // Gzip is enabled. If the server opts to use gzip then the content length in the response @@ -428,30 +429,40 @@ public long open(DataSpec dataSpec) throws HttpDataSourceException { } } catch (IOException e) { closeConnectionQuietly(); - throw new HttpDataSourceException(e, dataSpec, HttpDataSourceException.TYPE_OPEN); + throw new HttpDataSourceException( + e, + dataSpec, + PlaybackException.ERROR_CODE_IO_UNSPECIFIED, + HttpDataSourceException.TYPE_OPEN); } opened = true; transferStarted(dataSpec); try { - if (!skipFully(bytesToSkip)) { - throw new DataSourceException(DataSourceException.POSITION_OUT_OF_RANGE); - } + skipFully(bytesToSkip, dataSpec); } catch (IOException e) { closeConnectionQuietly(); - throw new HttpDataSourceException(e, dataSpec, HttpDataSourceException.TYPE_OPEN); + + if (e instanceof HttpDataSourceException) { + throw (HttpDataSourceException) e; + } + throw new HttpDataSourceException( + e, + dataSpec, + PlaybackException.ERROR_CODE_IO_UNSPECIFIED, + HttpDataSourceException.TYPE_OPEN); } return bytesToRead; } @Override - public int read(byte[] buffer, int offset, int readLength) throws HttpDataSourceException { + public int read(byte[] buffer, int offset, int length) throws HttpDataSourceException { try { - return readInternal(buffer, offset, readLength); + return readInternal(buffer, offset, length); } catch (IOException e) { - throw new HttpDataSourceException( + throw HttpDataSourceException.createForIOException( e, castNonNull(dataSpec), HttpDataSourceException.TYPE_READ); } } @@ -468,7 +479,10 @@ public void close() throws HttpDataSourceException { inputStream.close(); } catch (IOException e) { throw new HttpDataSourceException( - e, castNonNull(dataSpec), HttpDataSourceException.TYPE_CLOSE); + e, + castNonNull(dataSpec), + PlaybackException.ERROR_CODE_IO_UNSPECIFIED, + HttpDataSourceException.TYPE_CLOSE); } } } finally { @@ -481,9 +495,7 @@ public void close() throws HttpDataSourceException { } } - /** - * Establishes a connection, following redirects to do so where permitted. - */ + /** Establishes a connection, following redirects to do so where permitted. */ private HttpURLConnection makeConnection(DataSpec dataSpec) throws IOException { URL url = new URL(dataSpec.uri.toString()); @HttpMethod int httpMethod = dataSpec.httpMethod; @@ -492,7 +504,7 @@ private HttpURLConnection makeConnection(DataSpec dataSpec) throws IOException { long length = dataSpec.length; boolean allowGzip = dataSpec.isFlagSet(DataSpec.FLAG_ALLOW_GZIP); - if (!allowCrossProtocolRedirects) { + if (!allowCrossProtocolRedirects && !keepPostFor302Redirects) { // HttpURLConnection disallows cross-protocol redirects, but otherwise performs redirection // automatically. This is the behavior we want, so use it. return makeConnection( @@ -506,7 +518,8 @@ private HttpURLConnection makeConnection(DataSpec dataSpec) throws IOException { dataSpec.httpRequestHeaders); } - // We need to handle redirects ourselves to allow cross-protocol redirects. + // We need to handle redirects ourselves to allow cross-protocol redirects or to keep the POST + // request method for 302. int redirectCount = 0; while (redirectCount++ <= MAX_REDIRECTS) { HttpURLConnection connection = @@ -529,24 +542,32 @@ private HttpURLConnection makeConnection(DataSpec dataSpec) throws IOException { || responseCode == HTTP_STATUS_TEMPORARY_REDIRECT || responseCode == HTTP_STATUS_PERMANENT_REDIRECT)) { connection.disconnect(); - url = handleRedirect(url, location); + url = handleRedirect(url, location, dataSpec); } else if (httpMethod == DataSpec.HTTP_METHOD_POST && (responseCode == HttpURLConnection.HTTP_MULT_CHOICE || responseCode == HttpURLConnection.HTTP_MOVED_PERM || responseCode == HttpURLConnection.HTTP_MOVED_TEMP || responseCode == HttpURLConnection.HTTP_SEE_OTHER)) { - // POST request follows the redirect and is transformed into a GET request. connection.disconnect(); - httpMethod = DataSpec.HTTP_METHOD_GET; - httpBody = null; - url = handleRedirect(url, location); + boolean shouldKeepPost = + keepPostFor302Redirects && responseCode == HttpURLConnection.HTTP_MOVED_TEMP; + if (!shouldKeepPost) { + // POST request follows the redirect and is transformed into a GET request. + httpMethod = DataSpec.HTTP_METHOD_GET; + httpBody = null; + } + url = handleRedirect(url, location, dataSpec); } else { return connection; } } // If we get here we've been redirected more times than are permitted. - throw new NoRouteToHostException("Too many redirects: " + redirectCount); + throw new HttpDataSourceException( + new NoRouteToHostException("Too many redirects: " + redirectCount), + dataSpec, + PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED, + HttpDataSourceException.TYPE_OPEN); } /** @@ -621,27 +642,51 @@ private HttpURLConnection makeConnection( * * @param originalUrl The original URL. * @param location The Location header in the response. May be {@code null}. + * @param dataSpec The {@link DataSpec}. * @return The next URL. - * @throws IOException If redirection isn't possible. + * @throws HttpDataSourceException If redirection isn't possible. */ - private static URL handleRedirect(URL originalUrl, @Nullable String location) throws IOException { + private URL handleRedirect(URL originalUrl, @Nullable String location, DataSpec dataSpec) + throws HttpDataSourceException { if (location == null) { - throw new ProtocolException("Null location redirect"); + throw new HttpDataSourceException( + "Null location redirect", + dataSpec, + PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED, + HttpDataSourceException.TYPE_OPEN); } // Form the new url. - URL url = new URL(originalUrl, location); + URL url; + try { + url = new URL(originalUrl, location); + } catch (MalformedURLException e) { + throw new HttpDataSourceException( + e, + dataSpec, + PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED, + HttpDataSourceException.TYPE_OPEN); + } + // Check that the protocol of the new url is supported. String protocol = url.getProtocol(); if (!"https".equals(protocol) && !"http".equals(protocol)) { - throw new ProtocolException("Unsupported protocol redirect: " + protocol); - } - // Currently this method is only called if allowCrossProtocolRedirects is true, and so the code - // below isn't required. If we ever decide to handle redirects ourselves when cross-protocol - // redirects are disabled, we'll need to uncomment this block of code. - // if (!allowCrossProtocolRedirects && !protocol.equals(originalUrl.getProtocol())) { - // throw new ProtocolException("Disallowed cross-protocol redirect (" - // + originalUrl.getProtocol() + " to " + protocol + ")"); - // } + throw new HttpDataSourceException( + "Unsupported protocol redirect: " + protocol, + dataSpec, + PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED, + HttpDataSourceException.TYPE_OPEN); + } + if (!allowCrossProtocolRedirects && !protocol.equals(originalUrl.getProtocol())) { + throw new HttpDataSourceException( + "Disallowed cross-protocol redirect (" + + originalUrl.getProtocol() + + " to " + + protocol + + ")", + dataSpec, + PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED, + HttpDataSourceException.TYPE_OPEN); + } return url; } @@ -649,37 +694,42 @@ private static URL handleRedirect(URL originalUrl, @Nullable String location) th * Attempts to skip the specified number of bytes in full. * * @param bytesToSkip The number of bytes to skip. - * @throws InterruptedIOException If the thread is interrupted during the operation. - * @throws IOException If an error occurs reading from the source. - * @return Whether the bytes were skipped in full. If {@code false} then the data ended before the - * specified number of bytes were skipped. Always {@code true} if {@code bytesToSkip == 0}. + * @param dataSpec The {@link DataSpec}. + * @throws IOException If the thread is interrupted during the operation, or if the data ended + * before skipping the specified number of bytes. */ - private boolean skipFully(long bytesToSkip) throws IOException { + private void skipFully(long bytesToSkip, DataSpec dataSpec) throws IOException { if (bytesToSkip == 0) { - return true; + return; } byte[] skipBuffer = new byte[4096]; while (bytesToSkip > 0) { int readLength = (int) min(bytesToSkip, skipBuffer.length); int read = castNonNull(inputStream).read(skipBuffer, 0, readLength); if (Thread.currentThread().isInterrupted()) { - throw new InterruptedIOException(); + throw new HttpDataSourceException( + new InterruptedIOException(), + dataSpec, + PlaybackException.ERROR_CODE_IO_UNSPECIFIED, + HttpDataSourceException.TYPE_OPEN); } if (read == -1) { - return false; + throw new HttpDataSourceException( + dataSpec, + PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE, + HttpDataSourceException.TYPE_OPEN); } bytesToSkip -= read; bytesTransferred(read); } - return true; } /** - * Reads up to {@code length} bytes of data and stores them into {@code buffer}, starting at - * index {@code offset}. - *

        - * This method blocks until at least one byte of data can be read, the end of the opened range is - * detected, or an exception is thrown. + * Reads up to {@code length} bytes of data and stores them into {@code buffer}, starting at index + * {@code offset}. + * + *

        This method blocks until at least one byte of data can be read, the end of the opened range + * is detected, or an exception is thrown. * * @param buffer The buffer into which the read data should be stored. * @param offset The start offset into {@code buffer} at which data should be written. @@ -756,9 +806,7 @@ private static void maybeTerminateInputStream( } } - /** - * Closes the current connection quietly, if there is one. - */ + /** Closes the current connection quietly, if there is one. */ private void closeConnectionQuietly() { if (connection != null) { try { diff --git a/library/common/src/main/java/com/google/android/exoplayer2/upstream/HttpDataSource.java b/library/common/src/main/java/com/google/android/exoplayer2/upstream/HttpDataSource.java index dbaa686066f..150d9833481 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/upstream/HttpDataSource.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/upstream/HttpDataSource.java @@ -18,13 +18,16 @@ import android.text.TextUtils; import androidx.annotation.IntDef; import androidx.annotation.Nullable; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.util.Util; import com.google.common.base.Ascii; import com.google.common.base.Predicate; import java.io.IOException; +import java.io.InterruptedIOException; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.net.SocketTimeoutException; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -33,9 +36,7 @@ /** An HTTP {@link DataSource}. */ public interface HttpDataSource extends DataSource { - /** - * A factory for {@link HttpDataSource} instances. - */ + /** A factory for {@link HttpDataSource} instances. */ interface Factory extends DataSource.Factory { @Override @@ -61,9 +62,9 @@ interface Factory extends DataSource.Factory { } /** - * Stores HTTP request properties (aka HTTP headers) and provides methods to modify the headers - * in a thread safe way to avoid the potential of creating snapshots of an inconsistent or - * unintended state. + * Stores HTTP request properties (aka HTTP headers) and provides methods to modify the headers in + * a thread safe way to avoid the potential of creating snapshots of an inconsistent or unintended + * state. */ final class RequestProperties { @@ -119,9 +120,7 @@ public synchronized void remove(String name) { requestProperties.remove(name); } - /** - * Clears all request properties. - */ + /** Clears all request properties. */ public synchronized void clear() { requestPropertiesSnapshot = null; requestProperties.clear(); @@ -191,51 +190,176 @@ protected abstract HttpDataSource createDataSourceInternal( && !contentType.contains("xml"); }; - /** - * Thrown when an error is encountered when trying to read from a {@link HttpDataSource}. - */ - class HttpDataSourceException extends IOException { + /** Thrown when an error is encountered when trying to read from a {@link HttpDataSource}. */ + class HttpDataSourceException extends DataSourceException { + /** + * The type of operation that produced the error. One of {@link #TYPE_READ}, {@link #TYPE_OPEN} + * {@link #TYPE_CLOSE}. + */ @Documented @Retention(RetentionPolicy.SOURCE) @IntDef({TYPE_OPEN, TYPE_READ, TYPE_CLOSE}) public @interface Type {} + /** The error occurred reading data from a {@code HttpDataSource}. */ public static final int TYPE_OPEN = 1; + /** The error occurred in opening a {@code HttpDataSource}. */ public static final int TYPE_READ = 2; + /** The error occurred in closing a {@code HttpDataSource}. */ public static final int TYPE_CLOSE = 3; - @Type public final int type; - /** - * The {@link DataSpec} associated with the current connection. + * Returns a {@code HttpDataSourceException} whose error code is assigned according to the cause + * and type. */ + public static HttpDataSourceException createForIOException( + IOException cause, DataSpec dataSpec, @Type int type) { + @PlaybackException.ErrorCode int errorCode; + @Nullable String message = cause.getMessage(); + if (cause instanceof SocketTimeoutException) { + errorCode = PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT; + } else if (cause instanceof InterruptedIOException) { + // An interruption means the operation is being cancelled, in which case this exception + // should not cause the player to fail. If it does, it likely means that the owner of the + // operation is failing to swallow the interruption, which makes us enter an invalid state. + errorCode = PlaybackException.ERROR_CODE_FAILED_RUNTIME_CHECK; + } else if (message != null + && Ascii.toLowerCase(message).matches("cleartext.*not permitted.*")) { + errorCode = PlaybackException.ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED; + } else { + errorCode = PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED; + } + return errorCode == PlaybackException.ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED + ? new CleartextNotPermittedException(cause, dataSpec) + : new HttpDataSourceException(cause, dataSpec, errorCode, type); + } + + /** The {@link DataSpec} associated with the current connection. */ public final DataSpec dataSpec; + @Type public final int type; + + /** + * @deprecated Use {@link #HttpDataSourceException(DataSpec, int, int) + * HttpDataSourceException(DataSpec, PlaybackException.ERROR_CODE_IO_UNSPECIFIED, int)}. + */ + @Deprecated public HttpDataSourceException(DataSpec dataSpec, @Type int type) { - super(); + this(dataSpec, PlaybackException.ERROR_CODE_IO_UNSPECIFIED, type); + } + + /** + * Constructs an HttpDataSourceException. + * + * @param dataSpec The {@link DataSpec}. + * @param errorCode Reason of the error, should be one of the {@code ERROR_CODE_IO_*} in {@link + * PlaybackException.ErrorCode}. + * @param type See {@link Type}. + */ + public HttpDataSourceException( + DataSpec dataSpec, @PlaybackException.ErrorCode int errorCode, @Type int type) { + super(assignErrorCode(errorCode, type)); this.dataSpec = dataSpec; this.type = type; } + /** + * @deprecated Use {@link #HttpDataSourceException(String, DataSpec, int, int) + * HttpDataSourceException(String, DataSpec, PlaybackException.ERROR_CODE_IO_UNSPECIFIED, + * int)}. + */ + @Deprecated public HttpDataSourceException(String message, DataSpec dataSpec, @Type int type) { - super(message); + this(message, dataSpec, PlaybackException.ERROR_CODE_IO_UNSPECIFIED, type); + } + + /** + * Constructs an HttpDataSourceException. + * + * @param message The error message. + * @param dataSpec The {@link DataSpec}. + * @param errorCode Reason of the error, should be one of the {@code ERROR_CODE_IO_*} in {@link + * PlaybackException.ErrorCode}. + * @param type See {@link Type}. + */ + public HttpDataSourceException( + String message, + DataSpec dataSpec, + @PlaybackException.ErrorCode int errorCode, + @Type int type) { + super(message, assignErrorCode(errorCode, type)); this.dataSpec = dataSpec; this.type = type; } + /** + * @deprecated Use {@link #HttpDataSourceException(IOException, DataSpec, int, int) + * HttpDataSourceException(IOException, DataSpec, + * PlaybackException.ERROR_CODE_IO_UNSPECIFIED, int)}. + */ + @Deprecated public HttpDataSourceException(IOException cause, DataSpec dataSpec, @Type int type) { - super(cause); + this(cause, dataSpec, PlaybackException.ERROR_CODE_IO_UNSPECIFIED, type); + } + + /** + * Constructs an HttpDataSourceException. + * + * @param cause The error cause. + * @param dataSpec The {@link DataSpec}. + * @param errorCode Reason of the error, should be one of the {@code ERROR_CODE_IO_*} in {@link + * PlaybackException.ErrorCode}. + * @param type See {@link Type}. + */ + public HttpDataSourceException( + IOException cause, + DataSpec dataSpec, + @PlaybackException.ErrorCode int errorCode, + @Type int type) { + super(cause, assignErrorCode(errorCode, type)); this.dataSpec = dataSpec; this.type = type; } - public HttpDataSourceException(String message, IOException cause, DataSpec dataSpec, + /** + * @deprecated Use {@link #HttpDataSourceException(String, IOException, DataSpec, int, int) + * HttpDataSourceException(String, IOException, DataSpec, + * PlaybackException.ERROR_CODE_IO_UNSPECIFIED, int)}. + */ + @Deprecated + public HttpDataSourceException( + String message, IOException cause, DataSpec dataSpec, @Type int type) { + this(message, cause, dataSpec, PlaybackException.ERROR_CODE_IO_UNSPECIFIED, type); + } + + /** + * Constructs an HttpDataSourceException. + * + * @param message The error message. + * @param cause The error cause. + * @param dataSpec The {@link DataSpec}. + * @param errorCode Reason of the error, should be one of the {@code ERROR_CODE_IO_*} in {@link + * PlaybackException.ErrorCode}. + * @param type See {@link Type}. + */ + public HttpDataSourceException( + String message, + @Nullable IOException cause, + DataSpec dataSpec, + @PlaybackException.ErrorCode int errorCode, @Type int type) { - super(message, cause); + super(message, cause, assignErrorCode(errorCode, type)); this.dataSpec = dataSpec; this.type = type; } + + @PlaybackException.ErrorCode + private static int assignErrorCode(@PlaybackException.ErrorCode int errorCode, @Type int type) { + return errorCode == PlaybackException.ERROR_CODE_IO_UNSPECIFIED && type == TYPE_OPEN + ? PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED + : errorCode; + } } /** @@ -252,19 +376,22 @@ public CleartextNotPermittedException(IOException cause, DataSpec dataSpec) { + " https://exoplayer.dev/issues/cleartext-not-permitted", cause, dataSpec, + PlaybackException.ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED, TYPE_OPEN); } } - /** - * Thrown when the content type is invalid. - */ + /** Thrown when the content type is invalid. */ final class InvalidContentTypeException extends HttpDataSourceException { public final String contentType; public InvalidContentTypeException(String contentType, DataSpec dataSpec) { - super("Invalid content type: " + contentType, dataSpec, TYPE_OPEN); + super( + "Invalid content type: " + contentType, + dataSpec, + PlaybackException.ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE, + TYPE_OPEN); this.contentType = contentType; } } @@ -274,24 +401,21 @@ public InvalidContentTypeException(String contentType, DataSpec dataSpec) { */ final class InvalidResponseCodeException extends HttpDataSourceException { - /** - * The response code that was outside of the 2xx range. - */ + /** The response code that was outside of the 2xx range. */ public final int responseCode; /** The http status message. */ @Nullable public final String responseMessage; - /** - * An unmodifiable map of the response header fields and values. - */ + /** An unmodifiable map of the response header fields and values. */ public final Map> headerFields; /** The response body. */ public final byte[] responseBody; /** - * @deprecated Use {@link #InvalidResponseCodeException(int, String, Map, DataSpec, byte[])}. + * @deprecated Use {@link #InvalidResponseCodeException(int, String, IOException, Map, DataSpec, + * byte[])}. */ @Deprecated public InvalidResponseCodeException( @@ -299,13 +423,15 @@ public InvalidResponseCodeException( this( responseCode, /* responseMessage= */ null, + /* cause= */ null, headerFields, dataSpec, /* responseBody= */ Util.EMPTY_BYTE_ARRAY); } /** - * @deprecated Use {@link #InvalidResponseCodeException(int, String, Map, DataSpec, byte[])}. + * @deprecated Use {@link #InvalidResponseCodeException(int, String, IOException, Map, DataSpec, + * byte[])}. */ @Deprecated public InvalidResponseCodeException( @@ -316,6 +442,7 @@ public InvalidResponseCodeException( this( responseCode, responseMessage, + /* cause= */ null, headerFields, dataSpec, /* responseBody= */ Util.EMPTY_BYTE_ARRAY); @@ -324,16 +451,21 @@ public InvalidResponseCodeException( public InvalidResponseCodeException( int responseCode, @Nullable String responseMessage, + @Nullable IOException cause, Map> headerFields, DataSpec dataSpec, byte[] responseBody) { - super("Response code: " + responseCode, dataSpec, TYPE_OPEN); + super( + "Response code: " + responseCode, + cause, + dataSpec, + PlaybackException.ERROR_CODE_IO_BAD_HTTP_STATUS, + TYPE_OPEN); this.responseCode = responseCode; this.responseMessage = responseMessage; this.headerFields = headerFields; this.responseBody = responseBody; } - } /** @@ -350,7 +482,7 @@ public InvalidResponseCodeException( void close() throws HttpDataSourceException; @Override - int read(byte[] buffer, int offset, int readLength) throws HttpDataSourceException; + int read(byte[] buffer, int offset, int length) throws HttpDataSourceException; /** * Sets the value of a request header. The value will be used for subsequent connections @@ -373,9 +505,7 @@ public InvalidResponseCodeException( */ void clearRequestProperty(String name); - /** - * Clears all request headers that were set by {@link #setRequestProperty(String, String)}. - */ + /** Clears all request headers that were set by {@link #setRequestProperty(String, String)}. */ void clearAllRequestProperties(); /** diff --git a/library/common/src/main/java/com/google/android/exoplayer2/upstream/TransferListener.java b/library/common/src/main/java/com/google/android/exoplayer2/upstream/TransferListener.java index a8971e71a41..806efca73fa 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/upstream/TransferListener.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/upstream/TransferListener.java @@ -61,7 +61,7 @@ public interface TransferListener { * @param source The source performing the transfer. * @param dataSpec Describes the data being transferred. * @param isNetwork Whether the data is transferred through a network. - * @param bytesTransferred The number of bytes transferred since the previous call to this method + * @param bytesTransferred The number of bytes transferred since the previous call to this method. */ void onBytesTransferred( DataSource source, DataSpec dataSpec, boolean isNetwork, int bytesTransferred); diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/Assertions.java b/library/common/src/main/java/com/google/android/exoplayer2/util/Assertions.java index 0bb65e55e00..64496358cf0 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/Assertions.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/Assertions.java @@ -108,7 +108,7 @@ public static void checkState(boolean expression, Object errorMessage) { * @return The non-null reference that was validated. * @throws IllegalStateException If {@code reference} is null. */ - @SuppressWarnings({"contracts.postcondition.not.satisfied", "return.type.incompatible"}) + @SuppressWarnings({"nullness:contracts.postcondition", "nullness:return"}) @EnsuresNonNull({"#1"}) @Pure public static T checkStateNotNull(@Nullable T reference) { @@ -128,7 +128,7 @@ public static T checkStateNotNull(@Nullable T reference) { * @return The non-null reference that was validated. * @throws IllegalStateException If {@code reference} is null. */ - @SuppressWarnings({"contracts.postcondition.not.satisfied", "return.type.incompatible"}) + @SuppressWarnings({"nullness:contracts.postcondition", "nullness:return"}) @EnsuresNonNull({"#1"}) @Pure public static T checkStateNotNull(@Nullable T reference, Object errorMessage) { @@ -146,7 +146,7 @@ public static T checkStateNotNull(@Nullable T reference, Object errorMessage * @return The non-null reference that was validated. * @throws NullPointerException If {@code reference} is null. */ - @SuppressWarnings({"contracts.postcondition.not.satisfied", "return.type.incompatible"}) + @SuppressWarnings({"nullness:contracts.postcondition", "nullness:return"}) @EnsuresNonNull({"#1"}) @Pure public static T checkNotNull(@Nullable T reference) { @@ -166,7 +166,7 @@ public static T checkNotNull(@Nullable T reference) { * @return The non-null reference that was validated. * @throws NullPointerException If {@code reference} is null. */ - @SuppressWarnings({"contracts.postcondition.not.satisfied", "return.type.incompatible"}) + @SuppressWarnings({"nullness:contracts.postcondition", "nullness:return"}) @EnsuresNonNull({"#1"}) @Pure public static T checkNotNull(@Nullable T reference, Object errorMessage) { @@ -183,7 +183,7 @@ public static T checkNotNull(@Nullable T reference, Object errorMessage) { * @return The non-null, non-empty string that was validated. * @throws IllegalArgumentException If {@code string} is null or 0-length. */ - @SuppressWarnings({"contracts.postcondition.not.satisfied", "return.type.incompatible"}) + @SuppressWarnings({"nullness:contracts.postcondition", "nullness:return"}) @EnsuresNonNull({"#1"}) @Pure public static String checkNotEmpty(@Nullable String string) { @@ -202,7 +202,7 @@ public static String checkNotEmpty(@Nullable String string) { * @return The non-null, non-empty string that was validated. * @throws IllegalArgumentException If {@code string} is null or 0-length. */ - @SuppressWarnings({"contracts.postcondition.not.satisfied", "return.type.incompatible"}) + @SuppressWarnings({"nullness:contracts.postcondition", "nullness:return"}) @EnsuresNonNull({"#1"}) @Pure public static String checkNotEmpty(@Nullable String string, Object errorMessage) { @@ -224,5 +224,4 @@ public static void checkMainThread() { throw new IllegalStateException("Not in applications main thread"); } } - } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/BundleUtil.java b/library/common/src/main/java/com/google/android/exoplayer2/util/BundleUtil.java index 1c1e139d809..fcf07a8901f 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/BundleUtil.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/BundleUtil.java @@ -61,7 +61,7 @@ public static void putBinder(Bundle bundle, @Nullable String key, @Nullable IBin } // Method.invoke may take null "key". - @SuppressWarnings("nullness:argument.type.incompatible") + @SuppressWarnings("nullness:argument") @Nullable private static IBinder getBinderByReflection(Bundle bundle, @Nullable String key) { @Nullable Method getIBinder = getIBinderMethod; @@ -85,7 +85,7 @@ private static IBinder getBinderByReflection(Bundle bundle, @Nullable String key } // Method.invoke may take null "key" and "binder". - @SuppressWarnings("nullness:argument.type.incompatible") + @SuppressWarnings("nullness:argument") private static void putBinderByReflection( Bundle bundle, @Nullable String key, @Nullable IBinder binder) { @Nullable Method putIBinder = putIBinderMethod; diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/BundleableUtils.java b/library/common/src/main/java/com/google/android/exoplayer2/util/BundleableUtils.java new file mode 100644 index 00000000000..adc9514f7d7 --- /dev/null +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/BundleableUtils.java @@ -0,0 +1,92 @@ +/* + * 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 com.google.android.exoplayer2.util; + +import android.os.Bundle; +import androidx.annotation.Nullable; +import com.google.android.exoplayer2.Bundleable; +import com.google.common.collect.ImmutableList; +import java.util.ArrayList; +import java.util.List; + +/** Utilities for {@link Bundleable}. */ +public final class BundleableUtils { + + /** + * Converts a {@link Bundleable} to a {@link Bundle}. It's a convenience wrapper of {@link + * Bundleable#toBundle} that can take nullable values. + */ + @Nullable + public static Bundle toNullableBundle(@Nullable Bundleable bundleable) { + return bundleable == null ? null : bundleable.toBundle(); + } + + /** + * Converts a {@link Bundle} to a {@link Bundleable}. It's a convenience wrapper of {@link + * Bundleable.Creator#fromBundle} that can take nullable values. + */ + @Nullable + public static T fromNullableBundle( + Bundleable.Creator creator, @Nullable Bundle bundle) { + return bundle == null ? null : creator.fromBundle(bundle); + } + + /** + * Converts a {@link Bundle} to a {@link Bundleable}. It's a convenience wrapper of {@link + * Bundleable.Creator#fromBundle} that provides default value to ensure non-null. + */ + public static T fromNullableBundle( + Bundleable.Creator creator, @Nullable Bundle bundle, T defaultValue) { + return bundle == null ? defaultValue : creator.fromBundle(bundle); + } + + /** Converts a list of {@link Bundleable} to a list {@link Bundle}. */ + public static ImmutableList toBundleList(List bundleableList) { + ImmutableList.Builder builder = ImmutableList.builder(); + for (int i = 0; i < bundleableList.size(); i++) { + Bundleable bundleable = bundleableList.get(i); + builder.add(bundleable.toBundle()); + } + return builder.build(); + } + + /** Converts a list of {@link Bundle} to a list of {@link Bundleable}. */ + public static ImmutableList fromBundleList( + Bundleable.Creator creator, List bundleList) { + ImmutableList.Builder builder = ImmutableList.builder(); + for (int i = 0; i < bundleList.size(); i++) { + Bundle bundle = bundleList.get(i); + T bundleable = creator.fromBundle(bundle); + builder.add(bundleable); + } + return builder.build(); + } + + /** + * Converts a list of {@link Bundleable} to an {@link ArrayList} of {@link Bundle} so that the + * returned list can be put to {@link Bundle} using {@link Bundle#putParcelableArrayList} + * conveniently. + */ + public static ArrayList toBundleArrayList(List bundleableList) { + ArrayList arrayList = new ArrayList<>(bundleableList.size()); + for (int i = 0; i < bundleableList.size(); i++) { + arrayList.add(bundleableList.get(i).toBundle()); + } + return arrayList; + } + + private BundleableUtils() {} +} diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/Clock.java b/library/common/src/main/java/com/google/android/exoplayer2/util/Clock.java index 8ecb2ab8ec7..b21e5773e6a 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/Clock.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/Clock.java @@ -25,9 +25,7 @@ */ public interface Clock { - /** - * Default {@link Clock} to use for all non-test cases. - */ + /** Default {@link Clock} to use for all non-test cases. */ Clock DEFAULT = new SystemClock(); /** diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/ExoFlags.java b/library/common/src/main/java/com/google/android/exoplayer2/util/FlagSet.java similarity index 74% rename from library/common/src/main/java/com/google/android/exoplayer2/util/ExoFlags.java rename to library/common/src/main/java/com/google/android/exoplayer2/util/FlagSet.java index 46c9e486df3..6322114b90c 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/ExoFlags.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/FlagSet.java @@ -29,9 +29,9 @@ * *

        Instances are immutable. */ -public final class ExoFlags { +public final class FlagSet { - /** A builder for {@link ExoFlags} instances. */ + /** A builder for {@link FlagSet} instances. */ public static final class Builder { private final SparseBooleanArray flags; @@ -86,13 +86,13 @@ public Builder addAll(int... flags) { } /** - * Adds {@link ExoFlags flags}. + * Adds {@link FlagSet flags}. * * @param flags The set of flags to add. * @return This builder. * @throws IllegalStateException If {@link #build()} has already been called. */ - public Builder addAll(ExoFlags flags) { + public Builder addAll(FlagSet flags) { for (int i = 0; i < flags.size(); i++) { add(flags.get(i)); } @@ -100,21 +100,63 @@ public Builder addAll(ExoFlags flags) { } /** - * Builds an {@link ExoFlags} instance. + * Removes a flag. + * + * @param flag A flag. + * @return This builder. + * @throws IllegalStateException If {@link #build()} has already been called. + */ + public Builder remove(int flag) { + checkState(!buildCalled); + flags.delete(flag); + return this; + } + + /** + * Removes a flag if the provided condition is true. Does nothing otherwise. + * + * @param flag A flag. + * @param condition A condition. + * @return This builder. + * @throws IllegalStateException If {@link #build()} has already been called. + */ + public Builder removeIf(int flag, boolean condition) { + if (condition) { + return remove(flag); + } + return this; + } + + /** + * Removes flags. + * + * @param flags The flags to remove. + * @return This builder. + * @throws IllegalStateException If {@link #build()} has already been called. + */ + public Builder removeAll(int... flags) { + for (int flag : flags) { + remove(flag); + } + return this; + } + + /** + * Builds an {@link FlagSet} instance. * * @throws IllegalStateException If this method has already been called. */ - public ExoFlags build() { + public FlagSet build() { checkState(!buildCalled); buildCalled = true; - return new ExoFlags(flags); + return new FlagSet(flags); } } // A SparseBooleanArray is used instead of a Set to avoid auto-boxing the flag values. private final SparseBooleanArray flags; - private ExoFlags(SparseBooleanArray flags) { + private FlagSet(SparseBooleanArray flags) { this.flags = flags; } @@ -165,10 +207,10 @@ public boolean equals(@Nullable Object o) { if (this == o) { return true; } - if (!(o instanceof ExoFlags)) { + if (!(o instanceof FlagSet)) { return false; } - ExoFlags that = (ExoFlags) o; + FlagSet that = (FlagSet) o; return flags.equals(that.flags); } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/ListenerSet.java b/library/common/src/main/java/com/google/android/exoplayer2/util/ListenerSet.java index fe220b1946d..7f2ce9759a4 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/ListenerSet.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/ListenerSet.java @@ -60,14 +60,13 @@ public interface IterationFinishedEvent { * Invokes the iteration finished event. * * @param listener The listener to invoke the event on. - * @param eventFlags The combined event {@link ExoFlags flags} of all events sent in this + * @param eventFlags The combined event {@link FlagSet flags} of all events sent in this * iteration. */ - void invoke(T listener, ExoFlags eventFlags); + void invoke(T listener, FlagSet eventFlags); } private static final int MSG_ITERATION_FINISHED = 0; - private static final int MSG_LAZY_RELEASE = 1; private final Clock clock; private final HandlerWrapper handler; @@ -88,11 +87,7 @@ public interface IterationFinishedEvent { * during one {@link Looper} message queue iteration were handled by the listeners. */ public ListenerSet(Looper looper, Clock clock, IterationFinishedEvent iterationFinishedEvent) { - this( - /* listeners= */ new CopyOnWriteArraySet<>(), - looper, - clock, - iterationFinishedEvent); + this(/* listeners= */ new CopyOnWriteArraySet<>(), looper, clock, iterationFinishedEvent); } private ListenerSet( @@ -106,7 +101,7 @@ private ListenerSet( flushingEvents = new ArrayDeque<>(); queuedEvents = new ArrayDeque<>(); // It's safe to use "this" because we don't send a message before exiting the constructor. - @SuppressWarnings("methodref.receiver.bound.invalid") + @SuppressWarnings("nullness:methodref.receiver.bound") HandlerWrapper handler = clock.createHandler(looper, this::handleMessage); this.handler = handler; } @@ -155,6 +150,11 @@ public void remove(T listener) { } } + /** Returns the number of added listeners. */ + public int size() { + return listeners.size(); + } + /** * Adds an event that is sent to the listeners when {@link #flushEvents} is called. * @@ -178,7 +178,7 @@ public void flushEvents() { return; } if (!handler.hasMessages(MSG_ITERATION_FINISHED)) { - handler.obtainMessage(MSG_ITERATION_FINISHED).sendToTarget(); + handler.sendMessageAtFrontOfQueue(handler.obtainMessage(MSG_ITERATION_FINISHED)); } boolean recursiveFlushInProgress = !flushingEvents.isEmpty(); flushingEvents.addAll(queuedEvents); @@ -219,37 +219,15 @@ public void release() { released = true; } - /** - * Releases the set of listeners after all already scheduled {@link Looper} messages were able to - * trigger final events. - * - *

        After the specified released callback event, no other events are sent to a listener. - * - * @param releaseEventFlag An integer flag indicating the type of the release event, or {@link - * C#INDEX_UNSET} to report this event without a flag. - * @param releaseEvent The release event. - */ - public void lazyRelease(int releaseEventFlag, Event releaseEvent) { - handler.obtainMessage(MSG_LAZY_RELEASE, releaseEventFlag, 0, releaseEvent).sendToTarget(); - } - private boolean handleMessage(Message message) { - if (message.what == MSG_ITERATION_FINISHED) { - for (ListenerHolder holder : listeners) { - holder.iterationFinished(iterationFinishedEvent); - if (handler.hasMessages(MSG_ITERATION_FINISHED)) { - // The invocation above triggered new events (and thus scheduled a new message). We need - // to stop here because this new message will take care of informing every listener about - // the new update (including the ones already called here). - break; - } + for (ListenerHolder holder : listeners) { + holder.iterationFinished(iterationFinishedEvent); + if (handler.hasMessages(MSG_ITERATION_FINISHED)) { + // The invocation above triggered new events (and thus scheduled a new message). We need + // to stop here because this new message will take care of informing every listener about + // the new update (including the ones already called here). + break; } - } else if (message.what == MSG_LAZY_RELEASE) { - int releaseEventFlag = message.arg1; - @SuppressWarnings("unchecked") - Event releaseEvent = (Event) message.obj; - sendEvent(releaseEventFlag, releaseEvent); - release(); } return true; } @@ -258,13 +236,13 @@ private static final class ListenerHolder { @Nonnull public final T listener; - private ExoFlags.Builder flagsBuilder; + private FlagSet.Builder flagsBuilder; private boolean needsIterationFinishedEvent; private boolean released; public ListenerHolder(@Nonnull T listener) { this.listener = listener; - this.flagsBuilder = new ExoFlags.Builder(); + this.flagsBuilder = new FlagSet.Builder(); } public void release(IterationFinishedEvent event) { @@ -288,8 +266,8 @@ public void iterationFinished(IterationFinishedEvent event) { if (!released && needsIterationFinishedEvent) { // Reset flags before invoking the listener to ensure we keep all new flags that are set by // recursive events triggered from this callback. - ExoFlags flagsToNotify = flagsBuilder.build(); - flagsBuilder = new ExoFlags.Builder(); + FlagSet flagsToNotify = flagsBuilder.build(); + flagsBuilder = new FlagSet.Builder(); needsIterationFinishedEvent = false; event.invoke(listener, flagsToNotify); } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/Log.java b/library/common/src/main/java/com/google/android/exoplayer2/util/Log.java index fd1b74ca6e8..1b3a0809957 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/Log.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/Log.java @@ -57,12 +57,6 @@ private Log() {} return logLevel; } - /** Returns whether stack traces of {@link Throwable}s will be logged to logcat. */ - @Pure - public boolean getLogStackTraces() { - return logStackTraces; - } - /** * Sets the {@link LogLevel} for ExoPlayer logcat logging. * diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/LongArray.java b/library/common/src/main/java/com/google/android/exoplayer2/util/LongArray.java index d6a17336971..a9709dff703 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/LongArray.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/LongArray.java @@ -29,9 +29,7 @@ public LongArray() { this(DEFAULT_INITIAL_CAPACITY); } - /** - * @param initialCapacity The initial capacity of the array. - */ + /** @param initialCapacity The initial capacity of the array. */ public LongArray(int initialCapacity) { values = new long[initialCapacity]; } @@ -63,9 +61,7 @@ public long get(int index) { return values[index]; } - /** - * Returns the current size of the array. - */ + /** Returns the current size of the array. */ public int size() { return size; } @@ -78,5 +74,4 @@ public int size() { public long[] toArray() { return Arrays.copyOf(values, size); } - } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java b/library/common/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java index 066cdc9ea44..a3bf921172f 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java @@ -76,6 +76,7 @@ public final class MimeTypes { public static final String AUDIO_DTS = BASE_TYPE_AUDIO + "/vnd.dts"; public static final String AUDIO_DTS_HD = BASE_TYPE_AUDIO + "/vnd.dts.hd"; public static final String AUDIO_DTS_EXPRESS = BASE_TYPE_AUDIO + "/vnd.dts.hd;profile=lbr"; + public static final String AUDIO_DTS_UHD = BASE_TYPE_AUDIO + "/vnd.dts.uhd"; public static final String AUDIO_VORBIS = BASE_TYPE_AUDIO + "/vorbis"; public static final String AUDIO_OPUS = BASE_TYPE_AUDIO + "/opus"; public static final String AUDIO_AMR = BASE_TYPE_AUDIO + "/amr"; @@ -376,14 +377,18 @@ public static String getMediaMimeType(@Nullable String codec) { return MimeTypes.AUDIO_AC3; } else if (codec.startsWith("ec-3") || codec.startsWith("dec3")) { return MimeTypes.AUDIO_E_AC3; - } else if (codec.startsWith(Ac3Util.E_AC_3_CODEC_STRING)) { + } else if (codec.startsWith(Ac3Util.E_AC3_JOC_CODEC_STRING)) { return MimeTypes.AUDIO_E_AC3_JOC; } else if (codec.startsWith("ac-4") || codec.startsWith("dac4")) { return MimeTypes.AUDIO_AC4; - } else if (codec.startsWith("dtsc") || codec.startsWith("dtse")) { + } else if (codec.startsWith("dtsc")) { return MimeTypes.AUDIO_DTS; + } else if (codec.startsWith("dtse")) { + return MimeTypes.AUDIO_DTS_EXPRESS; } else if (codec.startsWith("dtsh") || codec.startsWith("dtsl")) { return MimeTypes.AUDIO_DTS_HD; + } else if (codec.startsWith("dtsx")) { + return MimeTypes.AUDIO_DTS_UHD; } else if (codec.startsWith("opus")) { return MimeTypes.AUDIO_OPUS; } else if (codec.startsWith("vorbis")) { diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/NalUnitUtil.java b/library/common/src/main/java/com/google/android/exoplayer2/util/NalUnitUtil.java index d6d4a7aa01b..1fd44011e00 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/NalUnitUtil.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/NalUnitUtil.java @@ -24,9 +24,7 @@ public final class NalUnitUtil { private static final String TAG = "NalUnitUtil"; - /** - * Holds data parsed from a sequence parameter set NAL unit. - */ + /** Holds data parsed from a sequence parameter set NAL unit. */ public static final class SpsData { public final int profileIdc; @@ -71,25 +69,23 @@ public SpsData( this.picOrderCntLsbLength = picOrderCntLsbLength; this.deltaPicOrderAlwaysZeroFlag = deltaPicOrderAlwaysZeroFlag; } - } - /** - * Holds data parsed from a picture parameter set NAL unit. - */ + /** Holds data parsed from a picture parameter set NAL unit. */ public static final class PpsData { public final int picParameterSetId; public final int seqParameterSetId; public final boolean bottomFieldPicOrderInFramePresentFlag; - public PpsData(int picParameterSetId, int seqParameterSetId, + public PpsData( + int picParameterSetId, + int seqParameterSetId, boolean bottomFieldPicOrderInFramePresentFlag) { this.picParameterSetId = picParameterSetId; this.seqParameterSetId = seqParameterSetId; this.bottomFieldPicOrderInFramePresentFlag = bottomFieldPicOrderInFramePresentFlag; } - } /** Four initial bytes that must prefix NAL units for decoding. */ @@ -98,25 +94,26 @@ public PpsData(int picParameterSetId, int seqParameterSetId, /** Value for aspect_ratio_idc indicating an extended aspect ratio, in H.264 and H.265 SPSs. */ public static final int EXTENDED_SAR = 0xFF; /** Aspect ratios indexed by aspect_ratio_idc, in H.264 and H.265 SPSs. */ - public static final float[] ASPECT_RATIO_IDC_VALUES = new float[] { - 1f /* Unspecified. Assume square */, - 1f, - 12f / 11f, - 10f / 11f, - 16f / 11f, - 40f / 33f, - 24f / 11f, - 20f / 11f, - 32f / 11f, - 80f / 33f, - 18f / 11f, - 15f / 11f, - 64f / 33f, - 160f / 99f, - 4f / 3f, - 3f / 2f, - 2f - }; + public static final float[] ASPECT_RATIO_IDC_VALUES = + new float[] { + 1f /* Unspecified. Assume square */, + 1f, + 12f / 11f, + 10f / 11f, + 16f / 11f, + 40f / 33f, + 24f / 11f, + 20f / 11f, + 32f / 11f, + 80f / 33f, + 18f / 11f, + 15f / 11f, + 64f / 33f, + 160f / 99f, + 4f / 3f, + 3f / 2f, + 2f + }; private static final int H264_NAL_UNIT_TYPE_SEI = 6; // Supplemental enhancement information private static final int H264_NAL_UNIT_TYPE_SPS = 7; // Sequence parameter set @@ -131,10 +128,10 @@ public PpsData(int picParameterSetId, int seqParameterSetId, private static int[] scratchEscapePositions = new int[10]; /** - * Unescapes {@code data} up to the specified limit, replacing occurrences of [0, 0, 3] with - * [0, 0]. The unescaped data is returned in-place, with the return value indicating its length. - *

        - * Executions of this method are mutually exclusive, so it should not be called with very large + * Unescapes {@code data} up to the specified limit, replacing occurrences of [0, 0, 3] with [0, + * 0]. The unescaped data is returned in-place, with the return value indicating its length. + * + *

        Executions of this method are mutually exclusive, so it should not be called with very large * buffers. * * @param data The data to unescape. @@ -150,8 +147,8 @@ public static int unescapeStream(byte[] data, int limit) { if (position < limit) { if (scratchEscapePositions.length <= scratchEscapeCount) { // Grow scratchEscapePositions to hold a larger number of positions. - scratchEscapePositions = Arrays.copyOf(scratchEscapePositions, - scratchEscapePositions.length * 2); + scratchEscapePositions = + Arrays.copyOf(scratchEscapePositions, scratchEscapePositions.length * 2); } scratchEscapePositions[scratchEscapeCount++] = position; position += 3; @@ -180,9 +177,9 @@ public static int unescapeStream(byte[] data, int limit) { /** * Discards data from the buffer up to the first SPS, where {@code data.position()} is interpreted * as the length of the buffer. - *

        - * When the method returns, {@code data.position()} will contain the new length of the buffer. If - * the buffer is not empty it is guaranteed to start with an SPS. + * + *

        When the method returns, {@code data.position()} will contain the new length of the buffer. + * If the buffer is not empty it is guaranteed to start with an SPS. * * @param data Buffer containing start code delimited NAL units. */ @@ -225,9 +222,9 @@ public static void discardToSps(ByteBuffer data) { */ public static boolean isNalUnitSei(@Nullable String mimeType, byte nalUnitHeaderFirstByte) { return (MimeTypes.VIDEO_H264.equals(mimeType) - && (nalUnitHeaderFirstByte & 0x1F) == H264_NAL_UNIT_TYPE_SEI) + && (nalUnitHeaderFirstByte & 0x1F) == H264_NAL_UNIT_TYPE_SEI) || (MimeTypes.VIDEO_H265.equals(mimeType) - && ((nalUnitHeaderFirstByte & 0x7E) >> 1) == H265_NAL_UNIT_TYPE_PREFIX_SEI); + && ((nalUnitHeaderFirstByte & 0x7E) >> 1) == H265_NAL_UNIT_TYPE_PREFIX_SEI); } /** @@ -273,9 +270,16 @@ public static SpsData parseSpsNalUnit(byte[] nalData, int nalOffset, int nalLimi int chromaFormatIdc = 1; // Default is 4:2:0 boolean separateColorPlaneFlag = false; - if (profileIdc == 100 || profileIdc == 110 || profileIdc == 122 || profileIdc == 244 - || profileIdc == 44 || profileIdc == 83 || profileIdc == 86 || profileIdc == 118 - || profileIdc == 128 || profileIdc == 138) { + if (profileIdc == 100 + || profileIdc == 110 + || profileIdc == 122 + || profileIdc == 244 + || profileIdc == 44 + || profileIdc == 83 + || profileIdc == 86 + || profileIdc == 118 + || profileIdc == 128 + || profileIdc == 138) { chromaFormatIdc = data.readUnsignedExpGolombCodedInt(); if (chromaFormatIdc == 3) { separateColorPlaneFlag = data.readBit(); @@ -403,16 +407,16 @@ public static PpsData parsePpsNalUnit(byte[] nalData, int nalOffset, int nalLimi /** * Finds the first NAL unit in {@code data}. - *

        - * If {@code prefixFlags} is null then the first three bytes of a NAL unit must be entirely + * + *

        If {@code prefixFlags} is null then the first three bytes of a NAL unit must be entirely * contained within the part of the array being searched in order for it to be found. - *

        - * When {@code prefixFlags} is non-null, this method supports finding NAL units whose first four - * bytes span {@code data} arrays passed to successive calls. To use this feature, pass the same - * {@code prefixFlags} parameter to successive calls. State maintained in this parameter enables - * the detection of such NAL units. Note that when using this feature, the return value may be 3, - * 2 or 1 less than {@code startOffset}, to indicate a NAL unit starting 3, 2 or 1 bytes before - * the first byte in the current array. + * + *

        When {@code prefixFlags} is non-null, this method supports finding NAL units whose first + * four bytes span {@code data} arrays passed to successive calls. To use this feature, pass the + * same {@code prefixFlags} parameter to successive calls. State maintained in this parameter + * enables the detection of such NAL units. Note that when using this feature, the return value + * may be 3, 2 or 1 less than {@code startOffset}, to indicate a NAL unit starting 3, 2 or 1 bytes + * before the first byte in the current array. * * @param data The data to search. * @param startOffset The offset (inclusive) in the data to start the search. @@ -422,8 +426,8 @@ public static PpsData parsePpsNalUnit(byte[] nalData, int nalOffset, int nalLimi * must be at least 3 elements long. * @return The offset of the NAL unit, or {@code endOffset} if a NAL unit was not found. */ - public static int findNalUnit(byte[] data, int startOffset, int endOffset, - boolean[] prefixFlags) { + public static int findNalUnit( + byte[] data, int startOffset, int endOffset, boolean[] prefixFlags) { int length = endOffset - startOffset; Assertions.checkState(length >= 0); @@ -515,5 +519,4 @@ private static void skipScalingList(ParsableNalUnitBitArray bitArray, int size) private NalUnitUtil() { // Prevent instantiation. } - } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/ParsableBitArray.java b/library/common/src/main/java/com/google/android/exoplayer2/util/ParsableBitArray.java index c14eee6f881..7efaa42c7ae 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/ParsableBitArray.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/ParsableBitArray.java @@ -89,16 +89,12 @@ public void reset(byte[] data, int limit) { byteLimit = limit; } - /** - * Returns the number of bits yet to be read. - */ + /** Returns the number of bits yet to be read. */ public int bitsLeft() { return (byteLimit - byteOffset) * 8 - bitOffset; } - /** - * Returns the current bit offset. - */ + /** Returns the current bit offset. */ public int getPosition() { return byteOffset * 8 + bitOffset; } @@ -124,9 +120,7 @@ public void setPosition(int position) { assertValidOffset(); } - /** - * Skips a single bit. - */ + /** Skips a single bit. */ public void skipBit() { if (++bitOffset == 8) { bitOffset = 0; @@ -344,8 +338,7 @@ public void putInt(int value, int numBits) { private void assertValidOffset() { // It is fine for position to be at the end of the array, but no further. - Assertions.checkState(byteOffset >= 0 - && (byteOffset < byteLimit || (byteOffset == byteLimit && bitOffset == 0))); + Assertions.checkState( + byteOffset >= 0 && (byteOffset < byteLimit || (byteOffset == byteLimit && bitOffset == 0))); } - } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/ParsableByteArray.java b/library/common/src/main/java/com/google/android/exoplayer2/util/ParsableByteArray.java index dff16d39f18..79913d2aa91 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/ParsableByteArray.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/ParsableByteArray.java @@ -120,9 +120,7 @@ public int bytesLeft() { return limit - position; } - /** - * Returns the limit. - */ + /** Returns the limit. */ public int limit() { return limit; } @@ -137,9 +135,7 @@ public void setLimit(int limit) { this.limit = limit; } - /** - * Returns the current offset in the array, in bytes. - */ + /** Returns the current offset in the array, in bytes. */ public int getPosition() { return position; } @@ -186,8 +182,8 @@ public void skipBytes(int bytes) { } /** - * Reads the next {@code length} bytes into {@code bitArray}, and resets the position of - * {@code bitArray} to zero. + * Reads the next {@code length} bytes into {@code bitArray}, and resets the position of {@code + * bitArray} to zero. * * @param bitArray The {@link ParsableBitArray} into which the bytes should be read. * @param length The number of bytes to write. @@ -222,97 +218,70 @@ public void readBytes(ByteBuffer buffer, int length) { position += length; } - /** - * Peeks at the next byte as an unsigned value. - */ + /** Peeks at the next byte as an unsigned value. */ public int peekUnsignedByte() { return (data[position] & 0xFF); } - /** - * Peeks at the next char. - */ + /** Peeks at the next char. */ public char peekChar() { - return (char) ((data[position] & 0xFF) << 8 - | (data[position + 1] & 0xFF)); + return (char) ((data[position] & 0xFF) << 8 | (data[position + 1] & 0xFF)); } - /** - * Reads the next byte as an unsigned value. - */ + /** Reads the next byte as an unsigned value. */ public int readUnsignedByte() { return (data[position++] & 0xFF); } - /** - * Reads the next two bytes as an unsigned value. - */ + /** Reads the next two bytes as an unsigned value. */ public int readUnsignedShort() { - return (data[position++] & 0xFF) << 8 - | (data[position++] & 0xFF); + return (data[position++] & 0xFF) << 8 | (data[position++] & 0xFF); } - /** - * Reads the next two bytes as an unsigned value. - */ + /** Reads the next two bytes as an unsigned value. */ public int readLittleEndianUnsignedShort() { return (data[position++] & 0xFF) | (data[position++] & 0xFF) << 8; } - /** - * Reads the next two bytes as a signed value. - */ + /** Reads the next two bytes as a signed value. */ public short readShort() { - return (short) ((data[position++] & 0xFF) << 8 - | (data[position++] & 0xFF)); + return (short) ((data[position++] & 0xFF) << 8 | (data[position++] & 0xFF)); } - /** - * Reads the next two bytes as a signed value. - */ + /** Reads the next two bytes as a signed value. */ public short readLittleEndianShort() { return (short) ((data[position++] & 0xFF) | (data[position++] & 0xFF) << 8); } - /** - * Reads the next three bytes as an unsigned value. - */ + /** Reads the next three bytes as an unsigned value. */ public int readUnsignedInt24() { return (data[position++] & 0xFF) << 16 | (data[position++] & 0xFF) << 8 | (data[position++] & 0xFF); } - /** - * Reads the next three bytes as a signed value. - */ + /** Reads the next three bytes as a signed value. */ public int readInt24() { return ((data[position++] & 0xFF) << 24) >> 8 | (data[position++] & 0xFF) << 8 | (data[position++] & 0xFF); } - /** - * Reads the next three bytes as a signed value in little endian order. - */ + /** Reads the next three bytes as a signed value in little endian order. */ public int readLittleEndianInt24() { return (data[position++] & 0xFF) | (data[position++] & 0xFF) << 8 | (data[position++] & 0xFF) << 16; } - /** - * Reads the next three bytes as an unsigned value in little endian order. - */ + /** Reads the next three bytes as an unsigned value in little endian order. */ public int readLittleEndianUnsignedInt24() { return (data[position++] & 0xFF) | (data[position++] & 0xFF) << 8 | (data[position++] & 0xFF) << 16; } - /** - * Reads the next four bytes as an unsigned value. - */ + /** Reads the next four bytes as an unsigned value. */ public long readUnsignedInt() { return (data[position++] & 0xFFL) << 24 | (data[position++] & 0xFFL) << 16 @@ -320,9 +289,7 @@ public long readUnsignedInt() { | (data[position++] & 0xFFL); } - /** - * Reads the next four bytes as an unsigned value in little endian order. - */ + /** Reads the next four bytes as an unsigned value in little endian order. */ public long readLittleEndianUnsignedInt() { return (data[position++] & 0xFFL) | (data[position++] & 0xFFL) << 8 @@ -330,9 +297,7 @@ public long readLittleEndianUnsignedInt() { | (data[position++] & 0xFFL) << 24; } - /** - * Reads the next four bytes as a signed value - */ + /** Reads the next four bytes as a signed value */ public int readInt() { return (data[position++] & 0xFF) << 24 | (data[position++] & 0xFF) << 16 @@ -340,9 +305,7 @@ public int readInt() { | (data[position++] & 0xFF); } - /** - * Reads the next four bytes as a signed value in little endian order. - */ + /** Reads the next four bytes as a signed value in little endian order. */ public int readLittleEndianInt() { return (data[position++] & 0xFF) | (data[position++] & 0xFF) << 8 @@ -350,9 +313,7 @@ public int readLittleEndianInt() { | (data[position++] & 0xFF) << 24; } - /** - * Reads the next eight bytes as a signed value. - */ + /** Reads the next eight bytes as a signed value. */ public long readLong() { return (data[position++] & 0xFFL) << 56 | (data[position++] & 0xFFL) << 48 @@ -364,9 +325,7 @@ public long readLong() { | (data[position++] & 0xFFL); } - /** - * Reads the next eight bytes as a signed value in little endian order. - */ + /** Reads the next eight bytes as a signed value in little endian order. */ public long readLittleEndianLong() { return (data[position++] & 0xFFL) | (data[position++] & 0xFFL) << 8 @@ -378,20 +337,17 @@ public long readLittleEndianLong() { | (data[position++] & 0xFFL) << 56; } - /** - * Reads the next four bytes, returning the integer portion of the fixed point 16.16 integer. - */ + /** Reads the next four bytes, returning the integer portion of the fixed point 16.16 integer. */ public int readUnsignedFixedPoint1616() { - int result = (data[position++] & 0xFF) << 8 - | (data[position++] & 0xFF); + int result = (data[position++] & 0xFF) << 8 | (data[position++] & 0xFF); position += 2; // Skip the non-integer portion. return result; } /** * Reads a Synchsafe integer. - *

        - * Synchsafe integers keep the highest bit of every byte zeroed. A 32 bit synchsafe integer can + * + *

        Synchsafe integers keep the highest bit of every byte zeroed. A 32 bit synchsafe integer can * store 28 bits of information. * * @return The parsed value. @@ -444,16 +400,12 @@ public long readUnsignedLongToLong() { return result; } - /** - * Reads the next four bytes as a 32-bit floating point value. - */ + /** Reads the next four bytes as a 32-bit floating point value. */ public float readFloat() { return Float.intBitsToFloat(readInt()); } - /** - * Reads the next eight bytes as a 64-bit floating point value. - */ + /** Reads the next eight bytes as a 64-bit floating point value. */ public double readDouble() { return Double.longBitsToDouble(readLong()); } @@ -555,8 +507,10 @@ public String readLine() { while (lineLimit < limit && !Util.isLinebreak(data[lineLimit])) { lineLimit++; } - if (lineLimit - position >= 3 && data[position] == (byte) 0xEF - && data[position + 1] == (byte) 0xBB && data[position + 2] == (byte) 0xBF) { + if (lineLimit - position >= 3 + && data[position] == (byte) 0xEF + && data[position + 1] == (byte) 0xBB + && data[position + 2] == (byte) 0xBF) { // There's a UTF-8 byte order mark at the start of the line. Discard it. position += 3; } @@ -611,5 +565,4 @@ public long readUtf8EncodedLong() { position += length; return value; } - } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/ParsableNalUnitBitArray.java b/library/common/src/main/java/com/google/android/exoplayer2/util/ParsableNalUnitBitArray.java index 6738ed7b0ef..50810bc6a05 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/ParsableNalUnitBitArray.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/ParsableNalUnitBitArray.java @@ -35,7 +35,7 @@ public final class ParsableNalUnitBitArray { * @param offset The byte offset in {@code data} to start reading from. * @param limit The byte offset of the end of the bitstream in {@code data}. */ - @SuppressWarnings({"initialization.fields.uninitialized", "method.invocation.invalid"}) + @SuppressWarnings({"initialization.fields.uninitialized", "nullness:method.invocation"}) public ParsableNalUnitBitArray(byte[] data, int offset, int limit) { reset(data, offset, limit); } @@ -55,9 +55,7 @@ public void reset(byte[] data, int offset, int limit) { assertValidOffset(); } - /** - * Skips a single bit. - */ + /** Skips a single bit. */ public void skipBit() { if (++bitOffset == 8) { bitOffset = 0; @@ -198,14 +196,16 @@ private int readExpGolombCodeNum() { } private boolean shouldSkipByte(int offset) { - return 2 <= offset && offset < byteLimit && data[offset] == (byte) 0x03 - && data[offset - 2] == (byte) 0x00 && data[offset - 1] == (byte) 0x00; + return 2 <= offset + && offset < byteLimit + && data[offset] == (byte) 0x03 + && data[offset - 2] == (byte) 0x00 + && data[offset - 1] == (byte) 0x00; } private void assertValidOffset() { // It is fine for position to be at the end of the array, but no further. - Assertions.checkState(byteOffset >= 0 - && (byteOffset < byteLimit || (byteOffset == byteLimit && bitOffset == 0))); + Assertions.checkState( + byteOffset >= 0 && (byteOffset < byteLimit || (byteOffset == byteLimit && bitOffset == 0))); } - } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/RepeatModeUtil.java b/library/common/src/main/java/com/google/android/exoplayer2/util/RepeatModeUtil.java index 0acc430b0c0..26c586f9a41 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/RepeatModeUtil.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/RepeatModeUtil.java @@ -24,7 +24,6 @@ /** Util class for repeat mode handling. */ public final class RepeatModeUtil { - // LINT.IfChange /** * Set of repeat toggle modes. Can be combined using bit-wise operations. Possible flag values are * {@link #REPEAT_TOGGLE_MODE_NONE}, {@link #REPEAT_TOGGLE_MODE_ONE} and {@link @@ -36,17 +35,12 @@ public final class RepeatModeUtil { flag = true, value = {REPEAT_TOGGLE_MODE_NONE, REPEAT_TOGGLE_MODE_ONE, REPEAT_TOGGLE_MODE_ALL}) public @interface RepeatToggleModes {} - /** - * All repeat mode buttons disabled. - */ + /** All repeat mode buttons disabled. */ public static final int REPEAT_TOGGLE_MODE_NONE = 0; - /** - * "Repeat One" button enabled. - */ + /** "Repeat One" button enabled. */ public static final int REPEAT_TOGGLE_MODE_ONE = 1; /** "Repeat All" button enabled. */ public static final int REPEAT_TOGGLE_MODE_ALL = 1 << 1; // 2 - // LINT.ThenChange(../../../../../../../../../ui/src/main/res/values/attrs.xml) private RepeatModeUtil() { // Prevent instantiation. @@ -59,8 +53,8 @@ private RepeatModeUtil() { * @param enabledModes Bitmask of enabled modes. * @return The next repeat mode. */ - public static @Player.RepeatMode int getNextRepeatMode(@Player.RepeatMode int currentMode, - int enabledModes) { + public static @Player.RepeatMode int getNextRepeatMode( + @Player.RepeatMode int currentMode, int enabledModes) { for (int offset = 1; offset <= 2; offset++) { @Player.RepeatMode int proposedMode = (currentMode + offset) % 3; if (isRepeatModeEnabled(proposedMode, enabledModes)) { diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/TimestampAdjuster.java b/library/common/src/main/java/com/google/android/exoplayer2/util/TimestampAdjuster.java index a76cf9b5123..1f5da87a597 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/TimestampAdjuster.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/TimestampAdjuster.java @@ -19,16 +19,32 @@ import com.google.android.exoplayer2.C; /** - * Offsets timestamps according to an initial sample timestamp offset. MPEG-2 TS timestamps scaling - * and adjustment is supported, taking into account timestamp rollover. + * Adjusts and offsets sample timestamps. MPEG-2 TS timestamps scaling and adjustment is supported, + * taking into account timestamp rollover. */ public final class TimestampAdjuster { /** * A special {@code firstSampleTimestampUs} value indicating that presentation timestamps should - * not be offset. + * not be offset. In this mode: + * + *

          + *
        • {@link #getFirstSampleTimestampUs()} will always return {@link C#TIME_UNSET}. + *
        • The only timestamp adjustment performed is to account for MPEG-2 TS timestamp rollover. + *
        + */ + public static final long MODE_NO_OFFSET = Long.MAX_VALUE; + + /** + * A special {@code firstSampleTimestampUs} value indicating that the adjuster will be shared by + * multiple threads. In this mode: + * + *
          + *
        • {@link #getFirstSampleTimestampUs()} will always return {@link C#TIME_UNSET}. + *
        • Calling threads must call {@link #sharedInitializeOrWait} prior to adjusting timestamps. + *
        */ - public static final long DO_NOT_OFFSET = Long.MAX_VALUE; + public static final long MODE_SHARED = Long.MAX_VALUE - 1; /** * The value one greater than the largest representable (33 bit) MPEG-2 TS 90 kHz clock @@ -36,9 +52,6 @@ public final class TimestampAdjuster { */ private static final long MAX_PTS_PLUS_ONE = 0x200000000L; - @GuardedBy("this") - private boolean sharedInitializationStarted; - @GuardedBy("this") private long firstSampleTimestampUs; @@ -46,53 +59,56 @@ public final class TimestampAdjuster { private long timestampOffsetUs; @GuardedBy("this") - private long lastSampleTimestampUs; + private long lastUnadjustedTimestampUs; + + /** + * Next sample timestamps for calling threads in shared mode when {@link #timestampOffsetUs} has + * not yet been set. + */ + private final ThreadLocal nextSampleTimestampUs; /** * @param firstSampleTimestampUs The desired value of the first adjusted sample timestamp in - * microseconds, or {@link #DO_NOT_OFFSET} if timestamps should not be offset. + * microseconds, or {@link #MODE_NO_OFFSET} if timestamps should not be offset, or {@link + * #MODE_SHARED} if the adjuster will be used in shared mode. */ public TimestampAdjuster(long firstSampleTimestampUs) { - this.firstSampleTimestampUs = firstSampleTimestampUs; - lastSampleTimestampUs = C.TIME_UNSET; + nextSampleTimestampUs = new ThreadLocal<>(); + reset(firstSampleTimestampUs); } /** * For shared timestamp adjusters, performs necessary initialization actions for a caller. * *
          - *
        • If the adjuster does not yet have a target {@link #getFirstSampleTimestampUs first sample - * timestamp} and if {@code canInitialize} is {@code true}, then initialization is started - * by setting the target first sample timestamp to {@code firstSampleTimestampUs}. The call - * returns, allowing the caller to proceed. Initialization completes when a caller adjusts - * the first timestamp. - *
        • If {@code canInitialize} is {@code true} and the adjuster already has a target {@link - * #getFirstSampleTimestampUs first sample timestamp}, then the call returns to allow the - * caller to proceed only if {@code firstSampleTimestampUs} is equal to the target. This - * ensures a caller that's previously started initialization can continue to proceed. It - * also allows other callers with the same {@code firstSampleTimestampUs} to proceed, since - * in this case it doesn't matter which caller adjusts the first timestamp to complete - * initialization. - *
        • If {@code canInitialize} is {@code false} or if {@code firstSampleTimestampUs} differs - * from the target {@link #getFirstSampleTimestampUs first sample timestamp}, then the call - * blocks until initialization completes. If initialization has already been completed the - * call returns immediately. + *
        • If the adjuster has already established a {@link #getTimestampOffsetUs timestamp offset} + * then this method is a no-op. + *
        • If {@code canInitialize} is {@code true} and the adjuster has not yet established a + * timestamp offset, then the adjuster records the desired first sample timestamp for the + * calling thread and returns to allow the caller to proceed. If the timestamp offset has + * still not been established when the caller attempts to adjust its first timestamp, then + * the recorded timestamp is used to set it. + *
        • If {@code canInitialize} is {@code false} and the adjuster has not yet established a + * timestamp offset, then the call blocks until the timestamp offset is set. *
        * * @param canInitialize Whether the caller is able to initialize the adjuster, if needed. - * @param startTimeUs The desired first sample timestamp of the caller, in microseconds. Only used - * if {@code canInitialize} is {@code true}. + * @param nextSampleTimestampUs The desired timestamp for the next sample loaded by the calling + * thread, in microseconds. Only used if {@code canInitialize} is {@code true}. * @throws InterruptedException If the thread is interrupted whilst blocked waiting for * initialization to complete. */ - public synchronized void sharedInitializeOrWait(boolean canInitialize, long startTimeUs) + public synchronized void sharedInitializeOrWait(boolean canInitialize, long nextSampleTimestampUs) throws InterruptedException { - if (canInitialize && !sharedInitializationStarted) { - firstSampleTimestampUs = startTimeUs; - sharedInitializationStarted = true; - } - if (!canInitialize || startTimeUs != firstSampleTimestampUs) { - while (lastSampleTimestampUs == C.TIME_UNSET) { + Assertions.checkState(firstSampleTimestampUs == MODE_SHARED); + if (timestampOffsetUs != C.TIME_UNSET) { + // Already initialized. + return; + } else if (canInitialize) { + this.nextSampleTimestampUs.set(nextSampleTimestampUs); + } else { + // Wait for another calling thread to complete initialization. + while (timestampOffsetUs == C.TIME_UNSET) { wait(); } } @@ -100,49 +116,43 @@ public synchronized void sharedInitializeOrWait(boolean canInitialize, long star /** * Returns the value of the first adjusted sample timestamp in microseconds, or {@link - * #DO_NOT_OFFSET} if timestamps will not be offset. + * C#TIME_UNSET} if timestamps will not be offset or if the adjuster is in shared mode. */ public synchronized long getFirstSampleTimestampUs() { - return firstSampleTimestampUs; + return firstSampleTimestampUs == MODE_NO_OFFSET || firstSampleTimestampUs == MODE_SHARED + ? C.TIME_UNSET + : firstSampleTimestampUs; } /** - * Returns the last value obtained from {@link #adjustSampleTimestamp}. If {@link - * #adjustSampleTimestamp} has not been called, returns the result of calling {@link - * #getFirstSampleTimestampUs()}. If this value is {@link #DO_NOT_OFFSET}, returns {@link - * C#TIME_UNSET}. + * Returns the last adjusted timestamp, in microseconds. If no timestamps have been adjusted yet + * then the result of {@link #getFirstSampleTimestampUs()} is returned. */ public synchronized long getLastAdjustedTimestampUs() { - return lastSampleTimestampUs != C.TIME_UNSET - ? (lastSampleTimestampUs + timestampOffsetUs) - : firstSampleTimestampUs != DO_NOT_OFFSET ? firstSampleTimestampUs : C.TIME_UNSET; + return lastUnadjustedTimestampUs != C.TIME_UNSET + ? lastUnadjustedTimestampUs + timestampOffsetUs + : getFirstSampleTimestampUs(); } /** - * Returns the offset between the input of {@link #adjustSampleTimestamp(long)} and its output. If - * {@link #DO_NOT_OFFSET} was provided to the constructor, 0 is returned. If the timestamp - * adjuster is yet not initialized, {@link C#TIME_UNSET} is returned. - * - * @return The offset between {@link #adjustSampleTimestamp(long)}'s input and output. {@link - * C#TIME_UNSET} if the adjuster is not yet initialized and 0 if timestamps should not be - * offset. + * Returns the offset between the input of {@link #adjustSampleTimestamp(long)} and its output, or + * {@link C#TIME_UNSET} if the offset has not yet been determined. */ public synchronized long getTimestampOffsetUs() { - return firstSampleTimestampUs == DO_NOT_OFFSET - ? 0 - : lastSampleTimestampUs == C.TIME_UNSET ? C.TIME_UNSET : timestampOffsetUs; + return timestampOffsetUs; } /** - * Resets the instance to its initial state. + * Resets the instance. * * @param firstSampleTimestampUs The desired value of the first adjusted sample timestamp after - * this reset, in microseconds, or {@link #DO_NOT_OFFSET} if timestamps should not be offset. + * this reset in microseconds, or {@link #MODE_NO_OFFSET} if timestamps should not be offset, + * or {@link #MODE_SHARED} if the adjuster will be used in shared mode. */ public synchronized void reset(long firstSampleTimestampUs) { this.firstSampleTimestampUs = firstSampleTimestampUs; - lastSampleTimestampUs = C.TIME_UNSET; - sharedInitializationStarted = false; + timestampOffsetUs = firstSampleTimestampUs == MODE_NO_OFFSET ? 0 : C.TIME_UNSET; + lastUnadjustedTimestampUs = C.TIME_UNSET; } /** @@ -155,10 +165,10 @@ public synchronized long adjustTsTimestamp(long pts90Khz) { if (pts90Khz == C.TIME_UNSET) { return C.TIME_UNSET; } - if (lastSampleTimestampUs != C.TIME_UNSET) { + if (lastUnadjustedTimestampUs != C.TIME_UNSET) { // The wrap count for the current PTS may be closestWrapCount or (closestWrapCount - 1), // and we need to snap to the one closest to lastSampleTimestampUs. - long lastPts = usToNonWrappedPts(lastSampleTimestampUs); + long lastPts = usToNonWrappedPts(lastUnadjustedTimestampUs); long closestWrapCount = (lastPts + (MAX_PTS_PLUS_ONE / 2)) / MAX_PTS_PLUS_ONE; long ptsWrapBelow = pts90Khz + (MAX_PTS_PLUS_ONE * (closestWrapCount - 1)); long ptsWrapAbove = pts90Khz + (MAX_PTS_PLUS_ONE * closestWrapCount); @@ -180,18 +190,16 @@ public synchronized long adjustSampleTimestamp(long timeUs) { if (timeUs == C.TIME_UNSET) { return C.TIME_UNSET; } - // Record the adjusted PTS to adjust for wraparound next time. - if (lastSampleTimestampUs != C.TIME_UNSET) { - lastSampleTimestampUs = timeUs; - } else { - if (firstSampleTimestampUs != DO_NOT_OFFSET) { - // Calculate the timestamp offset. - timestampOffsetUs = firstSampleTimestampUs - timeUs; - } - lastSampleTimestampUs = timeUs; - // Notify threads waiting for this adjuster to be initialized. + if (timestampOffsetUs == C.TIME_UNSET) { + long desiredSampleTimestampUs = + firstSampleTimestampUs == MODE_SHARED + ? Assertions.checkNotNull(nextSampleTimestampUs.get()) + : firstSampleTimestampUs; + timestampOffsetUs = desiredSampleTimestampUs - timeUs; + // Notify threads waiting for the timestamp offset to be determined. notifyAll(); } + lastUnadjustedTimestampUs = timeUs; return timeUs + timestampOffsetUs; } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/TraceUtil.java b/library/common/src/main/java/com/google/android/exoplayer2/util/TraceUtil.java index df6ffd557c1..87d63fcd060 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/TraceUtil.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/TraceUtil.java @@ -56,5 +56,4 @@ private static void beginSectionV18(String sectionName) { private static void endSectionV18() { android.os.Trace.endSection(); } - } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/Util.java b/library/common/src/main/java/com/google/android/exoplayer2/util/Util.java index 23ecc38e052..e222e83ffb6 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/Util.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/Util.java @@ -127,23 +127,23 @@ public final class Util { */ public static final String MODEL = Build.MODEL; - /** - * A concise description of the device that it can be useful to log for debugging purposes. - */ - public static final String DEVICE_DEBUG_INFO = DEVICE + ", " + MODEL + ", " + MANUFACTURER + ", " - + SDK_INT; + /** A concise description of the device that it can be useful to log for debugging purposes. */ + public static final String DEVICE_DEBUG_INFO = + DEVICE + ", " + MODEL + ", " + MANUFACTURER + ", " + SDK_INT; /** An empty byte array. */ public static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; private static final String TAG = "Util"; - private static final Pattern XS_DATE_TIME_PATTERN = Pattern.compile( - "(\\d\\d\\d\\d)\\-(\\d\\d)\\-(\\d\\d)[Tt]" - + "(\\d\\d):(\\d\\d):(\\d\\d)([\\.,](\\d+))?" - + "([Zz]|((\\+|\\-)(\\d?\\d):?(\\d\\d)))?"); + private static final Pattern XS_DATE_TIME_PATTERN = + Pattern.compile( + "(\\d\\d\\d\\d)\\-(\\d\\d)\\-(\\d\\d)[Tt]" + + "(\\d\\d):(\\d\\d):(\\d\\d)([\\.,](\\d+))?" + + "([Zz]|((\\+|\\-)(\\d?\\d):?(\\d\\d)))?"); private static final Pattern XS_DURATION_PATTERN = - Pattern.compile("^(-)?P(([0-9]*)Y)?(([0-9]*)M)?(([0-9]*)D)?" - + "(T(([0-9]*)H)?(([0-9]*)M)?(([0-9.]*)S)?)?$"); + Pattern.compile( + "^(-)?P(([0-9]*)Y)?(([0-9]*)M)?(([0-9]*)D)?" + + "(T(([0-9]*)H)?(([0-9]*)M)?(([0-9.]*)S)?)?$"); private static final Pattern ESCAPED_CHARACTER_PATTERN = Pattern.compile("%([A-Fa-f0-9]{2})"); // https://docs.microsoft.com/en-us/azure/media-services/previous/media-services-deliver-content-overview#URLs. @@ -336,14 +336,14 @@ public static void removeRange(List list, int fromIndex, int toIndex) { * *

        Use {@link Assertions#checkNotNull(Object)} to throw if the value is null. */ - @SuppressWarnings({"contracts.postcondition.not.satisfied", "return.type.incompatible"}) + @SuppressWarnings({"nullness:contracts.postcondition", "nullness:return"}) @EnsuresNonNull("#1") public static T castNonNull(@Nullable T value) { return value; } /** Casts a nullable type array to a non-null type array without runtime null check. */ - @SuppressWarnings({"contracts.postcondition.not.satisfied", "return.type.incompatible"}) + @SuppressWarnings({"nullness:contracts.postcondition", "nullness:return"}) @EnsuresNonNull("#1") public static T[] castNonNullTypeArray(@NullableType T[] value) { return value; @@ -357,7 +357,7 @@ public static T[] castNonNullTypeArray(@NullableType T[] value) { * @param length The output array length. Must be less or equal to the length of the input array. * @return The copied array. */ - @SuppressWarnings({"nullness:argument.type.incompatible", "nullness:return.type.incompatible"}) + @SuppressWarnings({"nullness:argument", "nullness:return"}) public static T[] nullSafeArrayCopy(T[] input, int length) { Assertions.checkArgument(length <= input.length); return Arrays.copyOf(input, length); @@ -371,7 +371,7 @@ public static T[] nullSafeArrayCopy(T[] input, int length) { * @param to The end of the range to be copied, exclusive. * @return The copied array. */ - @SuppressWarnings({"nullness:argument.type.incompatible", "nullness:return.type.incompatible"}) + @SuppressWarnings({"nullness:argument", "nullness:return"}) public static T[] nullSafeArrayCopyOfRange(T[] input, int from, int to) { Assertions.checkArgument(0 <= from); Assertions.checkArgument(to <= input.length); @@ -398,7 +398,7 @@ public static T[] nullSafeArrayAppend(T[] original, T newElement) { * @param second The second array. * @return The concatenated result. */ - @SuppressWarnings({"nullness:assignment.type.incompatible"}) + @SuppressWarnings("nullness:assignment") public static T[] nullSafeArrayConcatenation(T[] first, T[] second) { T[] concatenation = Arrays.copyOf(first, first.length + second.length); System.arraycopy( @@ -492,7 +492,7 @@ public static Handler createHandlerForCurrentOrMainLooper( * callback is required. * @return A {@link Handler} with the specified callback on the current {@link Looper} thread. */ - @SuppressWarnings({"nullness:argument.type.incompatible", "nullness:return.type.incompatible"}) + @SuppressWarnings({"nullness:argument", "nullness:return"}) public static Handler createHandler( Looper looper, @Nullable Handler.@UnknownInitialization Callback callback) { return new Handler(looper, callback); @@ -931,8 +931,8 @@ public static int binarySearchFloor( /** * Returns the index of the largest element in {@code array} that is less than (or optionally * equal to) a specified {@code value}. - *

        - * The search is performed using a binary search algorithm, so the array must be sorted. If the + * + *

        The search is performed using a binary search algorithm, so the array must be sorted. If the * array contains multiple elements equal to {@code value} and {@code inclusive} is true, the * index of the first one will be returned. * @@ -946,8 +946,8 @@ public static int binarySearchFloor( * @return The index of the largest element in {@code array} that is less than (or optionally * equal to) {@code value}. */ - public static int binarySearchFloor(long[] array, long value, boolean inclusive, - boolean stayInBounds) { + public static int binarySearchFloor( + long[] array, long value, boolean inclusive, boolean stayInBounds) { int index = Arrays.binarySearch(array, value); if (index < 0) { index = -(index + 2); @@ -1213,11 +1213,12 @@ public static long parseXsDuration(String value) { */ // incompatible types in argument. // dereference of possibly-null reference matcher.group(9) - @SuppressWarnings({"nullness:argument.type.incompatible", "nullness:dereference.of.nullable"}) + @SuppressWarnings({"nullness:argument", "nullness:dereference.of.nullable"}) public static long parseXsDateTime(String value) throws ParserException { Matcher matcher = XS_DATE_TIME_PATTERN.matcher(value); if (!matcher.matches()) { - throw new ParserException("Invalid date/time format: " + value); + throw ParserException.createForMalformedContainer( + "Invalid date/time format: " + value, /* cause= */ null); } int timezoneShift; @@ -1227,8 +1228,8 @@ public static long parseXsDateTime(String value) throws ParserException { } else if (matcher.group(9).equalsIgnoreCase("Z")) { timezoneShift = 0; } else { - timezoneShift = ((Integer.parseInt(matcher.group(12)) * 60 - + Integer.parseInt(matcher.group(13)))); + timezoneShift = + ((Integer.parseInt(matcher.group(12)) * 60 + Integer.parseInt(matcher.group(13)))); if ("-".equals(matcher.group(11))) { timezoneShift *= -1; } @@ -1238,12 +1239,13 @@ public static long parseXsDateTime(String value) throws ParserException { dateTime.clear(); // Note: The month value is 0-based, hence the -1 on group(2) - dateTime.set(Integer.parseInt(matcher.group(1)), - Integer.parseInt(matcher.group(2)) - 1, - Integer.parseInt(matcher.group(3)), - Integer.parseInt(matcher.group(4)), - Integer.parseInt(matcher.group(5)), - Integer.parseInt(matcher.group(6))); + dateTime.set( + Integer.parseInt(matcher.group(1)), + Integer.parseInt(matcher.group(2)) - 1, + Integer.parseInt(matcher.group(3)), + Integer.parseInt(matcher.group(4)), + Integer.parseInt(matcher.group(5)), + Integer.parseInt(matcher.group(6))); if (!TextUtils.isEmpty(matcher.group(8))) { final BigDecimal bd = new BigDecimal("0." + matcher.group(8)); // we care only for milliseconds, so movePointRight(3) @@ -1260,9 +1262,9 @@ public static long parseXsDateTime(String value) throws ParserException { /** * Scales a large timestamp. - *

        - * Logically, scaling consists of a multiplication followed by a division. The actual operations - * performed are designed to minimize the probability of overflow. + * + *

        Logically, scaling consists of a multiplication followed by a division. The actual + * operations performed are designed to minimize the probability of overflow. * * @param timestamp The timestamp to scale. * @param multiplier The multiplier. @@ -1432,8 +1434,10 @@ public static byte[] getBytesFromHexString(String hexString) { byte[] data = new byte[hexString.length() / 2]; for (int i = 0; i < data.length; i++) { int stringOffset = i * 2; - data[i] = (byte) ((Character.digit(hexString.charAt(stringOffset), 16) << 4) - + Character.digit(hexString.charAt(stringOffset + 1), 16)); + data[i] = + (byte) + ((Character.digit(hexString.charAt(stringOffset), 16) << 4) + + Character.digit(hexString.charAt(stringOffset + 1), 16)); } return data; } @@ -1487,8 +1491,13 @@ public static String getUserAgent(Context context, String applicationName) { } catch (NameNotFoundException e) { versionName = "?"; } - return applicationName + "/" + versionName + " (Linux;Android " + Build.VERSION.RELEASE - + ") " + ExoPlayerLibraryInfo.VERSION_SLASHY; + return applicationName + + "/" + + versionName + + " (Linux;Android " + + Build.VERSION.RELEASE + + ") " + + ExoPlayerLibraryInfo.VERSION_SLASHY; } /** Returns the number of codec strings in {@code codecs} whose type matches {@code trackType}. */ @@ -1677,9 +1686,7 @@ public static int getPcmFrameSize(@C.PcmEncoding int pcmEncoding, int channelCou } } - /** - * Returns the {@link C.AudioUsage} corresponding to the specified {@link C.StreamType}. - */ + /** Returns the {@link C.AudioUsage} corresponding to the specified {@link C.StreamType}. */ @C.AudioUsage public static int getAudioUsageForStreamType(@C.StreamType int streamType) { switch (streamType) { @@ -1701,9 +1708,7 @@ public static int getAudioUsageForStreamType(@C.StreamType int streamType) { } } - /** - * Returns the {@link C.AudioContentType} corresponding to the specified {@link C.StreamType}. - */ + /** Returns the {@link C.AudioContentType} corresponding to the specified {@link C.StreamType}. */ @C.AudioContentType public static int getAudioContentTypeForStreamType(@C.StreamType int streamType) { switch (streamType) { @@ -1721,9 +1726,7 @@ public static int getAudioContentTypeForStreamType(@C.StreamType int streamType) } } - /** - * Returns the {@link C.StreamType} corresponding to the specified {@link C.AudioUsage}. - */ + /** Returns the {@link C.StreamType} corresponding to the specified {@link C.AudioUsage}. */ @C.StreamType public static int getStreamTypeForAudioUsage(@C.AudioUsage int usage) { switch (usage) { @@ -1933,10 +1936,10 @@ public static String getStringForTime(StringBuilder builder, Formatter formatter * Escapes a string so that it's safe for use as a file or directory name on at least FAT32 * filesystems. FAT32 is the most restrictive of all filesystems still commonly used today. * - *

        For simplicity, this only handles common characters known to be illegal on FAT32: - * <, >, :, ", /, \, |, ?, and *. % is also escaped since it is used as the escape - * character. Escaping is performed in a consistent way so that no collisions occur and - * {@link #unescapeFileName(String)} can be used to retrieve the original file name. + *

        For simplicity, this only handles common characters known to be illegal on FAT32: <, + * >, :, ", /, \, |, ?, and *. % is also escaped since it is used as the escape character. + * Escaping is performed in a consistent way so that no collisions occur and {@link + * #unescapeFileName(String)} can be used to retrieve the original file name. * * @param fileName File name to be escaped. * @return An escaped file name which will be safe for use on at least FAT32 filesystems. @@ -2035,8 +2038,8 @@ public static Uri getDataUriForString(String mimeType, String data) { } /** - * A hacky method that always throws {@code t} even if {@code t} is a checked exception, - * and is not declared to be thrown. + * A hacky method that always throws {@code t} even if {@code t} is a checked exception, and is + * not declared to be thrown. */ public static void sneakyThrow(Throwable t) { sneakyThrowInternal(t); @@ -2083,8 +2086,9 @@ public static File createTempFile(Context context, String prefix) throws IOExcep */ public static int crc32(byte[] bytes, int start, int end, int initialValue) { for (int i = start; i < end; i++) { - initialValue = (initialValue << 8) - ^ CRC32_BYTES_MSBF[((initialValue >>> 24) ^ (bytes[i] & 0xFF)) & 0xFF]; + initialValue = + (initialValue << 8) + ^ CRC32_BYTES_MSBF[((initialValue >>> 24) ^ (bytes[i] & 0xFF)) & 0xFF]; } return initialValue; } @@ -2112,7 +2116,9 @@ public static byte[] gzip(byte[] input) { try (GZIPOutputStream os = new GZIPOutputStream(output)) { os.write(input); } catch (IOException e) { - throw new AssertionError(e); + // A ByteArrayOutputStream wrapped in a GZipOutputStream should never throw IOException since + // no I/O is happening. + throw new IllegalStateException(e); } return output.toByteArray(); } @@ -2389,6 +2395,34 @@ public static boolean tableExists(SQLiteDatabase database, String tableName) { return count > 0; } + /** + * Attempts to parse an error code from a diagnostic string found in framework media exceptions. + * + *

        For example: android.media.MediaCodec.error_1 or android.media.MediaDrm.error_neg_2. + * + * @param diagnosticsInfo A string from which to parse the error code. + * @return The parser error code, or 0 if an error code could not be parsed. + */ + public static int getErrorCodeFromPlatformDiagnosticsInfo(@Nullable String diagnosticsInfo) { + // TODO (internal b/192337376): Change 0 for ERROR_UNKNOWN once available. + if (diagnosticsInfo == null) { + return 0; + } + String[] strings = split(diagnosticsInfo, "_"); + int length = strings.length; + if (length < 2) { + return 0; + } + String digitsSection = strings[length - 1]; + boolean isNegative = length >= 3 && "neg".equals(strings[length - 2]); + try { + int errorCode = Integer.parseInt(Assertions.checkNotNull(digitsSection)); + return isNegative ? -errorCode : errorCode; + } catch (NumberFormatException e) { + return 0; + } + } + @Nullable private static String getSystemProperty(String name) { try { diff --git a/library/common/src/main/java/com/google/android/exoplayer2/video/AvcConfig.java b/library/common/src/main/java/com/google/android/exoplayer2/video/AvcConfig.java index 975b66f0939..a6c5577749a 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/video/AvcConfig.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/video/AvcConfig.java @@ -66,8 +66,9 @@ public static AvcConfig parse(ParsableByteArray data) throws ParserException { @Nullable String codecs = null; if (numSequenceParameterSets > 0) { byte[] sps = initializationData.get(0); - SpsData spsData = NalUnitUtil.parseSpsNalUnit(initializationData.get(0), - nalUnitLengthFieldLength, sps.length); + SpsData spsData = + NalUnitUtil.parseSpsNalUnit( + initializationData.get(0), nalUnitLengthFieldLength, sps.length); width = spsData.width; height = spsData.height; pixelWidthAspectRatio = spsData.pixelWidthAspectRatio; @@ -84,7 +85,7 @@ public static AvcConfig parse(ParsableByteArray data) throws ParserException { pixelWidthAspectRatio, codecs); } catch (ArrayIndexOutOfBoundsException e) { - throw new ParserException("Error parsing AVC config", e); + throw ParserException.createForMalformedContainer("Error parsing AVC config", e); } } @@ -109,5 +110,4 @@ private static byte[] buildNalUnitForChild(ParsableByteArray data) { data.skipBytes(length); return CodecSpecificDataUtil.buildNalUnit(data.getData(), offset, length); } - } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/video/ColorInfo.java b/library/common/src/main/java/com/google/android/exoplayer2/video/ColorInfo.java index 6d66c91f6c3..38fe9686688 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/video/ColorInfo.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/video/ColorInfo.java @@ -22,23 +22,67 @@ import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.util.Util; import java.util.Arrays; +import org.checkerframework.dataflow.qual.Pure; /** Stores color info. */ public final class ColorInfo implements Parcelable { + /** + * Returns the {@link C.ColorSpace} corresponding to the given ISO color primary code, as per + * table A.7.21.1 in Rec. ITU-T T.832 (03/2009), or {@link Format#NO_VALUE} if no mapping can be + * made. + */ + @Pure + @C.ColorSpace + public static int isoColorPrimariesToColorSpace(int isoColorPrimaries) { + switch (isoColorPrimaries) { + case 1: + return C.COLOR_SPACE_BT709; + case 4: // BT.470M. + case 5: // BT.470BG. + case 6: // SMPTE 170M. + case 7: // SMPTE 240M. + return C.COLOR_SPACE_BT601; + case 9: + return C.COLOR_SPACE_BT2020; + default: + return Format.NO_VALUE; + } + } + + /** + * Returns the {@link C.ColorTransfer} corresponding to the given ISO transfer characteristics + * code, as per table A.7.21.2 in Rec. ITU-T T.832 (03/2009), or {@link Format#NO_VALUE} if no + * mapping can be made. + */ + @Pure + @C.ColorTransfer + public static int isoTransferCharacteristicsToColorTransfer(int isoTransferCharacteristics) { + switch (isoTransferCharacteristics) { + case 1: // BT.709. + case 6: // SMPTE 170M. + case 7: // SMPTE 240M. + return C.COLOR_TRANSFER_SDR; + case 16: + return C.COLOR_TRANSFER_ST2084; + case 18: + return C.COLOR_TRANSFER_HLG; + default: + return Format.NO_VALUE; + } + } + /** * The color space of the video. Valid values are {@link C#COLOR_SPACE_BT601}, {@link * C#COLOR_SPACE_BT709}, {@link C#COLOR_SPACE_BT2020} or {@link Format#NO_VALUE} if unknown. */ - @C.ColorSpace - public final int colorSpace; + @C.ColorSpace public final int colorSpace; /** * The color range of the video. Valid values are {@link C#COLOR_RANGE_LIMITED}, {@link * C#COLOR_RANGE_FULL} or {@link Format#NO_VALUE} if unknown. */ - @C.ColorRange - public final int colorRange; + @C.ColorRange public final int colorRange; /** * The color transfer characteristics of the video. Valid values are {@link C#COLOR_TRANSFER_HLG}, @@ -99,8 +143,15 @@ public boolean equals(@Nullable Object obj) { @Override public String toString() { - return "ColorInfo(" + colorSpace + ", " + colorRange + ", " + colorTransfer - + ", " + (hdrStaticInfo != null) + ")"; + return "ColorInfo(" + + colorSpace + + ", " + + colorRange + + ", " + + colorTransfer + + ", " + + (hdrStaticInfo != null) + + ")"; } @Override diff --git a/library/common/src/main/java/com/google/android/exoplayer2/video/HevcConfig.java b/library/common/src/main/java/com/google/android/exoplayer2/video/HevcConfig.java index c058457665e..567485ba927 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/video/HevcConfig.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/video/HevcConfig.java @@ -64,7 +64,11 @@ public static HevcConfig parse(ParsableByteArray data) throws ParserException { int numberOfNalUnits = data.readUnsignedShort(); for (int j = 0; j < numberOfNalUnits; j++) { int nalUnitLength = data.readUnsignedShort(); - System.arraycopy(NalUnitUtil.NAL_START_CODE, 0, buffer, bufferPosition, + System.arraycopy( + NalUnitUtil.NAL_START_CODE, + 0, + buffer, + bufferPosition, NalUnitUtil.NAL_START_CODE.length); bufferPosition += NalUnitUtil.NAL_START_CODE.length; System.arraycopy( @@ -86,7 +90,7 @@ public static HevcConfig parse(ParsableByteArray data) throws ParserException { List initializationData = csdLength == 0 ? null : Collections.singletonList(buffer); return new HevcConfig(initializationData, lengthSizeMinusOne + 1, codecs); } catch (ArrayIndexOutOfBoundsException e) { - throw new ParserException("Error parsing HEVC config", e); + throw ParserException.createForMalformedContainer("Error parsing HEVC config", e); } } @@ -116,5 +120,4 @@ private HevcConfig( this.nalUnitLengthFieldLength = nalUnitLengthFieldLength; this.codecs = codecs; } - } diff --git a/library/common/src/test/java/com/google/android/exoplayer2/ExoPlaybackExceptionTest.java b/library/common/src/test/java/com/google/android/exoplayer2/ExoPlaybackExceptionTest.java index 1721ce807ad..d47c58fed89 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/ExoPlaybackExceptionTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/ExoPlaybackExceptionTest.java @@ -31,7 +31,7 @@ public class ExoPlaybackExceptionTest { public void roundTripViaBundle_ofExoPlaybackExceptionTypeRemote_yieldsEqualInstance() { ExoPlaybackException before = ExoPlaybackException.createForRemote(/* message= */ "test"); ExoPlaybackException after = ExoPlaybackException.CREATOR.fromBundle(before.toBundle()); - assertThat(areEqual(before, after)).isTrue(); + assertThat(areExoPlaybackExceptionsEqual(before, after)).isTrue(); } @Test @@ -43,25 +43,29 @@ public void roundTripViaBundle_ofExoPlaybackExceptionTypeRenderer_yieldsEqualIns /* rendererIndex= */ 123, /* rendererFormat= */ new Format.Builder().setCodecs("anyCodec").build(), /* rendererFormatSupport= */ C.FORMAT_UNSUPPORTED_SUBTYPE, - /* isRecoverable= */ true); + /* isRecoverable= */ true, + /* errorCode= */ PlaybackException.ERROR_CODE_DECODER_INIT_FAILED); ExoPlaybackException after = ExoPlaybackException.CREATOR.fromBundle(before.toBundle()); - assertThat(areEqual(before, after)).isTrue(); + assertThat(areExoPlaybackExceptionsEqual(before, after)).isTrue(); } @Test public void - roundTripViaBundle_ofExoPlaybackExceptionTypeRendererWithPrivateCause_yieldsRemoteExceptionWithSameMessage() { + roundTripViaBundle_ofExoPlaybackExceptionTypeUnexpectedWithPrivateCause_yieldsRemoteExceptionWithSameMessage() { ExoPlaybackException before = - ExoPlaybackException.createForRenderer( - new Exception(/* message= */ "anonymous exception that class loader cannot know") {}); + ExoPlaybackException.createForUnexpected( + new RuntimeException( + /* message= */ "anonymous exception that class loader cannot know") {}, + PlaybackException.ERROR_CODE_TIMEOUT); ExoPlaybackException after = ExoPlaybackException.CREATOR.fromBundle(before.toBundle()); assertThat(after.getCause()).isInstanceOf(RemoteException.class); assertThat(after.getCause()).hasMessageThat().isEqualTo(before.getCause().getMessage()); } - private static boolean areEqual(ExoPlaybackException a, ExoPlaybackException b) { + private static boolean areExoPlaybackExceptionsEqual( + ExoPlaybackException a, ExoPlaybackException b) { if (a == null || b == null) { return a == b; } @@ -73,10 +77,10 @@ private static boolean areEqual(ExoPlaybackException a, ExoPlaybackException b) && a.rendererFormatSupport == b.rendererFormatSupport && a.timestampMs == b.timestampMs && a.isRecoverable == b.isRecoverable - && areEqual(a.getCause(), b.getCause()); + && areThrowablesEqual(a.getCause(), b.getCause()); } - private static boolean areEqual(Throwable a, Throwable b) { + private static boolean areThrowablesEqual(Throwable a, Throwable b) { if (a == null || b == null) { return a == b; } diff --git a/library/common/src/test/java/com/google/android/exoplayer2/ForwardingPlayerTest.java b/library/common/src/test/java/com/google/android/exoplayer2/ForwardingPlayerTest.java new file mode 100644 index 00000000000..38bf1151357 --- /dev/null +++ b/library/common/src/test/java/com/google/android/exoplayer2/ForwardingPlayerTest.java @@ -0,0 +1,245 @@ +/* + * 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 com.google.android.exoplayer2; + +import static com.google.android.exoplayer2.Player.EVENT_IS_PLAYING_CHANGED; +import static com.google.android.exoplayer2.Player.EVENT_MEDIA_ITEM_TRANSITION; +import static com.google.android.exoplayer2.Player.EVENT_TIMELINE_CHANGED; +import static com.google.android.exoplayer2.util.Assertions.checkArgument; +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.testutil.StubExoPlayer; +import com.google.android.exoplayer2.util.FlagSet; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Queue; +import java.util.Set; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; + +/** Unit tests for {@link ForwardingPlayer}. */ +@RunWith(AndroidJUnit4.class) +public class ForwardingPlayerTest { + + @Test + public void addListener_addsForwardingListener() { + FakePlayer player = new FakePlayer(); + Player.Listener listener1 = mock(Player.Listener.class); + Player.Listener listener2 = mock(Player.Listener.class); + + ForwardingPlayer forwardingPlayer = new ForwardingPlayer(player); + forwardingPlayer.addListener(listener1); + // Add listener1 again. + forwardingPlayer.addListener(listener1); + forwardingPlayer.addListener(listener2); + + assertThat(player.listeners).hasSize(2); + } + + @Test + @SuppressWarnings("deprecation") // Testing backwards compatibility with deprecated method. + public void addEventListener_addsForwardingListener() { + FakePlayer player = new FakePlayer(); + Player.EventListener listener1 = mock(Player.EventListener.class); + Player.EventListener listener2 = mock(Player.EventListener.class); + + ForwardingPlayer forwardingPlayer = new ForwardingPlayer(player); + forwardingPlayer.addListener(listener1); + // Add listener1 again. + forwardingPlayer.addListener(listener1); + forwardingPlayer.addListener(listener2); + + assertThat(player.eventListeners).hasSize(2); + } + + @Test + public void removeListener_removesForwardingListener() { + FakePlayer player = new FakePlayer(); + Player.Listener listener1 = mock(Player.Listener.class); + Player.Listener listener2 = mock(Player.Listener.class); + ForwardingPlayer forwardingPlayer = new ForwardingPlayer(player); + forwardingPlayer.addListener(listener1); + forwardingPlayer.addListener(listener2); + + forwardingPlayer.removeListener(listener1); + assertThat(player.listeners).hasSize(1); + // Remove same listener again. + forwardingPlayer.removeListener(listener1); + assertThat(player.listeners).hasSize(1); + forwardingPlayer.removeListener(listener2); + assertThat(player.listeners).isEmpty(); + } + + @Test + @SuppressWarnings("deprecation") // Testing backwards compatibility with deprecated method. + public void removeEventListener_removesForwardingListener() { + FakePlayer player = new FakePlayer(); + Player.EventListener listener1 = mock(Player.EventListener.class); + Player.EventListener listener2 = mock(Player.EventListener.class); + ForwardingPlayer forwardingPlayer = new ForwardingPlayer(player); + forwardingPlayer.addListener(listener1); + forwardingPlayer.addListener(listener2); + + forwardingPlayer.removeListener(listener1); + assertThat(player.eventListeners).hasSize(1); + // Remove same listener again. + forwardingPlayer.removeListener(listener1); + assertThat(player.eventListeners).hasSize(1); + forwardingPlayer.removeListener(listener2); + assertThat(player.eventListeners).isEmpty(); + } + + @Test + public void onEvents_passesForwardingPlayerAsArgument() { + FakePlayer player = new FakePlayer(); + Player.Listener listener = mock(Player.Listener.class); + ForwardingPlayer forwardingPlayer = new ForwardingPlayer(player); + forwardingPlayer.addListener(listener); + Player.Listener forwardingListener = player.listeners.iterator().next(); + + forwardingListener.onEvents( + player, + new Player.Events( + new FlagSet.Builder() + .addAll( + EVENT_TIMELINE_CHANGED, EVENT_MEDIA_ITEM_TRANSITION, EVENT_IS_PLAYING_CHANGED) + .build())); + + ArgumentCaptor eventsArgumentCaptor = + ArgumentCaptor.forClass(Player.Events.class); + verify(listener).onEvents(same(forwardingPlayer), eventsArgumentCaptor.capture()); + Player.Events receivedEvents = eventsArgumentCaptor.getValue(); + assertThat(receivedEvents.size()).isEqualTo(3); + assertThat(receivedEvents.contains(EVENT_TIMELINE_CHANGED)).isTrue(); + assertThat(receivedEvents.contains(EVENT_MEDIA_ITEM_TRANSITION)).isTrue(); + assertThat(receivedEvents.contains(EVENT_IS_PLAYING_CHANGED)).isTrue(); + } + + @Test + public void forwardingPlayer_overridesAllPlayerMethods() throws Exception { + // Check with reflection that ForwardingPlayer overrides all Player methods. + List methods = getPublicMethods(Player.class); + for (int i = 0; i < methods.size(); i++) { + Method method = methods.get(i); + assertThat( + ForwardingPlayer.class.getDeclaredMethod( + method.getName(), method.getParameterTypes())) + .isNotNull(); + } + } + + @Test + @SuppressWarnings("deprecation") // Testing backwards compatibility with deprecated type. + public void forwardingEventListener_overridesAllEventListenerMethods() throws Exception { + // Check with reflection that ForwardingListener overrides all Listener methods. + Class forwardingListenerClass = getInnerClass("ForwardingEventListener"); + List methods = getPublicMethods(Player.EventListener.class); + for (int i = 0; i < methods.size(); i++) { + Method method = methods.get(i); + assertThat( + forwardingListenerClass.getDeclaredMethod( + method.getName(), method.getParameterTypes())) + .isNotNull(); + } + } + + @Test + public void forwardingListener_overridesAllListenerMethods() throws Exception { + // Check with reflection that ForwardingListener overrides all Listener methods. + Class forwardingListenerClass = getInnerClass("ForwardingListener"); + List methods = getPublicMethods(Player.Listener.class); + for (int i = 0; i < methods.size(); i++) { + Method method = methods.get(i); + assertThat(forwardingListenerClass.getMethod(method.getName(), method.getParameterTypes())) + .isNotNull(); + } + } + + /** Returns all the public methods of a Java interface. */ + private static List getPublicMethods(Class anInterface) { + checkArgument(anInterface.isInterface()); + // Run a BFS over all extended interfaces to inspect them all. + Queue> interfacesQueue = new ArrayDeque<>(); + interfacesQueue.add(anInterface); + Set> interfaces = new HashSet<>(); + while (!interfacesQueue.isEmpty()) { + Class currentInterface = interfacesQueue.remove(); + if (interfaces.add(currentInterface)) { + Collections.addAll(interfacesQueue, currentInterface.getInterfaces()); + } + } + + List list = new ArrayList<>(); + for (Class currentInterface : interfaces) { + for (Method method : currentInterface.getDeclaredMethods()) { + if (Modifier.isPublic(method.getModifiers())) { + list.add(method); + } + } + } + + return list; + } + + private static Class getInnerClass(String className) { + for (Class innerClass : ForwardingPlayer.class.getDeclaredClasses()) { + if (innerClass.getSimpleName().equals(className)) { + return innerClass; + } + } + throw new IllegalStateException(); + } + + private static class FakePlayer extends StubExoPlayer { + + @SuppressWarnings("deprecation") // Use of deprecated type for backwards compatibility. + private final Set eventListeners = new HashSet<>(); + + private final Set listeners = new HashSet<>(); + + @Override + @SuppressWarnings("deprecation") // Implementing deprecated method. + public void addListener(EventListener listener) { + eventListeners.add(listener); + } + + @Override + public void addListener(Listener listener) { + listeners.add(listener); + } + + @Override + @SuppressWarnings("deprecation") // Implementing deprecated method. + public void removeListener(EventListener listener) { + eventListeners.remove(listener); + } + + @Override + public void removeListener(Listener listener) { + listeners.remove(listener); + } + } +} diff --git a/library/common/src/test/java/com/google/android/exoplayer2/MediaMetadataTest.java b/library/common/src/test/java/com/google/android/exoplayer2/MediaMetadataTest.java index 47aa1a6833d..769758647ea 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/MediaMetadataTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/MediaMetadataTest.java @@ -20,13 +20,6 @@ import android.net.Uri; import android.os.Bundle; import androidx.test.ext.junit.runners.AndroidJUnit4; -import com.google.android.exoplayer2.metadata.Metadata; -import com.google.android.exoplayer2.metadata.id3.ApicFrame; -import com.google.android.exoplayer2.metadata.id3.TextInformationFrame; -import com.google.android.exoplayer2.util.MimeTypes; -import com.google.common.collect.ImmutableList; -import java.util.Arrays; -import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; @@ -49,12 +42,25 @@ public void builder_minimal_correctDefaults() { assertThat(mediaMetadata.userRating).isNull(); assertThat(mediaMetadata.overallRating).isNull(); assertThat(mediaMetadata.artworkData).isNull(); + assertThat(mediaMetadata.artworkDataType).isNull(); assertThat(mediaMetadata.artworkUri).isNull(); assertThat(mediaMetadata.trackNumber).isNull(); assertThat(mediaMetadata.totalTrackCount).isNull(); assertThat(mediaMetadata.folderType).isNull(); assertThat(mediaMetadata.isPlayable).isNull(); - assertThat(mediaMetadata.year).isNull(); + assertThat(mediaMetadata.recordingYear).isNull(); + assertThat(mediaMetadata.recordingMonth).isNull(); + assertThat(mediaMetadata.recordingDay).isNull(); + assertThat(mediaMetadata.releaseYear).isNull(); + assertThat(mediaMetadata.releaseMonth).isNull(); + assertThat(mediaMetadata.releaseDay).isNull(); + assertThat(mediaMetadata.composer).isNull(); + assertThat(mediaMetadata.conductor).isNull(); + assertThat(mediaMetadata.writer).isNull(); + assertThat(mediaMetadata.discNumber).isNull(); + assertThat(mediaMetadata.totalDiscCount).isNull(); + assertThat(mediaMetadata.genre).isNull(); + assertThat(mediaMetadata.compilation).isNull(); assertThat(mediaMetadata.extras).isNull(); } @@ -70,9 +76,10 @@ public void builderSetTitle_setsTitle() { @Test public void builderSetArtworkData_setsArtworkData() { byte[] bytes = new byte[] {35, 12, 6, 77}; - MediaMetadata mediaMetadata = new MediaMetadata.Builder().setArtworkData(bytes).build(); + MediaMetadata mediaMetadata = + new MediaMetadata.Builder().setArtworkData(new byte[] {35, 12, 6, 77}, null).build(); - assertThat(Arrays.equals(mediaMetadata.artworkData, bytes)).isTrue(); + assertThat(mediaMetadata.artworkData).isEqualTo(bytes); } @Test @@ -95,12 +102,25 @@ public void roundTripViaBundle_yieldsEqualInstance() { .setMediaUri(Uri.parse("https://www.google.com")) .setUserRating(new HeartRating(false)) .setOverallRating(new PercentageRating(87.4f)) - .setArtworkData(new byte[] {-88, 12, 3, 2, 124, -54, -33, 69}) + .setArtworkData( + new byte[] {-88, 12, 3, 2, 124, -54, -33, 69}, MediaMetadata.PICTURE_TYPE_MEDIA) .setTrackNumber(4) .setTotalTrackCount(12) .setFolderType(MediaMetadata.FOLDER_TYPE_PLAYLISTS) .setIsPlayable(true) - .setYear(2000) + .setRecordingYear(2000) + .setRecordingMonth(11) + .setRecordingDay(23) + .setReleaseYear(2001) + .setReleaseMonth(1) + .setReleaseDay(2) + .setComposer("Composer") + .setConductor("Conductor") + .setWriter("Writer") + .setDiscNumber(1) + .setTotalDiscCount(3) + .setGenre("Pop") + .setCompilation("Amazing songs.") .setExtras(extras) // Extras is not implemented in MediaMetadata.equals(Object o). .build(); @@ -108,56 +128,4 @@ public void roundTripViaBundle_yieldsEqualInstance() { assertThat(fromBundle).isEqualTo(mediaMetadata); assertThat(fromBundle.extras.getString("exampleKey")).isEqualTo("exampleValue"); } - - @Test - public void builderPopulatedFromTextInformationFrameEntry_setsValues() { - String title = "the title"; - String artist = "artist"; - String albumTitle = "album title"; - String albumArtist = "album Artist"; - String trackNumberInfo = "11/17"; - String year = "2000"; - - List entries = - ImmutableList.of( - new TextInformationFrame(/* id= */ "TT2", /* description= */ null, /* value= */ title), - new TextInformationFrame(/* id= */ "TP1", /* description= */ null, /* value= */ artist), - new TextInformationFrame( - /* id= */ "TAL", /* description= */ null, /* value= */ albumTitle), - new TextInformationFrame( - /* id= */ "TP2", /* description= */ null, /* value= */ albumArtist), - new TextInformationFrame( - /* id= */ "TRK", /* description= */ null, /* value= */ trackNumberInfo), - new TextInformationFrame(/* id= */ "TYE", /* description= */ null, /* value= */ year)); - MediaMetadata.Builder builder = MediaMetadata.EMPTY.buildUpon(); - - for (Metadata.Entry entry : entries) { - entry.populateMediaMetadata(builder); - } - - assertThat(builder.build().title.toString()).isEqualTo(title); - assertThat(builder.build().artist.toString()).isEqualTo(artist); - assertThat(builder.build().albumTitle.toString()).isEqualTo(albumTitle); - assertThat(builder.build().albumArtist.toString()).isEqualTo(albumArtist); - assertThat(builder.build().trackNumber).isEqualTo(11); - assertThat(builder.build().totalTrackCount).isEqualTo(17); - assertThat(builder.build().year).isEqualTo(2000); - } - - @Test - public void builderPopulatedFromApicFrameEntry_setsArtwork() { - byte[] pictureData = new byte[] {-12, 52, 33, 85, 34, 22, 1, -55}; - Metadata.Entry entry = - new ApicFrame( - /* mimeType= */ MimeTypes.BASE_TYPE_IMAGE, - /* description= */ "an image", - /* pictureType= */ 0x03, - pictureData); - - MediaMetadata.Builder builder = MediaMetadata.EMPTY.buildUpon(); - entry.populateMediaMetadata(builder); - - MediaMetadata mediaMetadata = builder.build(); - assertThat(mediaMetadata.artworkData).isEqualTo(pictureData); - } } diff --git a/library/common/src/test/java/com/google/android/exoplayer2/PlaybackExceptionTest.java b/library/common/src/test/java/com/google/android/exoplayer2/PlaybackExceptionTest.java new file mode 100644 index 00000000000..b963c847c7b --- /dev/null +++ b/library/common/src/test/java/com/google/android/exoplayer2/PlaybackExceptionTest.java @@ -0,0 +1,116 @@ +/* + * 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 com.google.android.exoplayer2; + +import static com.google.common.truth.Truth.assertThat; + +import android.os.Bundle; +import android.os.RemoteException; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import java.io.IOException; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** Unit tests for {@link PlaybackException}. */ +@RunWith(AndroidJUnit4.class) +public class PlaybackExceptionTest { + + @Test + public void roundTripViaBundle_yieldsEqualInstance() { + PlaybackException before = + new PlaybackException( + /* message= */ "test", + /* cause= */ new IOException(/* message= */ "io"), + PlaybackException.ERROR_CODE_IO_FILE_NOT_FOUND); + PlaybackException after = PlaybackException.CREATOR.fromBundle(before.toBundle()); + assertPlaybackExceptionsAreEquivalent(before, after); + } + + // Backward compatibility tests. + // The following tests prevent accidental modifications which break communication with older + // ExoPlayer versions hosted in other processes. + + @Test + public void bundle_producesExpectedException() { + IOException expectedCause = new IOException("cause message"); + PlaybackException expectedException = + new PlaybackException( + "message", + expectedCause, + PlaybackException.ERROR_CODE_AUDIO_TRACK_INIT_FAILED, + /* timestampMs= */ 1000); + + Bundle bundle = new Bundle(); + bundle.putInt("0", 5001); // Error code + bundle.putLong("1", 1000); // Timestamp. + bundle.putString("2", "message"); + bundle.putString("3", expectedCause.getClass().getName()); + bundle.putString("4", "cause message"); + + assertPlaybackExceptionsAreEquivalent( + expectedException, PlaybackException.CREATOR.fromBundle(bundle)); + } + + @Test + public void exception_producesExpectedBundle() { + IllegalStateException cause = new IllegalStateException("cause message"); + PlaybackException exception = + new PlaybackException( + "message", + cause, + PlaybackException.ERROR_CODE_DECODING_FAILED, + /* timestampMs= */ 2000); + + Bundle bundle = exception.toBundle(); + assertThat(bundle.getInt("0")).isEqualTo(4003); // Error code. + assertThat(bundle.getLong("1")).isEqualTo(2000); // Timestamp. + assertThat(bundle.getString("2")).isEqualTo("message"); + assertThat(bundle.getString("3")).isEqualTo(cause.getClass().getName()); + assertThat(bundle.getString("4")).isEqualTo("cause message"); + } + + @Test + public void bundleWithUnexpectedCause_producesRemoteExceptionCause() { + RemoteException expectedCause = new RemoteException("cause message"); + PlaybackException expectedException = + new PlaybackException( + "message", + expectedCause, + PlaybackException.ERROR_CODE_AUDIO_TRACK_INIT_FAILED, + /* timestampMs= */ 1000); + + Bundle bundle = new Bundle(); + bundle.putInt("0", 5001); // Error code + bundle.putLong("1", 1000); // Timestamp. + bundle.putString("2", "message"); + bundle.putString("3", "invalid cause class name"); + bundle.putString("4", "cause message"); + + assertPlaybackExceptionsAreEquivalent( + expectedException, PlaybackException.CREATOR.fromBundle(bundle)); + } + + // Internal methods. + + private static void assertPlaybackExceptionsAreEquivalent( + PlaybackException a, PlaybackException b) { + assertThat(a).hasMessageThat().isEqualTo(b.getMessage()); + assertThat(a.errorCode).isEqualTo(b.errorCode); + assertThat(a.timestampMs).isEqualTo(b.timestampMs); + assertThat(a.getCause().getClass()).isSameInstanceAs(b.getCause().getClass()); + assertThat(a).hasCauseThat().hasMessageThat().isEqualTo(b.getCause().getMessage()); + } +} diff --git a/library/common/src/test/java/com/google/android/exoplayer2/metadata/emsg/EventMessageDecoderTest.java b/library/common/src/test/java/com/google/android/exoplayer2/metadata/emsg/EventMessageDecoderTest.java index 2bd02446daa..5d3aad24b27 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/metadata/emsg/EventMessageDecoderTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/metadata/emsg/EventMessageDecoderTest.java @@ -50,7 +50,7 @@ public void decodeEventMessage() { assertThat(eventMessage.value).isEqualTo("123"); assertThat(eventMessage.durationMs).isEqualTo(3000); assertThat(eventMessage.id).isEqualTo(1000403); - assertThat(eventMessage.messageData).isEqualTo(new byte[]{0, 1, 2, 3, 4}); + assertThat(eventMessage.messageData).isEqualTo(new byte[] {0, 1, 2, 3, 4}); } @Test diff --git a/library/common/src/test/java/com/google/android/exoplayer2/metadata/emsg/EventMessageTest.java b/library/common/src/test/java/com/google/android/exoplayer2/metadata/emsg/EventMessageTest.java index 9a47b81d448..536392f85eb 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/metadata/emsg/EventMessageTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/metadata/emsg/EventMessageTest.java @@ -39,5 +39,4 @@ public void eventMessageParcelable() { // Assert equals. assertThat(fromParcelEventMessage).isEqualTo(eventMessage); } - } diff --git a/library/common/src/test/java/com/google/android/exoplayer2/metadata/flac/PictureFrameTest.java b/library/common/src/test/java/com/google/android/exoplayer2/metadata/flac/PictureFrameTest.java index 6b7a18e2871..1a7b7b7be04 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/metadata/flac/PictureFrameTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/metadata/flac/PictureFrameTest.java @@ -19,6 +19,9 @@ import android.os.Parcel; import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.MediaMetadata; +import com.google.android.exoplayer2.metadata.Metadata; +import com.google.android.exoplayer2.util.MimeTypes; import org.junit.Test; import org.junit.runner.RunWith; @@ -39,4 +42,107 @@ public void parcelable() { parcel.recycle(); } + + @Test + public void populateMediaMetadata_setsBuilderValues() { + byte[] pictureData = new byte[] {-12, 52, 33, 85, 34, 22, 1, -55}; + Metadata.Entry entry = + new PictureFrame( + /* pictureType= */ MediaMetadata.PICTURE_TYPE_FRONT_COVER, + /* mimeType= */ MimeTypes.IMAGE_JPEG, + /* description= */ "an image", + /* width= */ 4, + /* height= */ 2, + /* depth= */ 1, + /* colors= */ 1, + pictureData); + + MediaMetadata.Builder builder = MediaMetadata.EMPTY.buildUpon(); + entry.populateMediaMetadata(builder); + + MediaMetadata mediaMetadata = builder.build(); + assertThat(mediaMetadata.artworkData).isEqualTo(pictureData); + assertThat(mediaMetadata.artworkDataType).isEqualTo(MediaMetadata.PICTURE_TYPE_FRONT_COVER); + } + + @Test + public void populateMediaMetadata_considersTypePriority() { + byte[] data1 = new byte[] {1, 1, 1, 1}; + byte[] data2 = new byte[] {2, 2, 2, 2}; + byte[] data3 = new byte[] {3, 3, 3, 3}; + byte[] data4 = new byte[] {4, 4, 4, 4}; + byte[] data5 = new byte[] {5, 5, 5, 5}; + + Metadata.Entry entry1 = + new PictureFrame( + /* pictureType= */ MediaMetadata.PICTURE_TYPE_BAND_ORCHESTRA, + /* mimeType= */ MimeTypes.IMAGE_JPEG, + /* description= */ "an image", + /* width= */ 2, + /* height= */ 2, + /* depth= */ 1, + /* colors= */ 1, + data1); + Metadata.Entry entry2 = + new PictureFrame( + /* pictureType= */ MediaMetadata.PICTURE_TYPE_DURING_RECORDING, + /* mimeType= */ MimeTypes.IMAGE_JPEG, + /* description= */ "an image", + /* width= */ 2, + /* height= */ 2, + /* depth= */ 1, + /* colors= */ 1, + data2); + Metadata.Entry entry3 = + new PictureFrame( + /* pictureType= */ MediaMetadata.PICTURE_TYPE_FRONT_COVER, + /* mimeType= */ MimeTypes.IMAGE_JPEG, + /* description= */ "an image", + /* width= */ 2, + /* height= */ 2, + /* depth= */ 1, + /* colors= */ 1, + data3); + Metadata.Entry entry4 = + new PictureFrame( + /* pictureType= */ MediaMetadata.PICTURE_TYPE_ARTIST_PERFORMER, + /* mimeType= */ MimeTypes.IMAGE_JPEG, + /* description= */ "an image", + /* width= */ 2, + /* height= */ 2, + /* depth= */ 1, + /* colors= */ 1, + data4); + Metadata.Entry entry5 = + new PictureFrame( + /* pictureType= */ MediaMetadata.PICTURE_TYPE_FRONT_COVER, + /* mimeType= */ MimeTypes.IMAGE_JPEG, + /* description= */ "an image", + /* width= */ 2, + /* height= */ 2, + /* depth= */ 1, + /* colors= */ 1, + data5); + + MediaMetadata.Builder builder = MediaMetadata.EMPTY.buildUpon(); + + entry1.populateMediaMetadata(builder); + assertThat(builder.build().artworkData).isEqualTo(data1); + + // Data updates when any type is given, if the current type is not front cover. + entry2.populateMediaMetadata(builder); + assertThat(builder.build().artworkData).isEqualTo(data2); + + // Data updates because this entry picture type is front cover. + entry3.populateMediaMetadata(builder); + assertThat(builder.build().artworkData).isEqualTo(data3); + + // Data does not update because the current type is front cover, and this entry type is not. + entry4.populateMediaMetadata(builder); + assertThat(builder.build().artworkData).isEqualTo(data3); + + // Data updates because this entry picture type is front cover. + entry5.populateMediaMetadata(builder); + assertThat(builder.build().artworkData).isEqualTo(data5); + } } diff --git a/library/common/src/test/java/com/google/android/exoplayer2/metadata/flac/VorbisCommentTest.java b/library/common/src/test/java/com/google/android/exoplayer2/metadata/flac/VorbisCommentTest.java index e3a12a80130..4c0f0592de9 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/metadata/flac/VorbisCommentTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/metadata/flac/VorbisCommentTest.java @@ -19,6 +19,10 @@ import android.os.Parcel; import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.MediaMetadata; +import com.google.android.exoplayer2.metadata.Metadata; +import com.google.common.collect.ImmutableList; +import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; @@ -39,4 +43,32 @@ public void parcelable() { parcel.recycle(); } + + @Test + public void populateMediaMetadata_setsMediaMetadataValues() { + String title = "the title"; + String artist = "artist"; + String albumTitle = "album title"; + String albumArtist = "album Artist"; + String description = "a description about the audio."; + List entries = + ImmutableList.of( + new VorbisComment("TITLE", title), + new VorbisComment("ARTIST", artist), + new VorbisComment("ALBUM", albumTitle), + new VorbisComment("ALBUMARTIST", albumArtist), + new VorbisComment("DESCRIPTION", description)); + MediaMetadata.Builder builder = MediaMetadata.EMPTY.buildUpon(); + + for (Metadata.Entry entry : entries) { + entry.populateMediaMetadata(builder); + } + MediaMetadata mediaMetadata = builder.build(); + + assertThat(mediaMetadata.title.toString()).isEqualTo(title); + assertThat(mediaMetadata.artist.toString()).isEqualTo(artist); + assertThat(mediaMetadata.albumTitle.toString()).isEqualTo(albumTitle); + assertThat(mediaMetadata.albumArtist.toString()).isEqualTo(albumArtist); + assertThat(mediaMetadata.description.toString()).isEqualTo(description); + } } diff --git a/library/common/src/test/java/com/google/android/exoplayer2/metadata/id3/ApicFrameTest.java b/library/common/src/test/java/com/google/android/exoplayer2/metadata/id3/ApicFrameTest.java new file mode 100644 index 00000000000..3f60711b19c --- /dev/null +++ b/library/common/src/test/java/com/google/android/exoplayer2/metadata/id3/ApicFrameTest.java @@ -0,0 +1,123 @@ +/* + * 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 com.google.android.exoplayer2.metadata.id3; + +import static com.google.common.truth.Truth.assertThat; + +import android.os.Parcel; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.MediaMetadata; +import com.google.android.exoplayer2.metadata.Metadata; +import com.google.android.exoplayer2.util.MimeTypes; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** Unit test for {@link ApicFrame}. */ +@RunWith(AndroidJUnit4.class) +public class ApicFrameTest { + + @Test + public void parcelable() { + ApicFrame apicFrameToParcel = new ApicFrame("", "", 0, new byte[0]); + + Parcel parcel = Parcel.obtain(); + apicFrameToParcel.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + + ApicFrame apicFrameFromParcel = ApicFrame.CREATOR.createFromParcel(parcel); + assertThat(apicFrameFromParcel).isEqualTo(apicFrameToParcel); + + parcel.recycle(); + } + + @Test + public void populateMediaMetadata_setsBuilderValues() { + byte[] pictureData = new byte[] {-12, 52, 33, 85, 34, 22, 1, -55}; + @MediaMetadata.PictureType int pictureType = MediaMetadata.PICTURE_TYPE_LEAFLET_PAGE; + Metadata.Entry entry = + new ApicFrame( + /* mimeType= */ MimeTypes.BASE_TYPE_IMAGE, + /* description= */ "an image", + pictureType, + pictureData); + + MediaMetadata.Builder builder = MediaMetadata.EMPTY.buildUpon(); + entry.populateMediaMetadata(builder); + + MediaMetadata mediaMetadata = builder.build(); + assertThat(mediaMetadata.artworkData).isEqualTo(pictureData); + assertThat(mediaMetadata.artworkDataType).isEqualTo(pictureType); + } + + @Test + public void populateMediaMetadata_considersTypePriority() { + byte[] data1 = new byte[] {1, 1, 1, 1}; + byte[] data2 = new byte[] {2, 2, 2, 2}; + byte[] data3 = new byte[] {3, 3, 3, 3}; + byte[] data4 = new byte[] {4, 4, 4, 4}; + byte[] data5 = new byte[] {5, 5, 5, 5}; + Metadata.Entry entry1 = + new ApicFrame( + /* mimeType= */ MimeTypes.BASE_TYPE_IMAGE, + /* description= */ "an image", + MediaMetadata.PICTURE_TYPE_BAND_ARTIST_LOGO, + data1); + Metadata.Entry entry2 = + new ApicFrame( + /* mimeType= */ MimeTypes.BASE_TYPE_IMAGE, + /* description= */ "an image", + MediaMetadata.PICTURE_TYPE_ARTIST_PERFORMER, + data2); + Metadata.Entry entry3 = + new ApicFrame( + /* mimeType= */ MimeTypes.BASE_TYPE_IMAGE, + /* description= */ "an image", + MediaMetadata.PICTURE_TYPE_FRONT_COVER, + data3); + Metadata.Entry entry4 = + new ApicFrame( + /* mimeType= */ MimeTypes.BASE_TYPE_IMAGE, + /* description= */ "an image", + MediaMetadata.PICTURE_TYPE_ILLUSTRATION, + data4); + Metadata.Entry entry5 = + new ApicFrame( + /* mimeType= */ MimeTypes.BASE_TYPE_IMAGE, + /* description= */ "an image", + MediaMetadata.PICTURE_TYPE_FRONT_COVER, + data5); + MediaMetadata.Builder builder = MediaMetadata.EMPTY.buildUpon(); + + entry1.populateMediaMetadata(builder); + assertThat(builder.build().artworkData).isEqualTo(data1); + + // Data updates when any type is given, if the current type is not front cover. + entry2.populateMediaMetadata(builder); + assertThat(builder.build().artworkData).isEqualTo(data2); + + // Data updates because this entry picture type is front cover. + entry3.populateMediaMetadata(builder); + assertThat(builder.build().artworkData).isEqualTo(data3); + + // Data does not update because the current type is front cover, and this entry type is not. + entry4.populateMediaMetadata(builder); + assertThat(builder.build().artworkData).isEqualTo(data3); + + // Data updates because this entry picture type is front cover. + entry5.populateMediaMetadata(builder); + assertThat(builder.build().artworkData).isEqualTo(data5); + } +} diff --git a/library/common/src/test/java/com/google/android/exoplayer2/metadata/id3/ChapterFrameTest.java b/library/common/src/test/java/com/google/android/exoplayer2/metadata/id3/ChapterFrameTest.java index f3e883833a1..25d6ceb7802 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/metadata/id3/ChapterFrameTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/metadata/id3/ChapterFrameTest.java @@ -28,10 +28,11 @@ public final class ChapterFrameTest { @Test public void parcelable() { - Id3Frame[] subFrames = new Id3Frame[] { - new TextInformationFrame("TIT2", null, "title"), - new UrlLinkFrame("WXXX", "description", "url") - }; + Id3Frame[] subFrames = + new Id3Frame[] { + new TextInformationFrame("TIT2", null, "title"), + new UrlLinkFrame("WXXX", "description", "url") + }; ChapterFrame chapterFrameToParcel = new ChapterFrame("id", 0, 1, 2, 3, subFrames); Parcel parcel = Parcel.obtain(); @@ -43,5 +44,4 @@ public void parcelable() { parcel.recycle(); } - } diff --git a/library/common/src/test/java/com/google/android/exoplayer2/metadata/id3/ChapterTocFrameTest.java b/library/common/src/test/java/com/google/android/exoplayer2/metadata/id3/ChapterTocFrameTest.java index 0b4a9859c91..f0f8b41b70e 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/metadata/id3/ChapterTocFrameTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/metadata/id3/ChapterTocFrameTest.java @@ -29,12 +29,13 @@ public final class ChapterTocFrameTest { @Test public void parcelable() { String[] children = new String[] {"child0", "child1"}; - Id3Frame[] subFrames = new Id3Frame[] { - new TextInformationFrame("TIT2", null, "title"), - new UrlLinkFrame("WXXX", "description", "url") - }; - ChapterTocFrame chapterTocFrameToParcel = new ChapterTocFrame("id", false, true, children, - subFrames); + Id3Frame[] subFrames = + new Id3Frame[] { + new TextInformationFrame("TIT2", null, "title"), + new UrlLinkFrame("WXXX", "description", "url") + }; + ChapterTocFrame chapterTocFrameToParcel = + new ChapterTocFrame("id", false, true, children, subFrames); Parcel parcel = Parcel.obtain(); chapterTocFrameToParcel.writeToParcel(parcel, 0); @@ -45,5 +46,4 @@ public void parcelable() { parcel.recycle(); } - } diff --git a/library/common/src/test/java/com/google/android/exoplayer2/metadata/id3/Id3DecoderTest.java b/library/common/src/test/java/com/google/android/exoplayer2/metadata/id3/Id3DecoderTest.java index 972e855a5b0..f08b8f87402 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/metadata/id3/Id3DecoderTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/metadata/id3/Id3DecoderTest.java @@ -38,8 +38,13 @@ public final class Id3DecoderTest { @Test public void decodeTxxxFrame() { - byte[] rawId3 = buildSingleFrameTag("TXXX", new byte[] {3, 0, 109, 100, 105, 97, 108, 111, 103, - 95, 86, 73, 78, 68, 73, 67, 79, 49, 53, 50, 55, 54, 54, 52, 95, 115, 116, 97, 114, 116, 0}); + byte[] rawId3 = + buildSingleFrameTag( + "TXXX", + new byte[] { + 3, 0, 109, 100, 105, 97, 108, 111, 103, 95, 86, 73, 78, 68, 73, 67, 79, 49, 53, 50, + 55, 54, 54, 52, 95, 115, 116, 97, 114, 116, 0 + }); Id3Decoder decoder = new Id3Decoder(); Metadata metadata = decoder.decode(rawId3, rawId3.length); assertThat(metadata.length()).isEqualTo(1); @@ -65,8 +70,9 @@ public void decodeTxxxFrame() { @Test public void decodeTextInformationFrame() { - byte[] rawId3 = buildSingleFrameTag("TIT2", new byte[] {3, 72, 101, 108, 108, 111, 32, 87, 111, - 114, 108, 100, 0}); + byte[] rawId3 = + buildSingleFrameTag( + "TIT2", new byte[] {3, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 0}); Id3Decoder decoder = new Id3Decoder(); Metadata metadata = decoder.decode(rawId3, rawId3.length); assertThat(metadata.length()).isEqualTo(1); @@ -92,9 +98,41 @@ public void decodeTextInformationFrame() { @Test public void decodeWxxxFrame() { - byte[] rawId3 = buildSingleFrameTag("WXXX", new byte[] {ID3_TEXT_ENCODING_UTF_8, 116, 101, 115, - 116, 0, 104, 116, 116, 112, 115, 58, 47, 47, 116, 101, 115, 116, 46, 99, 111, 109, 47, 97, - 98, 99, 63, 100, 101, 102}); + byte[] rawId3 = + buildSingleFrameTag( + "WXXX", + new byte[] { + ID3_TEXT_ENCODING_UTF_8, + 116, + 101, + 115, + 116, + 0, + 104, + 116, + 116, + 112, + 115, + 58, + 47, + 47, + 116, + 101, + 115, + 116, + 46, + 99, + 111, + 109, + 47, + 97, + 98, + 99, + 63, + 100, + 101, + 102 + }); Id3Decoder decoder = new Id3Decoder(); Metadata metadata = decoder.decode(rawId3, rawId3.length); assertThat(metadata.length()).isEqualTo(1); @@ -120,8 +158,13 @@ public void decodeWxxxFrame() { @Test public void decodeUrlLinkFrame() { - byte[] rawId3 = buildSingleFrameTag("WCOM", new byte[] {104, 116, 116, 112, 115, 58, 47, 47, - 116, 101, 115, 116, 46, 99, 111, 109, 47, 97, 98, 99, 63, 100, 101, 102}); + byte[] rawId3 = + buildSingleFrameTag( + "WCOM", + new byte[] { + 104, 116, 116, 112, 115, 58, 47, 47, 116, 101, 115, 116, 46, 99, 111, 109, 47, 97, 98, + 99, 63, 100, 101, 102 + }); Id3Decoder decoder = new Id3Decoder(); Metadata metadata = decoder.decode(rawId3, rawId3.length); assertThat(metadata.length()).isEqualTo(1); @@ -148,7 +191,7 @@ public void decodePrivFrame() { assertThat(metadata.length()).isEqualTo(1); PrivFrame privFrame = (PrivFrame) metadata.get(0); assertThat(privFrame.owner).isEqualTo("test"); - assertThat(privFrame.privateData).isEqualTo(new byte[]{1, 2, 3, 4}); + assertThat(privFrame.privateData).isEqualTo(new byte[] {1, 2, 3, 4}); // Test empty. rawId3 = buildSingleFrameTag("PRIV", new byte[0]); @@ -161,9 +204,13 @@ public void decodePrivFrame() { @Test public void decodeApicFrame() { - byte[] rawId3 = buildSingleFrameTag("APIC", new byte[] {3, 105, 109, 97, 103, 101, 47, 106, 112, - 101, 103, 0, 16, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 0}); + byte[] rawId3 = + buildSingleFrameTag( + "APIC", + new byte[] { + 3, 105, 109, 97, 103, 101, 47, 106, 112, 101, 103, 0, 16, 72, 101, 108, 108, 111, 32, + 87, 111, 114, 108, 100, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 + }); Id3Decoder decoder = new Id3Decoder(); Metadata metadata = decoder.decode(rawId3, rawId3.length); assertThat(metadata.length()).isEqualTo(1); @@ -172,13 +219,37 @@ public void decodeApicFrame() { assertThat(apicFrame.pictureType).isEqualTo(16); assertThat(apicFrame.description).isEqualTo("Hello World"); assertThat(apicFrame.pictureData).hasLength(10); - assertThat(apicFrame.pictureData).isEqualTo(new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}); + assertThat(apicFrame.pictureData).isEqualTo(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}); } @Test public void decodeCommentFrame() { - byte[] rawId3 = buildSingleFrameTag("COMM", new byte[] {ID3_TEXT_ENCODING_UTF_8, 101, 110, 103, - 100, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 0, 116, 101, 120, 116, 0}); + byte[] rawId3 = + buildSingleFrameTag( + "COMM", + new byte[] { + ID3_TEXT_ENCODING_UTF_8, + 101, + 110, + 103, + 100, + 101, + 115, + 99, + 114, + 105, + 112, + 116, + 105, + 111, + 110, + 0, + 116, + 101, + 120, + 116, + 0 + }); Id3Decoder decoder = new Id3Decoder(); Metadata metadata = decoder.decode(rawId3, rawId3.length); assertThat(metadata.length()).isEqualTo(1); diff --git a/library/common/src/test/java/com/google/android/exoplayer2/metadata/id3/MlltFrameTest.java b/library/common/src/test/java/com/google/android/exoplayer2/metadata/id3/MlltFrameTest.java index 48e8fcede31..c42bd61e933 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/metadata/id3/MlltFrameTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/metadata/id3/MlltFrameTest.java @@ -45,5 +45,4 @@ public void parcelable() { parcel.recycle(); } - } diff --git a/library/common/src/test/java/com/google/android/exoplayer2/metadata/id3/TextInformationFrameTest.java b/library/common/src/test/java/com/google/android/exoplayer2/metadata/id3/TextInformationFrameTest.java new file mode 100644 index 00000000000..00fdcb6087a --- /dev/null +++ b/library/common/src/test/java/com/google/android/exoplayer2/metadata/id3/TextInformationFrameTest.java @@ -0,0 +1,111 @@ +/* + * 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 com.google.android.exoplayer2.metadata.id3; + +import static com.google.common.truth.Truth.assertThat; + +import android.os.Parcel; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.MediaMetadata; +import com.google.android.exoplayer2.metadata.Metadata; +import com.google.common.collect.ImmutableList; +import java.util.List; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** Unit test for {@link TextInformationFrame}. */ +@RunWith(AndroidJUnit4.class) +public class TextInformationFrameTest { + + @Test + public void parcelable() { + TextInformationFrame textInformationFrameToParcel = new TextInformationFrame("", "", ""); + + Parcel parcel = Parcel.obtain(); + textInformationFrameToParcel.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + + TextInformationFrame textInformationFrameFromParcel = + TextInformationFrame.CREATOR.createFromParcel(parcel); + assertThat(textInformationFrameFromParcel).isEqualTo(textInformationFrameToParcel); + + parcel.recycle(); + } + + @Test + public void populateMediaMetadata_setsBuilderValues() { + String title = "the title"; + String artist = "artist"; + String albumTitle = "album title"; + String albumArtist = "album Artist"; + String trackNumberInfo = "11/17"; + String recordingYear = "2000"; + String recordingMonth = "07"; + String recordingDay = "10"; + String releaseDate = "2001-01-02T00:00:00"; + String composer = "composer"; + String conductor = "conductor"; + String writer = "writer"; + + List entries = + ImmutableList.of( + new TextInformationFrame(/* id= */ "TT2", /* description= */ null, /* value= */ title), + new TextInformationFrame(/* id= */ "TP1", /* description= */ null, /* value= */ artist), + new TextInformationFrame( + /* id= */ "TAL", /* description= */ null, /* value= */ albumTitle), + new TextInformationFrame( + /* id= */ "TP2", /* description= */ null, /* value= */ albumArtist), + new TextInformationFrame( + /* id= */ "TRK", /* description= */ null, /* value= */ trackNumberInfo), + new TextInformationFrame( + /* id= */ "TYE", /* description= */ null, /* value= */ recordingYear), + new TextInformationFrame( + /* id= */ "TDA", + /* description= */ null, + /* value= */ recordingDay + recordingMonth), + new TextInformationFrame( + /* id= */ "TDRL", /* description= */ null, /* value= */ releaseDate), + new TextInformationFrame( + /* id= */ "TCM", /* description= */ null, /* value= */ composer), + new TextInformationFrame( + /* id= */ "TP3", /* description= */ null, /* value= */ conductor), + new TextInformationFrame( + /* id= */ "TXT", /* description= */ null, /* value= */ writer)); + MediaMetadata.Builder builder = MediaMetadata.EMPTY.buildUpon(); + + for (Metadata.Entry entry : entries) { + entry.populateMediaMetadata(builder); + } + + MediaMetadata mediaMetadata = builder.build(); + + assertThat(mediaMetadata.title.toString()).isEqualTo(title); + assertThat(mediaMetadata.artist.toString()).isEqualTo(artist); + assertThat(mediaMetadata.albumTitle.toString()).isEqualTo(albumTitle); + assertThat(mediaMetadata.albumArtist.toString()).isEqualTo(albumArtist); + assertThat(mediaMetadata.trackNumber).isEqualTo(11); + assertThat(mediaMetadata.totalTrackCount).isEqualTo(17); + assertThat(mediaMetadata.recordingYear).isEqualTo(2000); + assertThat(mediaMetadata.recordingMonth).isEqualTo(7); + assertThat(mediaMetadata.recordingDay).isEqualTo(10); + assertThat(mediaMetadata.releaseYear).isEqualTo(2001); + assertThat(mediaMetadata.releaseMonth).isEqualTo(1); + assertThat(mediaMetadata.releaseDay).isEqualTo(2); + assertThat(mediaMetadata.composer.toString()).isEqualTo(composer); + assertThat(mediaMetadata.conductor.toString()).isEqualTo(conductor); + assertThat(mediaMetadata.writer.toString()).isEqualTo(writer); + } +} diff --git a/library/common/src/test/java/com/google/android/exoplayer2/source/ads/AdPlaybackStateTest.java b/library/common/src/test/java/com/google/android/exoplayer2/source/ads/AdPlaybackStateTest.java index 948cbe2c698..90e28934b02 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/source/ads/AdPlaybackStateTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/source/ads/AdPlaybackStateTest.java @@ -23,7 +23,6 @@ import android.net.Uri; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.C; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -31,106 +30,211 @@ @RunWith(AndroidJUnit4.class) public class AdPlaybackStateTest { - private static final long[] TEST_AD_GROUP_TMES_US = new long[] {0, C.msToUs(10_000)}; + private static final long[] TEST_AD_GROUP_TIMES_US = new long[] {0, 5_000_000, 10_000_000}; private static final Uri TEST_URI = Uri.EMPTY; private static final Object TEST_ADS_ID = new Object(); - private AdPlaybackState state; - - @Before - public void setUp() { - state = new AdPlaybackState(TEST_ADS_ID, TEST_AD_GROUP_TMES_US); - } - @Test public void setAdCount() { - assertThat(state.adGroups[0].count).isEqualTo(C.LENGTH_UNSET); - state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 1); - assertThat(state.adGroups[0].count).isEqualTo(1); + AdPlaybackState state = + new AdPlaybackState(TEST_ADS_ID, TEST_AD_GROUP_TIMES_US).withRemovedAdGroupCount(1); + + assertThat(state.getAdGroup(1).count).isEqualTo(C.LENGTH_UNSET); + state = state.withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 1); + + assertThat(state.getAdGroup(1).count).isEqualTo(1); } @Test public void setAdUriBeforeAdCount() { - state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 1, TEST_URI); - state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 2); + AdPlaybackState state = + new AdPlaybackState(TEST_ADS_ID, TEST_AD_GROUP_TIMES_US).withRemovedAdGroupCount(1); + + state = state.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 1, TEST_URI); + state = state.withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 2); - assertThat(state.adGroups[0].uris[0]).isNull(); - assertThat(state.adGroups[0].states[0]).isEqualTo(AdPlaybackState.AD_STATE_UNAVAILABLE); - assertThat(state.adGroups[0].uris[1]).isSameInstanceAs(TEST_URI); - assertThat(state.adGroups[0].states[1]).isEqualTo(AdPlaybackState.AD_STATE_AVAILABLE); + assertThat(state.getAdGroup(1).uris[0]).isNull(); + assertThat(state.getAdGroup(1).states[0]).isEqualTo(AdPlaybackState.AD_STATE_UNAVAILABLE); + assertThat(state.getAdGroup(1).uris[1]).isSameInstanceAs(TEST_URI); + assertThat(state.getAdGroup(1).states[1]).isEqualTo(AdPlaybackState.AD_STATE_AVAILABLE); } @Test public void setAdErrorBeforeAdCount() { - state = state.withAdLoadError(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0); - state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 2); + AdPlaybackState state = + new AdPlaybackState(TEST_ADS_ID, TEST_AD_GROUP_TIMES_US).withRemovedAdGroupCount(1); + + state = state.withAdLoadError(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 0); + state = state.withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 2); + + assertThat(state.getAdGroup(1).uris[0]).isNull(); + assertThat(state.getAdGroup(1).states[0]).isEqualTo(AdPlaybackState.AD_STATE_ERROR); + assertThat(state.isAdInErrorState(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 0)).isTrue(); + assertThat(state.getAdGroup(1).states[1]).isEqualTo(AdPlaybackState.AD_STATE_UNAVAILABLE); + assertThat(state.isAdInErrorState(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 1)).isFalse(); + } + + @Test + public void withAdGroupTimeUs_updatesAdGroupTimeUs() { + AdPlaybackState state = + new AdPlaybackState(TEST_ADS_ID, /* adGroupTimesUs...= */ 0, 5_000, 10_000) + .withRemovedAdGroupCount(1); + + state = + state + .withAdGroupTimeUs(/* adGroupIndex= */ 1, 3_000) + .withAdGroupTimeUs(/* adGroupIndex= */ 2, 6_000); + + assertThat(state.adGroupCount).isEqualTo(3); + assertThat(state.getAdGroup(1).timeUs).isEqualTo(3_000); + assertThat(state.getAdGroup(2).timeUs).isEqualTo(6_000); + } + + @Test + public void withNewAdGroup_addsGroupAndKeepsExistingGroups() { + AdPlaybackState state = + new AdPlaybackState(TEST_ADS_ID, /* adGroupTimesUs...= */ 0, 3_000, 6_000) + .withRemovedAdGroupCount(1) + .withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 2) + .withAdCount(/* adGroupIndex= */ 2, /* adCount= */ 1) + .withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 1, TEST_URI) + .withSkippedAd(/* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 0); + + state = + state + .withNewAdGroup(/* adGroupIndex= */ 1, /* adGroupTimeUs= */ 1_000) + .withNewAdGroup(/* adGroupIndex= */ 3, /* adGroupTimeUs= */ 5_000) + .withNewAdGroup(/* adGroupIndex= */ 5, /* adGroupTimeUs= */ 8_000); + + assertThat(state.adGroupCount).isEqualTo(6); + assertThat(state.getAdGroup(1).count).isEqualTo(C.INDEX_UNSET); + assertThat(state.getAdGroup(2).count).isEqualTo(2); + assertThat(state.getAdGroup(2).uris[1]).isSameInstanceAs(TEST_URI); + assertThat(state.getAdGroup(3).count).isEqualTo(C.INDEX_UNSET); + assertThat(state.getAdGroup(4).count).isEqualTo(1); + assertThat(state.getAdGroup(4).states[0]).isEqualTo(AdPlaybackState.AD_STATE_SKIPPED); + assertThat(state.getAdGroup(5).count).isEqualTo(C.INDEX_UNSET); + } + + @Test + public void withAdDurationsUs_updatesAdDurations() { + AdPlaybackState state = + new AdPlaybackState(TEST_ADS_ID, /* adGroupTimesUs...= */ 0, 10_000) + .withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 2) + .withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 2) + .withAdDurationsUs(new long[][] {new long[] {5_000, 6_000}, new long[] {7_000, 8_000}}); + + state = state.withAdDurationsUs(/* adGroupIndex= */ 1, /* adDurationsUs...= */ 1_000, 2_000); - assertThat(state.adGroups[0].uris[0]).isNull(); - assertThat(state.adGroups[0].states[0]).isEqualTo(AdPlaybackState.AD_STATE_ERROR); - assertThat(state.isAdInErrorState(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0)).isTrue(); - assertThat(state.adGroups[0].states[1]).isEqualTo(AdPlaybackState.AD_STATE_UNAVAILABLE); - assertThat(state.isAdInErrorState(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 1)).isFalse(); + assertThat(state.getAdGroup(0).durationsUs[0]).isEqualTo(5_000); + assertThat(state.getAdGroup(0).durationsUs[1]).isEqualTo(6_000); + assertThat(state.getAdGroup(1).durationsUs[0]).isEqualTo(1_000); + assertThat(state.getAdGroup(1).durationsUs[1]).isEqualTo(2_000); } @Test public void getFirstAdIndexToPlayIsZero() { - state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 3); - state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0, TEST_URI); - state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 2, TEST_URI); + AdPlaybackState state = + new AdPlaybackState(TEST_ADS_ID, TEST_AD_GROUP_TIMES_US).withRemovedAdGroupCount(1); + state = state.withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 3); + state = state.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 0, TEST_URI); + state = state.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 2, TEST_URI); - assertThat(state.adGroups[0].getFirstAdIndexToPlay()).isEqualTo(0); + assertThat(state.getAdGroup(1).getFirstAdIndexToPlay()).isEqualTo(0); } @Test public void getFirstAdIndexToPlaySkipsPlayedAd() { - state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 3); - state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0, TEST_URI); - state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 2, TEST_URI); + AdPlaybackState state = + new AdPlaybackState(TEST_ADS_ID, TEST_AD_GROUP_TIMES_US).withRemovedAdGroupCount(1); + state = state.withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 3); + state = state.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 0, TEST_URI); + state = state.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 2, TEST_URI); - state = state.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0); + state = state.withPlayedAd(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 0); - assertThat(state.adGroups[0].getFirstAdIndexToPlay()).isEqualTo(1); - assertThat(state.adGroups[0].states[1]).isEqualTo(AdPlaybackState.AD_STATE_UNAVAILABLE); - assertThat(state.adGroups[0].states[2]).isEqualTo(AdPlaybackState.AD_STATE_AVAILABLE); + assertThat(state.getAdGroup(1).getFirstAdIndexToPlay()).isEqualTo(1); + assertThat(state.getAdGroup(1).states[1]).isEqualTo(AdPlaybackState.AD_STATE_UNAVAILABLE); + assertThat(state.getAdGroup(1).states[2]).isEqualTo(AdPlaybackState.AD_STATE_AVAILABLE); } @Test public void getFirstAdIndexToPlaySkipsSkippedAd() { - state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 3); - state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0, TEST_URI); - state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 2, TEST_URI); + AdPlaybackState state = + new AdPlaybackState(TEST_ADS_ID, TEST_AD_GROUP_TIMES_US).withRemovedAdGroupCount(1); + state = state.withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 3); + state = state.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 0, TEST_URI); + state = state.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 2, TEST_URI); - state = state.withSkippedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0); + state = state.withSkippedAd(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 0); - assertThat(state.adGroups[0].getFirstAdIndexToPlay()).isEqualTo(1); - assertThat(state.adGroups[0].states[1]).isEqualTo(AdPlaybackState.AD_STATE_UNAVAILABLE); - assertThat(state.adGroups[0].states[2]).isEqualTo(AdPlaybackState.AD_STATE_AVAILABLE); + assertThat(state.getAdGroup(1).getFirstAdIndexToPlay()).isEqualTo(1); + assertThat(state.getAdGroup(1).states[1]).isEqualTo(AdPlaybackState.AD_STATE_UNAVAILABLE); + assertThat(state.getAdGroup(1).states[2]).isEqualTo(AdPlaybackState.AD_STATE_AVAILABLE); } @Test public void getFirstAdIndexToPlaySkipsErrorAds() { - state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 3); - state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0, TEST_URI); - state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 2, TEST_URI); + AdPlaybackState state = + new AdPlaybackState(TEST_ADS_ID, TEST_AD_GROUP_TIMES_US).withRemovedAdGroupCount(1); + state = state.withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 3); + state = state.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 0, TEST_URI); + state = state.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 2, TEST_URI); - state = state.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0); - state = state.withAdLoadError(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 1); + state = state.withPlayedAd(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 0); + state = state.withAdLoadError(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 1); - assertThat(state.adGroups[0].getFirstAdIndexToPlay()).isEqualTo(2); + assertThat(state.getAdGroup(1).getFirstAdIndexToPlay()).isEqualTo(2); } @Test public void getNextAdIndexToPlaySkipsErrorAds() { - state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 3); - state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 1, TEST_URI); + AdPlaybackState state = + new AdPlaybackState(TEST_ADS_ID, TEST_AD_GROUP_TIMES_US).withRemovedAdGroupCount(1); + state = state.withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 3); + state = state.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 1, TEST_URI); - state = state.withAdLoadError(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 1); + state = state.withAdLoadError(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 1); - assertThat(state.adGroups[0].getNextAdIndexToPlay(0)).isEqualTo(2); + assertThat(state.getAdGroup(1).getNextAdIndexToPlay(0)).isEqualTo(2); + } + + @Test + public void getFirstAdIndexToPlay_withPlayedServerSideInsertedAds_returnsFirstIndex() { + AdPlaybackState state = + new AdPlaybackState(TEST_ADS_ID, TEST_AD_GROUP_TIMES_US).withRemovedAdGroupCount(1); + state = state.withIsServerSideInserted(/* adGroupIndex= */ 1, /* isServerSideInserted= */ true); + state = state.withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 3); + state = state.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 0, TEST_URI); + state = state.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 1, TEST_URI); + state = state.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 2, TEST_URI); + + state = state.withPlayedAd(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 0); + + assertThat(state.getAdGroup(1).getFirstAdIndexToPlay()).isEqualTo(0); + } + + @Test + public void getNextAdIndexToPlay_withPlayedServerSideInsertedAds_returnsNextIndex() { + AdPlaybackState state = + new AdPlaybackState(TEST_ADS_ID, TEST_AD_GROUP_TIMES_US).withRemovedAdGroupCount(1); + state = state.withIsServerSideInserted(/* adGroupIndex= */ 1, /* isServerSideInserted= */ true); + state = state.withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 3); + state = state.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 0, TEST_URI); + state = state.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 1, TEST_URI); + state = state.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 2, TEST_URI); + + state = state.withPlayedAd(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 0); + state = state.withPlayedAd(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 1); + state = state.withPlayedAd(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 2); + + assertThat(state.getAdGroup(1).getNextAdIndexToPlay(/* lastPlayedAdIndex= */ 0)).isEqualTo(1); + assertThat(state.getAdGroup(1).getNextAdIndexToPlay(/* lastPlayedAdIndex= */ 1)).isEqualTo(2); } @Test public void setAdStateTwiceThrows() { + AdPlaybackState state = new AdPlaybackState(TEST_ADS_ID, TEST_AD_GROUP_TIMES_US); state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 1); state = state.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0); try { @@ -143,25 +247,32 @@ public void setAdStateTwiceThrows() { @Test public void skipAllWithoutAdCount() { + AdPlaybackState state = new AdPlaybackState(TEST_ADS_ID, TEST_AD_GROUP_TIMES_US); state = state.withSkippedAdGroup(0); state = state.withSkippedAdGroup(1); - assertThat(state.adGroups[0].count).isEqualTo(0); - assertThat(state.adGroups[1].count).isEqualTo(0); + assertThat(state.getAdGroup(0).count).isEqualTo(0); + assertThat(state.getAdGroup(1).count).isEqualTo(0); } @Test public void roundTripViaBundle_yieldsEqualFieldsExceptAdsId() { AdPlaybackState originalState = - state - .withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 1) - .withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0) - .withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0, TEST_URI) - .withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 2) - .withSkippedAd(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 0) - .withPlayedAd(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 1) + new AdPlaybackState(TEST_ADS_ID, TEST_AD_GROUP_TIMES_US) + .withRemovedAdGroupCount(1) + .withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 1) + .withPlayedAd(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 0) .withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 0, TEST_URI) - .withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 1, TEST_URI) - .withAdDurationsUs(new long[][] {{12}, {34, 56}}) + .withAdCount(/* adGroupIndex= */ 2, /* adCount= */ 2) + .withSkippedAd(/* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 0) + .withPlayedAd(/* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 1) + .withAdUri(/* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 0, TEST_URI) + .withAdUri(/* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 1, TEST_URI) + .withContentResumeOffsetUs(/* adGroupIndex= */ 1, /* contentResumeOffsetUs= */ 4444) + .withContentResumeOffsetUs(/* adGroupIndex= */ 2, /* contentResumeOffsetUs= */ 3333) + .withIsServerSideInserted(/* adGroupIndex= */ 1, /* isServerSideInserted= */ true) + .withIsServerSideInserted(/* adGroupIndex= */ 2, /* isServerSideInserted= */ true) + .withAdDurationsUs(/* adGroupIndex= */ 1, /* adDurationsUs...= */ 12) + .withAdDurationsUs(/* adGroupIndex= */ 2, /* adDurationsUs...= */ 34, 56) .withAdResumePositionUs(123) .withContentDurationUs(456); @@ -169,8 +280,9 @@ public void roundTripViaBundle_yieldsEqualFieldsExceptAdsId() { assertThat(restoredState.adsId).isNull(); assertThat(restoredState.adGroupCount).isEqualTo(originalState.adGroupCount); - assertThat(restoredState.adGroupTimesUs).isEqualTo(originalState.adGroupTimesUs); - assertThat(restoredState.adGroups).isEqualTo(originalState.adGroups); + for (int i = 0; i < restoredState.adGroupCount; i++) { + assertThat(restoredState.getAdGroup(i)).isEqualTo(originalState.getAdGroup(i)); + } assertThat(restoredState.adResumePositionUs).isEqualTo(originalState.adResumePositionUs); assertThat(restoredState.contentDurationUs).isEqualTo(originalState.contentDurationUs); } @@ -178,14 +290,164 @@ public void roundTripViaBundle_yieldsEqualFieldsExceptAdsId() { @Test public void roundTripViaBundle_ofAdGroup_yieldsEqualInstance() { AdPlaybackState.AdGroup adGroup = - new AdPlaybackState.AdGroup() + new AdPlaybackState.AdGroup(/* timeUs= */ 42) .withAdCount(2) .withAdState(AD_STATE_AVAILABLE, /* index= */ 0) .withAdState(AD_STATE_PLAYED, /* index= */ 1) .withAdUri(Uri.parse("https://www.google.com"), /* index= */ 0) .withAdUri(Uri.EMPTY, /* index= */ 1) - .withAdDurationsUs(new long[] {1234, 5678}); + .withAdDurationsUs(new long[] {1234, 5678}) + .withContentResumeOffsetUs(4444) + .withIsServerSideInserted(true); assertThat(AdPlaybackState.AdGroup.CREATOR.fromBundle(adGroup.toBundle())).isEqualTo(adGroup); } + + @Test + public void + getAdGroupIndexAfterPositionUs_withClientSideInsertedAds_returnsNextAdGroupWithUnplayedAds() { + AdPlaybackState state = + new AdPlaybackState( + /* adsId= */ new Object(), + /* adGroupTimesUs...= */ 0, + 1000, + 2000, + 3000, + 4000, + C.TIME_END_OF_SOURCE) + .withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 1) + .withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 1) + .withAdCount(/* adGroupIndex= */ 2, /* adCount= */ 1) + .withAdCount(/* adGroupIndex= */ 3, /* adCount= */ 1) + .withAdCount(/* adGroupIndex= */ 4, /* adCount= */ 1) + .withAdCount(/* adGroupIndex= */ 5, /* adCount= */ 1) + .withPlayedAd(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 0) + .withPlayedAd(/* adGroupIndex= */ 3, /* adIndexInAdGroup= */ 0); + + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ 0, /* periodDurationUs= */ C.TIME_UNSET)) + .isEqualTo(2); + assertThat( + state.getAdGroupIndexAfterPositionUs(/* positionUs= */ 0, /* periodDurationUs= */ 5000)) + .isEqualTo(2); + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ 1999, /* periodDurationUs= */ C.TIME_UNSET)) + .isEqualTo(2); + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ 1999, /* periodDurationUs= */ 5000)) + .isEqualTo(2); + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ 2000, /* periodDurationUs= */ C.TIME_UNSET)) + .isEqualTo(4); + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ 2000, /* periodDurationUs= */ 5000)) + .isEqualTo(4); + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ 3999, /* periodDurationUs= */ C.TIME_UNSET)) + .isEqualTo(4); + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ 3999, /* periodDurationUs= */ 5000)) + .isEqualTo(4); + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ 4000, /* periodDurationUs= */ C.TIME_UNSET)) + .isEqualTo(5); + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ 4000, /* periodDurationUs= */ 5000)) + .isEqualTo(5); + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ 4999, /* periodDurationUs= */ C.TIME_UNSET)) + .isEqualTo(5); + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ 4999, /* periodDurationUs= */ 5000)) + .isEqualTo(5); + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ 5000, /* periodDurationUs= */ C.TIME_UNSET)) + .isEqualTo(5); + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ 5000, /* periodDurationUs= */ 5000)) + .isEqualTo(C.INDEX_UNSET); + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ C.TIME_END_OF_SOURCE, /* periodDurationUs= */ C.TIME_UNSET)) + .isEqualTo(C.INDEX_UNSET); + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ C.TIME_END_OF_SOURCE, /* periodDurationUs= */ 5000)) + .isEqualTo(C.INDEX_UNSET); + } + + @Test + public void getAdGroupIndexAfterPositionUs_withServerSideInsertedAds_returnsNextAdGroup() { + AdPlaybackState state = + new AdPlaybackState(/* adsId= */ new Object(), /* adGroupTimesUs...= */ 0, 1000, 2000) + .withIsServerSideInserted(/* adGroupIndex= */ 0, /* isServerSideInserted= */ true) + .withIsServerSideInserted(/* adGroupIndex= */ 1, /* isServerSideInserted= */ true) + .withIsServerSideInserted(/* adGroupIndex= */ 2, /* isServerSideInserted= */ true) + .withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 1) + .withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 1) + .withAdCount(/* adGroupIndex= */ 2, /* adCount= */ 1) + .withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0) + .withPlayedAd(/* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 0); + + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ 0, /* periodDurationUs= */ C.TIME_UNSET)) + .isEqualTo(1); + assertThat( + state.getAdGroupIndexAfterPositionUs(/* positionUs= */ 0, /* periodDurationUs= */ 5000)) + .isEqualTo(1); + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ 999, /* periodDurationUs= */ C.TIME_UNSET)) + .isEqualTo(1); + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ 999, /* periodDurationUs= */ 5000)) + .isEqualTo(1); + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ 1000, /* periodDurationUs= */ C.TIME_UNSET)) + .isEqualTo(2); + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ 1000, /* periodDurationUs= */ 5000)) + .isEqualTo(2); + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ 1999, /* periodDurationUs= */ C.TIME_UNSET)) + .isEqualTo(2); + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ 1999, /* periodDurationUs= */ 5000)) + .isEqualTo(2); + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ 2000, /* periodDurationUs= */ C.TIME_UNSET)) + .isEqualTo(C.INDEX_UNSET); + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ 2000, /* periodDurationUs= */ 5000)) + .isEqualTo(C.INDEX_UNSET); + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ C.TIME_END_OF_SOURCE, /* periodDurationUs= */ C.TIME_UNSET)) + .isEqualTo(C.INDEX_UNSET); + assertThat( + state.getAdGroupIndexAfterPositionUs( + /* positionUs= */ C.TIME_END_OF_SOURCE, /* periodDurationUs= */ 5000)) + .isEqualTo(C.INDEX_UNSET); + } } diff --git a/library/common/src/test/java/com/google/android/exoplayer2/trackselection/TrackSelectionParametersTest.java b/library/common/src/test/java/com/google/android/exoplayer2/trackselection/TrackSelectionParametersTest.java new file mode 100644 index 00000000000..69743bb609c --- /dev/null +++ b/library/common/src/test/java/com/google/android/exoplayer2/trackselection/TrackSelectionParametersTest.java @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.exoplayer2.trackselection; + +import static androidx.test.core.app.ApplicationProvider.getApplicationContext; +import static com.google.common.truth.Truth.assertThat; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.util.MimeTypes; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** Tests for {@link TrackSelectionParameters}. */ +@RunWith(AndroidJUnit4.class) +public class TrackSelectionParametersTest { + + @Test + public void defaultValue_withoutChange_isAsExpected() { + TrackSelectionParameters parameters = TrackSelectionParameters.DEFAULT_WITHOUT_CONTEXT; + + // Video + assertThat(parameters.maxVideoWidth).isEqualTo(Integer.MAX_VALUE); + assertThat(parameters.maxVideoHeight).isEqualTo(Integer.MAX_VALUE); + assertThat(parameters.maxVideoFrameRate).isEqualTo(Integer.MAX_VALUE); + assertThat(parameters.maxVideoBitrate).isEqualTo(Integer.MAX_VALUE); + assertThat(parameters.minVideoWidth).isEqualTo(0); + assertThat(parameters.minVideoHeight).isEqualTo(0); + assertThat(parameters.minVideoFrameRate).isEqualTo(0); + assertThat(parameters.minVideoBitrate).isEqualTo(0); + assertThat(parameters.viewportWidth).isEqualTo(Integer.MAX_VALUE); + assertThat(parameters.viewportHeight).isEqualTo(Integer.MAX_VALUE); + assertThat(parameters.viewportOrientationMayChange).isTrue(); + assertThat(parameters.preferredVideoMimeTypes).isEmpty(); + // Audio + assertThat(parameters.preferredAudioLanguages).isEmpty(); + assertThat(parameters.preferredAudioRoleFlags).isEqualTo(0); + assertThat(parameters.maxAudioChannelCount).isEqualTo(Integer.MAX_VALUE); + assertThat(parameters.maxAudioBitrate).isEqualTo(Integer.MAX_VALUE); + // Text + assertThat(parameters.preferredAudioMimeTypes).isEmpty(); + assertThat(parameters.preferredTextLanguages).isEmpty(); + assertThat(parameters.preferredTextRoleFlags).isEqualTo(0); + assertThat(parameters.selectUndeterminedTextLanguage).isFalse(); + // General + assertThat(parameters.forceLowestBitrate).isFalse(); + assertThat(parameters.forceHighestSupportedBitrate).isFalse(); + } + + @Test + public void parametersSet_fromDefault_isAsExpected() { + TrackSelectionParameters parameters = + TrackSelectionParameters.DEFAULT_WITHOUT_CONTEXT + .buildUpon() + // Video + .setMaxVideoSize(/* maxVideoWidth= */ 0, /* maxVideoHeight= */ 1) + .setMaxVideoFrameRate(2) + .setMaxVideoBitrate(3) + .setMinVideoSize(/* minVideoWidth= */ 4, /* minVideoHeight= */ 5) + .setMinVideoFrameRate(6) + .setMinVideoBitrate(7) + .setViewportSize( + /* viewportWidth= */ 8, + /* viewportHeight= */ 9, + /* viewportOrientationMayChange= */ true) + .setPreferredVideoMimeTypes(MimeTypes.VIDEO_AV1, MimeTypes.VIDEO_H264) + // Audio + .setPreferredAudioLanguages("zh", "jp") + .setPreferredAudioRoleFlags(C.ROLE_FLAG_COMMENTARY) + .setMaxAudioChannelCount(10) + .setMaxAudioBitrate(11) + .setPreferredAudioMimeTypes(MimeTypes.AUDIO_AC3, MimeTypes.AUDIO_E_AC3) + // Text + .setPreferredTextLanguages("de", "en") + .setPreferredTextRoleFlags(C.ROLE_FLAG_CAPTION) + .setSelectUndeterminedTextLanguage(true) + // General + .setForceLowestBitrate(false) + .setForceHighestSupportedBitrate(true) + .build(); + + // Video + assertThat(parameters.maxVideoWidth).isEqualTo(0); + assertThat(parameters.maxVideoHeight).isEqualTo(1); + assertThat(parameters.maxVideoFrameRate).isEqualTo(2); + assertThat(parameters.maxVideoBitrate).isEqualTo(3); + assertThat(parameters.minVideoWidth).isEqualTo(4); + assertThat(parameters.minVideoHeight).isEqualTo(5); + assertThat(parameters.minVideoFrameRate).isEqualTo(6); + assertThat(parameters.minVideoBitrate).isEqualTo(7); + assertThat(parameters.viewportWidth).isEqualTo(8); + assertThat(parameters.viewportHeight).isEqualTo(9); + assertThat(parameters.viewportOrientationMayChange).isTrue(); + assertThat(parameters.preferredVideoMimeTypes) + .containsExactly(MimeTypes.VIDEO_AV1, MimeTypes.VIDEO_H264) + .inOrder(); + // Audio + assertThat(parameters.preferredAudioLanguages).containsExactly("zh", "jp").inOrder(); + assertThat(parameters.preferredAudioRoleFlags).isEqualTo(C.ROLE_FLAG_COMMENTARY); + assertThat(parameters.maxAudioChannelCount).isEqualTo(10); + assertThat(parameters.maxAudioBitrate).isEqualTo(11); + assertThat(parameters.preferredAudioMimeTypes) + .containsExactly(MimeTypes.AUDIO_AC3, MimeTypes.AUDIO_E_AC3) + .inOrder(); + // Text + assertThat(parameters.preferredTextLanguages).containsExactly("de", "en").inOrder(); + assertThat(parameters.preferredTextRoleFlags).isEqualTo(C.ROLE_FLAG_CAPTION); + assertThat(parameters.selectUndeterminedTextLanguage).isTrue(); + // General + assertThat(parameters.forceLowestBitrate).isFalse(); + assertThat(parameters.forceHighestSupportedBitrate).isTrue(); + } + + @Test + public void setMaxVideoSizeSd_defaultBuilder_parametersVideoSizeAreSd() { + TrackSelectionParameters parameters = + new TrackSelectionParameters.Builder(getApplicationContext()).setMaxVideoSizeSd().build(); + + assertThat(parameters.maxVideoWidth).isEqualTo(1279); + assertThat(parameters.maxVideoHeight).isEqualTo(719); + } + + @Test + public void clearVideoSizeConstraints_withSdConstrains_clearConstrains() { + TrackSelectionParameters parameters = + new TrackSelectionParameters.Builder(getApplicationContext()) + .setMaxVideoSizeSd() + .clearVideoSizeConstraints() + .build(); + + assertThat(parameters.maxVideoWidth).isEqualTo(Integer.MAX_VALUE); + assertThat(parameters.maxVideoHeight).isEqualTo(Integer.MAX_VALUE); + } + + @Test + public void clearViewPortConstraints_withConstrains_clearConstrains() { + TrackSelectionParameters parameters = + new TrackSelectionParameters.Builder(getApplicationContext()) + .setViewportSize( + /*viewportWidth=*/ 1, + /*viewportHeight=*/ 2, + /*viewportOrientationMayChange=*/ false) + .clearViewportSizeConstraints() + .build(); + + assertThat(parameters.viewportWidth).isEqualTo(Integer.MAX_VALUE); + assertThat(parameters.viewportHeight).isEqualTo(Integer.MAX_VALUE); + assertThat(parameters.viewportOrientationMayChange).isTrue(); + } +} diff --git a/library/common/src/test/java/com/google/android/exoplayer2/upstream/BaseDataSourceTest.java b/library/common/src/test/java/com/google/android/exoplayer2/upstream/BaseDataSourceTest.java index 1eb49188bfd..ae3219f3f2f 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/upstream/BaseDataSourceTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/upstream/BaseDataSourceTest.java @@ -101,9 +101,9 @@ public long open(DataSpec dataSpec) throws IOException { } @Override - public int read(byte[] buffer, int offset, int readLength) throws IOException { - bytesTransferred(readLength); - return readLength; + public int read(byte[] buffer, int offset, int length) throws IOException { + bytesTransferred(length); + return length; } @Override diff --git a/library/common/src/test/java/com/google/android/exoplayer2/upstream/DataSourceExceptionTest.java b/library/common/src/test/java/com/google/android/exoplayer2/upstream/DataSourceExceptionTest.java index 59a4939a68e..432333f09f6 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/upstream/DataSourceExceptionTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/upstream/DataSourceExceptionTest.java @@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assertThat; import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.PlaybackException; import java.io.IOException; import org.junit.Test; import org.junit.runner.RunWith; @@ -26,30 +27,31 @@ @RunWith(AndroidJUnit4.class) public class DataSourceExceptionTest { - private static final int REASON_OTHER = DataSourceException.POSITION_OUT_OF_RANGE - 1; - @Test public void isCausedByPositionOutOfRange_reasonIsPositionOutOfRange_returnsTrue() { - DataSourceException e = new DataSourceException(DataSourceException.POSITION_OUT_OF_RANGE); + DataSourceException e = + new DataSourceException(PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE); assertThat(DataSourceException.isCausedByPositionOutOfRange(e)).isTrue(); } @Test public void isCausedByPositionOutOfRange_reasonIsOther_returnsFalse() { - DataSourceException e = new DataSourceException(REASON_OTHER); + DataSourceException e = new DataSourceException(PlaybackException.ERROR_CODE_IO_UNSPECIFIED); assertThat(DataSourceException.isCausedByPositionOutOfRange(e)).isFalse(); } @Test - public void isCausedByPositionOutOfRange_indirectauseReasonIsPositionOutOfRange_returnsTrue() { - DataSourceException cause = new DataSourceException(DataSourceException.POSITION_OUT_OF_RANGE); + public void isCausedByPositionOutOfRange_indirectCauseReasonIsPositionOutOfRange_returnsTrue() { + DataSourceException cause = + new DataSourceException(PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE); IOException e = new IOException(new IOException(cause)); assertThat(DataSourceException.isCausedByPositionOutOfRange(e)).isTrue(); } @Test public void isCausedByPositionOutOfRange_causeReasonIsOther_returnsFalse() { - DataSourceException cause = new DataSourceException(REASON_OTHER); + DataSourceException cause = + new DataSourceException(PlaybackException.ERROR_CODE_IO_UNSPECIFIED); IOException e = new IOException(new IOException(cause)); assertThat(DataSourceException.isCausedByPositionOutOfRange(e)).isFalse(); } diff --git a/library/common/src/test/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSourceTest.java b/library/common/src/test/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSourceTest.java index f84b4489774..712d17df3b6 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSourceTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSourceTest.java @@ -22,11 +22,14 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.testutil.TestUtil; +import com.google.android.exoplayer2.upstream.HttpDataSource.HttpDataSourceException; +import java.net.HttpURLConnection; import java.util.HashMap; import java.util.Map; import okhttp3.Headers; import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockWebServer; +import okhttp3.mockwebserver.RecordedRequest; import okio.Buffer; import org.junit.Test; import org.junit.runner.RunWith; @@ -126,6 +129,86 @@ public void open_invalidResponseCode() { assertThat(exception.responseBody).isEqualTo(TestUtil.createByteArray(1, 2, 3)); } + @Test + public void open_redirectChanges302PostToGet() + throws HttpDataSourceException, InterruptedException { + byte[] postBody = new byte[] {1, 2, 3}; + DefaultHttpDataSource defaultHttpDataSource = + new DefaultHttpDataSource.Factory() + .setConnectTimeoutMs(1000) + .setReadTimeoutMs(1000) + .setKeepPostFor302Redirects(false) + .setAllowCrossProtocolRedirects(true) + .createDataSource(); + + MockWebServer mockWebServer = new MockWebServer(); + String newLocationUrl = mockWebServer.url("/redirect-path").toString(); + mockWebServer.enqueue( + new MockResponse() + .setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP) + .addHeader("Location", newLocationUrl)); + mockWebServer.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_OK)); + + DataSpec dataSpec = + new DataSpec.Builder() + .setUri(mockWebServer.url("/test-path").toString()) + .setHttpMethod(DataSpec.HTTP_METHOD_POST) + .setHttpBody(postBody) + .build(); + + defaultHttpDataSource.open(dataSpec); + + RecordedRequest request1 = mockWebServer.takeRequest(10, SECONDS); + assertThat(request1).isNotNull(); + assertThat(request1.getPath()).isEqualTo("/test-path"); + assertThat(request1.getMethod()).isEqualTo("POST"); + assertThat(request1.getBodySize()).isEqualTo(postBody.length); + RecordedRequest request2 = mockWebServer.takeRequest(10, SECONDS); + assertThat(request2).isNotNull(); + assertThat(request2.getPath()).isEqualTo("/redirect-path"); + assertThat(request2.getMethod()).isEqualTo("GET"); + assertThat(request2.getBodySize()).isEqualTo(0); + } + + @Test + public void open_redirectKeeps302Post() throws HttpDataSourceException, InterruptedException { + byte[] postBody = new byte[] {1, 2, 3}; + DefaultHttpDataSource defaultHttpDataSource = + new DefaultHttpDataSource.Factory() + .setConnectTimeoutMs(1000) + .setReadTimeoutMs(1000) + .setKeepPostFor302Redirects(true) + .createDataSource(); + + MockWebServer mockWebServer = new MockWebServer(); + String newLocationUrl = mockWebServer.url("/redirect-path").toString(); + mockWebServer.enqueue( + new MockResponse() + .setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP) + .addHeader("Location", newLocationUrl)); + mockWebServer.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_OK)); + + DataSpec dataSpec = + new DataSpec.Builder() + .setUri(mockWebServer.url("/test-path").toString()) + .setHttpMethod(DataSpec.HTTP_METHOD_POST) + .setHttpBody(postBody) + .build(); + + defaultHttpDataSource.open(dataSpec); + + RecordedRequest request1 = mockWebServer.takeRequest(10, SECONDS); + assertThat(request1).isNotNull(); + assertThat(request1.getPath()).isEqualTo("/test-path"); + assertThat(request1.getMethod()).isEqualTo("POST"); + assertThat(request1.getBodySize()).isEqualTo(postBody.length); + RecordedRequest request2 = mockWebServer.takeRequest(10, SECONDS); + assertThat(request2).isNotNull(); + assertThat(request2.getPath()).isEqualTo("/redirect-path"); + assertThat(request2.getMethod()).isEqualTo("POST"); + assertThat(request2.getBodySize()).isEqualTo(postBody.length); + } + @Test public void factory_setRequestPropertyAfterCreation_setsCorrectHeaders() throws Exception { MockWebServer mockWebServer = new MockWebServer(); diff --git a/library/common/src/test/java/com/google/android/exoplayer2/util/ExoFlagsTest.java b/library/common/src/test/java/com/google/android/exoplayer2/util/FlagSetTest.java similarity index 87% rename from library/common/src/test/java/com/google/android/exoplayer2/util/ExoFlagsTest.java rename to library/common/src/test/java/com/google/android/exoplayer2/util/FlagSetTest.java index 0cc71a2881b..91ea26b8466 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/util/ExoFlagsTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/util/FlagSetTest.java @@ -24,13 +24,13 @@ import org.junit.Test; import org.junit.runner.RunWith; -/** Unit test for {@link ExoFlags}. */ +/** Unit test for {@link FlagSet}. */ @RunWith(AndroidJUnit4.class) -public final class ExoFlagsTest { +public final class FlagSetTest { @Test public void contains_withoutAdd_returnsFalseForAllValues() { - ExoFlags flags = new ExoFlags.Builder().build(); + FlagSet flags = new FlagSet.Builder().build(); assertThat(flags.contains(/* flag= */ -1234)).isFalse(); assertThat(flags.contains(/* flag= */ 0)).isFalse(); @@ -40,8 +40,8 @@ public void contains_withoutAdd_returnsFalseForAllValues() { @Test public void contains_afterAdd_returnsTrueForAddedValues() { - ExoFlags flags = - new ExoFlags.Builder() + FlagSet flags = + new FlagSet.Builder() .add(/* flag= */ -1234) .add(/* flag= */ 0) .add(/* flag= */ 2) @@ -59,8 +59,8 @@ public void contains_afterAdd_returnsTrueForAddedValues() { @Test public void contains_afterAddIf_returnsTrueForAddedValues() { - ExoFlags flags = - new ExoFlags.Builder() + FlagSet flags = + new FlagSet.Builder() .addIf(/* flag= */ -1234, /* condition= */ true) .addIf(/* flag= */ 0, /* condition= */ false) .addIf(/* flag= */ 2, /* condition= */ true) @@ -78,15 +78,15 @@ public void contains_afterAddIf_returnsTrueForAddedValues() { @Test public void containsAny_withoutAdd_returnsFalseForAllValues() { - ExoFlags flags = new ExoFlags.Builder().build(); + FlagSet flags = new FlagSet.Builder().build(); assertThat(flags.containsAny(/* flags...= */ -1234, 0, 2, Integer.MAX_VALUE)).isFalse(); } @Test public void containsAny_afterAdd_returnsTrueForAddedValues() { - ExoFlags flags = - new ExoFlags.Builder() + FlagSet flags = + new FlagSet.Builder() .add(/* flag= */ -1234) .add(/* flag= */ 0) .add(/* flag= */ 2) @@ -102,15 +102,15 @@ public void containsAny_afterAdd_returnsTrueForAddedValues() { @Test public void size_withoutAdd_returnsZero() { - ExoFlags flags = new ExoFlags.Builder().build(); + FlagSet flags = new FlagSet.Builder().build(); assertThat(flags.size()).isEqualTo(0); } @Test public void size_afterAdd_returnsNumberUniqueOfElements() { - ExoFlags flags = - new ExoFlags.Builder() + FlagSet flags = + new FlagSet.Builder() .add(/* flag= */ 0) .add(/* flag= */ 0) .add(/* flag= */ 0) @@ -123,22 +123,22 @@ public void size_afterAdd_returnsNumberUniqueOfElements() { @Test public void get_withNegativeIndex_throwsIndexOutOfBoundsException() { - ExoFlags flags = new ExoFlags.Builder().build(); + FlagSet flags = new FlagSet.Builder().build(); assertThrows(IndexOutOfBoundsException.class, () -> flags.get(/* index= */ -1)); } @Test public void get_withIndexExceedingSize_throwsIndexOutOfBoundsException() { - ExoFlags flags = new ExoFlags.Builder().add(/* flag= */ 0).add(/* flag= */ 123).build(); + FlagSet flags = new FlagSet.Builder().add(/* flag= */ 0).add(/* flag= */ 123).build(); assertThrows(IndexOutOfBoundsException.class, () -> flags.get(/* index= */ 2)); } @Test public void get_afterAdd_returnsAllUniqueValues() { - ExoFlags flags = - new ExoFlags.Builder() + FlagSet flags = + new FlagSet.Builder() .add(/* flag= */ 0) .add(/* flag= */ 0) .add(/* flag= */ 0) diff --git a/library/common/src/test/java/com/google/android/exoplayer2/util/ListenerSetTest.java b/library/common/src/test/java/com/google/android/exoplayer2/util/ListenerSetTest.java index f8e60619989..d350e99c32a 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/util/ListenerSetTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/util/ListenerSetTest.java @@ -22,7 +22,6 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; -import android.os.Handler; import android.os.Looper; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.C; @@ -148,22 +147,22 @@ public void callback3() { InOrder inOrder = Mockito.inOrder(listener1, listener2); inOrder.verify(listener1).callback2(); inOrder.verify(listener2).callback2(); - inOrder.verify(listener1).iterationFinished(createExoFlags(EVENT_ID_2)); - inOrder.verify(listener2).iterationFinished(createExoFlags(EVENT_ID_2)); + inOrder.verify(listener1).iterationFinished(createFlagSet(EVENT_ID_2)); + inOrder.verify(listener2).iterationFinished(createFlagSet(EVENT_ID_2)); inOrder.verify(listener1).callback1(); inOrder.verify(listener2).callback1(); inOrder.verify(listener1).callback2(); inOrder.verify(listener2).callback2(); inOrder.verify(listener1).callback1(); inOrder.verify(listener2).callback1(); - inOrder.verify(listener1).iterationFinished(createExoFlags(EVENT_ID_1, EVENT_ID_2)); - inOrder.verify(listener2).iterationFinished(createExoFlags(EVENT_ID_1, EVENT_ID_2)); + inOrder.verify(listener1).iterationFinished(createFlagSet(EVENT_ID_1, EVENT_ID_2)); + inOrder.verify(listener2).iterationFinished(createFlagSet(EVENT_ID_1, EVENT_ID_2)); inOrder.verify(listener1).callback3(); inOrder.verify(listener2).callback3(); inOrder.verify(listener1).callback1(); inOrder.verify(listener2).callback1(); - inOrder.verify(listener1).iterationFinished(createExoFlags(EVENT_ID_1, EVENT_ID_3)); - inOrder.verify(listener2).iterationFinished(createExoFlags(EVENT_ID_1, EVENT_ID_3)); + inOrder.verify(listener1).iterationFinished(createFlagSet(EVENT_ID_1, EVENT_ID_3)); + inOrder.verify(listener2).iterationFinished(createFlagSet(EVENT_ID_1, EVENT_ID_3)); inOrder.verifyNoMoreInteractions(); } @@ -178,7 +177,7 @@ public void flushEvents_calledFromIterationFinishedCallback_restartsIterationFin boolean eventSent; @Override - public void iterationFinished(ExoFlags flags) { + public void iterationFinished(FlagSet flags) { if (!eventSent) { listenerSet.sendEvent(EVENT_ID_1, TestListener::callback1); eventSent = true; @@ -198,14 +197,14 @@ public void iterationFinished(ExoFlags flags) { inOrder.verify(listener1).callback2(); inOrder.verify(listener2).callback2(); inOrder.verify(listener3).callback2(); - inOrder.verify(listener1).iterationFinished(createExoFlags(EVENT_ID_2)); - inOrder.verify(listener2).iterationFinished(createExoFlags(EVENT_ID_2)); + inOrder.verify(listener1).iterationFinished(createFlagSet(EVENT_ID_2)); + inOrder.verify(listener2).iterationFinished(createFlagSet(EVENT_ID_2)); inOrder.verify(listener1).callback1(); inOrder.verify(listener2).callback1(); inOrder.verify(listener3).callback1(); - inOrder.verify(listener1).iterationFinished(createExoFlags(EVENT_ID_1)); - inOrder.verify(listener2).iterationFinished(createExoFlags(EVENT_ID_1)); - inOrder.verify(listener3).iterationFinished(createExoFlags(EVENT_ID_1, EVENT_ID_2)); + inOrder.verify(listener1).iterationFinished(createFlagSet(EVENT_ID_1)); + inOrder.verify(listener2).iterationFinished(createFlagSet(EVENT_ID_1)); + inOrder.verify(listener3).iterationFinished(createFlagSet(EVENT_ID_1, EVENT_ID_2)); inOrder.verifyNoMoreInteractions(); } @@ -248,8 +247,8 @@ public void callback1() { inOrder.verify(listener1).callback1(); inOrder.verify(listener1).callback2(); inOrder.verify(listener2).callback2(); - inOrder.verify(listener1).iterationFinished(createExoFlags(EVENT_ID_1, EVENT_ID_2)); - inOrder.verify(listener2).iterationFinished(createExoFlags(EVENT_ID_2)); + inOrder.verify(listener1).iterationFinished(createFlagSet(EVENT_ID_1, EVENT_ID_2)); + inOrder.verify(listener2).iterationFinished(createFlagSet(EVENT_ID_2)); inOrder.verifyNoMoreInteractions(); } @@ -273,8 +272,8 @@ public void add_withQueueing_onlyReceivesUpdatesForFutureEvents() { inOrder.verify(listener1).callback1(); inOrder.verify(listener1).callback2(); inOrder.verify(listener2).callback2(); - inOrder.verify(listener1).iterationFinished(createExoFlags(EVENT_ID_1, EVENT_ID_2)); - inOrder.verify(listener2).iterationFinished(createExoFlags(EVENT_ID_2)); + inOrder.verify(listener1).iterationFinished(createFlagSet(EVENT_ID_1, EVENT_ID_2)); + inOrder.verify(listener2).iterationFinished(createFlagSet(EVENT_ID_2)); inOrder.verifyNoMoreInteractions(); } @@ -302,7 +301,7 @@ public void callback1() { ShadowLooper.runMainLooperToNextTask(); verify(listener1).callback1(); - verify(listener1).iterationFinished(createExoFlags(EVENT_ID_1)); + verify(listener1).iterationFinished(createFlagSet(EVENT_ID_1)); verifyNoMoreInteractions(listener1, listener2); } @@ -323,7 +322,7 @@ public void remove_withQueueing_stopsReceivingEventsImmediately() { ShadowLooper.runMainLooperToNextTask(); verify(listener2, times(2)).callback1(); - verify(listener2).iterationFinished(createExoFlags(EVENT_ID_1)); + verify(listener2).iterationFinished(createFlagSet(EVENT_ID_1)); verifyNoMoreInteractions(listener1, listener2); } @@ -350,7 +349,7 @@ public void callback1() { ShadowLooper.runMainLooperToNextTask(); verify(listener1).callback1(); - verify(listener1).iterationFinished(createExoFlags(EVENT_ID_1)); + verify(listener1).iterationFinished(createFlagSet(EVENT_ID_1)); verifyNoMoreInteractions(listener1, listener2); } @@ -367,34 +366,6 @@ public void release_preventsRegisteringNewListeners() { verify(listener, never()).callback1(); } - @Test - public void lazyRelease_stopsForwardingEventsFromNewHandlerMessagesAndCallsReleaseCallback() { - ListenerSet listenerSet = - new ListenerSet<>(Looper.myLooper(), Clock.DEFAULT, TestListener::iterationFinished); - TestListener listener = mock(TestListener.class); - listenerSet.add(listener); - - // In-line event before release. - listenerSet.sendEvent(EVENT_ID_1, TestListener::callback1); - // Message triggering event sent before release. - new Handler().post(() -> listenerSet.sendEvent(EVENT_ID_1, TestListener::callback1)); - // Lazy release with release callback. - listenerSet.lazyRelease(EVENT_ID_3, TestListener::callback3); - // In-line event after release. - listenerSet.sendEvent(EVENT_ID_1, TestListener::callback1); - // Message triggering event sent after release. - new Handler().post(() -> listenerSet.sendEvent(EVENT_ID_2, TestListener::callback2)); - ShadowLooper.runMainLooperToNextTask(); - - // Verify all events are delivered except for the one triggered by the message sent after the - // lazy release. - verify(listener, times(3)).callback1(); - verify(listener).callback3(); - verify(listener).iterationFinished(createExoFlags(EVENT_ID_1)); - verify(listener).iterationFinished(createExoFlags(EVENT_ID_1, EVENT_ID_3)); - verifyNoMoreInteractions(listener); - } - private interface TestListener { default void callback1() {} @@ -402,11 +373,11 @@ default void callback2() {} default void callback3() {} - default void iterationFinished(ExoFlags flags) {} + default void iterationFinished(FlagSet flags) {} } - private static ExoFlags createExoFlags(int... flagValues) { - ExoFlags.Builder flagsBuilder = new ExoFlags.Builder(); + private static FlagSet createFlagSet(int... flagValues) { + FlagSet.Builder flagsBuilder = new FlagSet.Builder(); for (int value : flagValues) { flagsBuilder.add(value); } diff --git a/library/common/src/test/java/com/google/android/exoplayer2/util/MediaFormatUtilTest.java b/library/common/src/test/java/com/google/android/exoplayer2/util/MediaFormatUtilTest.java index 0d41e214963..08887964179 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/util/MediaFormatUtilTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/util/MediaFormatUtilTest.java @@ -25,11 +25,9 @@ import com.google.common.collect.ImmutableList; import org.junit.Test; import org.junit.runner.RunWith; -import org.robolectric.annotation.Config; /** Unit tests for {@link MediaFormatUtil}. */ @RunWith(AndroidJUnit4.class) -@Config(sdk = 29) // Allows using MediaFormat.getKeys() to make assertions over the expected keys. public class MediaFormatUtilTest { @Test diff --git a/library/common/src/test/java/com/google/android/exoplayer2/util/MimeTypesTest.java b/library/common/src/test/java/com/google/android/exoplayer2/util/MimeTypesTest.java index 2baac87e858..490a68d0ab4 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/util/MimeTypesTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/util/MimeTypesTest.java @@ -137,9 +137,10 @@ public void getMediaMimeType_fromValidCodecs_returnsCorrectMimeType() { assertThat(MimeTypes.getMediaMimeType("ec-3")).isEqualTo(MimeTypes.AUDIO_E_AC3); assertThat(MimeTypes.getMediaMimeType("ec+3")).isEqualTo(MimeTypes.AUDIO_E_AC3_JOC); assertThat(MimeTypes.getMediaMimeType("dtsc")).isEqualTo(MimeTypes.AUDIO_DTS); - assertThat(MimeTypes.getMediaMimeType("dtse")).isEqualTo(MimeTypes.AUDIO_DTS); + assertThat(MimeTypes.getMediaMimeType("dtse")).isEqualTo(MimeTypes.AUDIO_DTS_EXPRESS); assertThat(MimeTypes.getMediaMimeType("dtsh")).isEqualTo(MimeTypes.AUDIO_DTS_HD); assertThat(MimeTypes.getMediaMimeType("dtsl")).isEqualTo(MimeTypes.AUDIO_DTS_HD); + assertThat(MimeTypes.getMediaMimeType("dtsx")).isEqualTo(MimeTypes.AUDIO_DTS_UHD); assertThat(MimeTypes.getMediaMimeType("opus")).isEqualTo(MimeTypes.AUDIO_OPUS); assertThat(MimeTypes.getMediaMimeType("vorbis")).isEqualTo(MimeTypes.AUDIO_VORBIS); assertThat(MimeTypes.getMediaMimeType("mp4a")).isEqualTo(MimeTypes.AUDIO_AAC); diff --git a/library/common/src/test/java/com/google/android/exoplayer2/util/NalUnitUtilTest.java b/library/common/src/test/java/com/google/android/exoplayer2/util/NalUnitUtilTest.java index fe081a99db8..4d9fc89a031 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/util/NalUnitUtilTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/util/NalUnitUtilTest.java @@ -29,9 +29,10 @@ public final class NalUnitUtilTest { private static final int TEST_PARTIAL_NAL_POSITION = 4; private static final int TEST_NAL_POSITION = 10; - private static final byte[] SPS_TEST_DATA = createByteArray(0x00, 0x00, 0x01, 0x67, 0x4D, 0x40, - 0x16, 0xEC, 0xA0, 0x50, 0x17, 0xFC, 0xB8, 0x08, 0x80, 0x00, 0x00, 0x03, 0x00, 0x80, 0x00, - 0x00, 0x0F, 0x47, 0x8B, 0x16, 0xCB); + private static final byte[] SPS_TEST_DATA = + createByteArray( + 0x00, 0x00, 0x01, 0x67, 0x4D, 0x40, 0x16, 0xEC, 0xA0, 0x50, 0x17, 0xFC, 0xB8, 0x08, 0x80, + 0x00, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 0x0F, 0x47, 0x8B, 0x16, 0xCB); private static final int SPS_TEST_DATA_OFFSET = 3; @Test @@ -121,8 +122,8 @@ public void findNalUnitWithPrefix() { @Test public void parseSpsNalUnit() { - NalUnitUtil.SpsData data = NalUnitUtil.parseSpsNalUnit(SPS_TEST_DATA, SPS_TEST_DATA_OFFSET, - SPS_TEST_DATA.length); + NalUnitUtil.SpsData data = + NalUnitUtil.parseSpsNalUnit(SPS_TEST_DATA, SPS_TEST_DATA_OFFSET, SPS_TEST_DATA.length); assertThat(data.width).isEqualTo(640); assertThat(data.height).isEqualTo(360); assertThat(data.deltaPicOrderAlwaysZeroFlag).isFalse(); diff --git a/library/common/src/test/java/com/google/android/exoplayer2/util/ParsableByteArrayTest.java b/library/common/src/test/java/com/google/android/exoplayer2/util/ParsableByteArrayTest.java index 444e5f7b469..fbf0368c9f8 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/util/ParsableByteArrayTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/util/ParsableByteArrayTest.java @@ -79,8 +79,8 @@ public void readShort() { } private static void testReadShort(short testValue) { - ParsableByteArray testArray = new ParsableByteArray( - ByteBuffer.allocate(4).putShort(testValue).array()); + ParsableByteArray testArray = + new ParsableByteArray(ByteBuffer.allocate(4).putShort(testValue).array()); int readValue = testArray.readShort(); // Assert that the value we read was the value we wrote. @@ -105,8 +105,8 @@ public void readInt() { } private static void testReadInt(int testValue) { - ParsableByteArray testArray = new ParsableByteArray( - ByteBuffer.allocate(4).putInt(testValue).array()); + ParsableByteArray testArray = + new ParsableByteArray(ByteBuffer.allocate(4).putInt(testValue).array()); int readValue = testArray.readInt(); // Assert that the value we read was the value we wrote. @@ -131,8 +131,9 @@ public void readUnsignedInt() { } private static void testReadUnsignedInt(long testValue) { - ParsableByteArray testArray = new ParsableByteArray( - Arrays.copyOfRange(ByteBuffer.allocate(8).putLong(testValue).array(), 4, 8)); + ParsableByteArray testArray = + new ParsableByteArray( + Arrays.copyOfRange(ByteBuffer.allocate(8).putLong(testValue).array(), 4, 8)); long readValue = testArray.readUnsignedInt(); // Assert that the value we read was the value we wrote. @@ -167,8 +168,8 @@ public void readUnsignedIntToInt() { } private static void testReadUnsignedIntToInt(int testValue) { - ParsableByteArray testArray = new ParsableByteArray( - ByteBuffer.allocate(4).putInt(testValue).array()); + ParsableByteArray testArray = + new ParsableByteArray(ByteBuffer.allocate(4).putInt(testValue).array()); int readValue = testArray.readUnsignedIntToInt(); // Assert that the value we read was the value we wrote. @@ -203,8 +204,8 @@ public void readUnsignedLongToLong() { } private static void testReadUnsignedLongToLong(long testValue) { - ParsableByteArray testArray = new ParsableByteArray( - ByteBuffer.allocate(8).putLong(testValue).array()); + ParsableByteArray testArray = + new ParsableByteArray(ByteBuffer.allocate(8).putLong(testValue).array()); long readValue = testArray.readUnsignedLongToLong(); // Assert that the value we read was the value we wrote. @@ -229,8 +230,8 @@ public void readLong() { } private static void testReadLong(long testValue) { - ParsableByteArray testArray = new ParsableByteArray( - ByteBuffer.allocate(8).putLong(testValue).array()); + ParsableByteArray testArray = + new ParsableByteArray(ByteBuffer.allocate(8).putLong(testValue).array()); long readValue = testArray.readLong(); // Assert that the value we read was the value we wrote. @@ -327,28 +328,22 @@ public void readingBytesReturnsCopy() { @Test public void readLittleEndianLong() { - ParsableByteArray byteArray = new ParsableByteArray(new byte[] { - 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, (byte) 0xFF - }); + ParsableByteArray byteArray = + new ParsableByteArray(new byte[] {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0xFF}); assertThat(byteArray.readLittleEndianLong()).isEqualTo(0xFF00000000000001L); assertThat(byteArray.getPosition()).isEqualTo(8); } @Test public void readLittleEndianUnsignedInt() { - ParsableByteArray byteArray = new ParsableByteArray(new byte[] { - 0x10, 0x00, 0x00, (byte) 0xFF - }); + ParsableByteArray byteArray = new ParsableByteArray(new byte[] {0x10, 0x00, 0x00, (byte) 0xFF}); assertThat(byteArray.readLittleEndianUnsignedInt()).isEqualTo(0xFF000010L); assertThat(byteArray.getPosition()).isEqualTo(4); } @Test public void readLittleEndianInt() { - ParsableByteArray byteArray = new ParsableByteArray(new byte[] { - 0x01, 0x00, 0x00, (byte) 0xFF - }); + ParsableByteArray byteArray = new ParsableByteArray(new byte[] {0x01, 0x00, 0x00, (byte) 0xFF}); assertThat(byteArray.readLittleEndianInt()).isEqualTo(0xFF000001); assertThat(byteArray.getPosition()).isEqualTo(4); } @@ -379,9 +374,8 @@ public void readInt24Negative() { @Test public void readLittleEndianUnsignedShort() { - ParsableByteArray byteArray = new ParsableByteArray(new byte[] { - 0x01, (byte) 0xFF, 0x02, (byte) 0xFF - }); + ParsableByteArray byteArray = + new ParsableByteArray(new byte[] {0x01, (byte) 0xFF, 0x02, (byte) 0xFF}); assertThat(byteArray.readLittleEndianUnsignedShort()).isEqualTo(0xFF01); assertThat(byteArray.getPosition()).isEqualTo(2); assertThat(byteArray.readLittleEndianUnsignedShort()).isEqualTo(0xFF02); @@ -390,9 +384,8 @@ public void readLittleEndianUnsignedShort() { @Test public void readLittleEndianShort() { - ParsableByteArray byteArray = new ParsableByteArray(new byte[] { - 0x01, (byte) 0xFF, 0x02, (byte) 0xFF - }); + ParsableByteArray byteArray = + new ParsableByteArray(new byte[] {0x01, (byte) 0xFF, 0x02, (byte) 0xFF}); assertThat(byteArray.readLittleEndianShort()).isEqualTo((short) 0xFF01); assertThat(byteArray.getPosition()).isEqualTo(2); assertThat(byteArray.readLittleEndianShort()).isEqualTo((short) 0xFF02); @@ -402,13 +395,29 @@ public void readLittleEndianShort() { @Test public void readString() { byte[] data = { - (byte) 0xC3, (byte) 0xA4, (byte) 0x20, - (byte) 0xC3, (byte) 0xB6, (byte) 0x20, - (byte) 0xC2, (byte) 0xAE, (byte) 0x20, - (byte) 0xCF, (byte) 0x80, (byte) 0x20, - (byte) 0xE2, (byte) 0x88, (byte) 0x9A, (byte) 0x20, - (byte) 0xC2, (byte) 0xB1, (byte) 0x20, - (byte) 0xE8, (byte) 0xB0, (byte) 0xA2, (byte) 0x20, + (byte) 0xC3, + (byte) 0xA4, + (byte) 0x20, + (byte) 0xC3, + (byte) 0xB6, + (byte) 0x20, + (byte) 0xC2, + (byte) 0xAE, + (byte) 0x20, + (byte) 0xCF, + (byte) 0x80, + (byte) 0x20, + (byte) 0xE2, + (byte) 0x88, + (byte) 0x9A, + (byte) 0x20, + (byte) 0xC2, + (byte) 0xB1, + (byte) 0x20, + (byte) 0xE8, + (byte) 0xB0, + (byte) 0xA2, + (byte) 0x20, }; ParsableByteArray byteArray = new ParsableByteArray(data); assertThat(byteArray.readString(data.length)).isEqualTo("ä ö ® π √ ± 谢 "); @@ -425,9 +434,7 @@ public void readAsciiString() { @Test public void readStringOutOfBoundsDoesNotMovePosition() { - byte[] data = { - (byte) 0xC3, (byte) 0xA4, (byte) 0x20 - }; + byte[] data = {(byte) 0xC3, (byte) 0xA4, (byte) 0x20}; ParsableByteArray byteArray = new ParsableByteArray(data); try { byteArray.readString(data.length + 1); @@ -446,9 +453,7 @@ public void readEmptyString() { @Test public void readNullTerminatedStringWithLengths() { - byte[] bytes = new byte[] { - 'f', 'o', 'o', 0, 'b', 'a', 'r', 0 - }; + byte[] bytes = new byte[] {'f', 'o', 'o', 0, 'b', 'a', 'r', 0}; // Test with lengths that match NUL byte positions. ParsableByteArray parser = new ParsableByteArray(bytes); assertThat(parser.readNullTerminatedString(4)).isEqualTo("foo"); @@ -481,9 +486,7 @@ public void readNullTerminatedStringWithLengths() { @Test public void readNullTerminatedString() { - byte[] bytes = new byte[] { - 'f', 'o', 'o', 0, 'b', 'a', 'r', 0 - }; + byte[] bytes = new byte[] {'f', 'o', 'o', 0, 'b', 'a', 'r', 0}; // Test normal case. ParsableByteArray parser = new ParsableByteArray(bytes); assertThat(parser.readNullTerminatedString()).isEqualTo("foo"); @@ -505,9 +508,7 @@ public void readNullTerminatedString() { @Test public void readNullTerminatedStringWithoutEndingNull() { - byte[] bytes = new byte[] { - 'f', 'o', 'o', 0, 'b', 'a', 'r' - }; + byte[] bytes = new byte[] {'f', 'o', 'o', 0, 'b', 'a', 'r'}; ParsableByteArray parser = new ParsableByteArray(bytes); assertThat(parser.readNullTerminatedString()).isEqualTo("foo"); assertThat(parser.readNullTerminatedString()).isEqualTo("bar"); @@ -548,9 +549,7 @@ public void readDelimiterTerminatedStringWithoutEndingDelimiter() { @Test public void readSingleLineWithoutEndingTrail() { - byte[] bytes = new byte[] { - 'f', 'o', 'o' - }; + byte[] bytes = new byte[] {'f', 'o', 'o'}; ParsableByteArray parser = new ParsableByteArray(bytes); assertThat(parser.readLine()).isEqualTo("foo"); assertThat(parser.readLine()).isNull(); @@ -558,9 +557,7 @@ public void readSingleLineWithoutEndingTrail() { @Test public void readSingleLineWithEndingLf() { - byte[] bytes = new byte[] { - 'f', 'o', 'o', '\n' - }; + byte[] bytes = new byte[] {'f', 'o', 'o', '\n'}; ParsableByteArray parser = new ParsableByteArray(bytes); assertThat(parser.readLine()).isEqualTo("foo"); assertThat(parser.readLine()).isNull(); @@ -568,9 +565,7 @@ public void readSingleLineWithEndingLf() { @Test public void readTwoLinesWithCrFollowedByLf() { - byte[] bytes = new byte[] { - 'f', 'o', 'o', '\r', '\n', 'b', 'a', 'r' - }; + byte[] bytes = new byte[] {'f', 'o', 'o', '\r', '\n', 'b', 'a', 'r'}; ParsableByteArray parser = new ParsableByteArray(bytes); assertThat(parser.readLine()).isEqualTo("foo"); assertThat(parser.readLine()).isEqualTo("bar"); @@ -579,9 +574,7 @@ public void readTwoLinesWithCrFollowedByLf() { @Test public void readThreeLinesWithEmptyLine() { - byte[] bytes = new byte[] { - 'f', 'o', 'o', '\r', '\n', '\r', 'b', 'a', 'r' - }; + byte[] bytes = new byte[] {'f', 'o', 'o', '\r', '\n', '\r', 'b', 'a', 'r'}; ParsableByteArray parser = new ParsableByteArray(bytes); assertThat(parser.readLine()).isEqualTo("foo"); assertThat(parser.readLine()).isEqualTo(""); @@ -591,9 +584,7 @@ public void readThreeLinesWithEmptyLine() { @Test public void readFourLinesWithLfFollowedByCr() { - byte[] bytes = new byte[] { - 'f', 'o', 'o', '\n', '\r', '\r', 'b', 'a', 'r', '\r', '\n' - }; + byte[] bytes = new byte[] {'f', 'o', 'o', '\n', '\r', '\r', 'b', 'a', 'r', '\r', '\n'}; ParsableByteArray parser = new ParsableByteArray(bytes); assertThat(parser.readLine()).isEqualTo("foo"); assertThat(parser.readLine()).isEqualTo(""); @@ -601,5 +592,4 @@ public void readFourLinesWithLfFollowedByCr() { assertThat(parser.readLine()).isEqualTo("bar"); assertThat(parser.readLine()).isNull(); } - } diff --git a/library/common/src/test/java/com/google/android/exoplayer2/util/TimestampAdjusterTest.java b/library/common/src/test/java/com/google/android/exoplayer2/util/TimestampAdjusterTest.java new file mode 100644 index 00000000000..d7466362bee --- /dev/null +++ b/library/common/src/test/java/com/google/android/exoplayer2/util/TimestampAdjusterTest.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.exoplayer2.util; + +import static com.google.android.exoplayer2.util.TimestampAdjuster.MODE_NO_OFFSET; +import static com.google.common.truth.Truth.assertThat; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** Tests for {@link TimestampAdjuster}. */ +@RunWith(AndroidJUnit4.class) +public class TimestampAdjusterTest { + + @Test + public void adjustSampleTimestamp_fromZero() { + TimestampAdjuster adjuster = new TimestampAdjuster(/* firstSampleTimestampUs= */ 0); + long firstAdjustedTimestampUs = adjuster.adjustSampleTimestamp(/* timeUs= */ 2000); + long secondAdjustedTimestampUs = adjuster.adjustSampleTimestamp(/* timeUs= */ 6000); + + assertThat(firstAdjustedTimestampUs).isEqualTo(0); + assertThat(secondAdjustedTimestampUs).isEqualTo(4000); + } + + @Test + public void adjustSampleTimestamp_fromNonZero() { + TimestampAdjuster adjuster = new TimestampAdjuster(/* firstSampleTimestampUs= */ 1000); + long firstAdjustedTimestampUs = adjuster.adjustSampleTimestamp(/* timeUs= */ 2000); + long secondAdjustedTimestampUs = adjuster.adjustSampleTimestamp(/* timeUs= */ 6000); + + assertThat(firstAdjustedTimestampUs).isEqualTo(1000); + assertThat(secondAdjustedTimestampUs).isEqualTo(5000); + } + + @Test + public void adjustSampleTimestamp_noOffset() { + TimestampAdjuster adjuster = + new TimestampAdjuster(/* firstSampleTimestampUs= */ MODE_NO_OFFSET); + long firstAdjustedTimestampUs = adjuster.adjustSampleTimestamp(/* timeUs= */ 2000); + long secondAdjustedTimestampUs = adjuster.adjustSampleTimestamp(/* timeUs= */ 6000); + + assertThat(firstAdjustedTimestampUs).isEqualTo(2000); + assertThat(secondAdjustedTimestampUs).isEqualTo(6000); + } + + @Test + public void adjustSampleTimestamp_afterResetToNoOffset() { + TimestampAdjuster adjuster = new TimestampAdjuster(/* firstSampleTimestampUs= */ 0); + // Let the adjuster establish an offset, to make sure that reset really clears it. + adjuster.adjustSampleTimestamp(/* timeUs= */ 1000); + adjuster.reset(/* firstSampleTimestampUs= */ MODE_NO_OFFSET); + long firstAdjustedTimestampUs = adjuster.adjustSampleTimestamp(/* timeUs= */ 2000); + long secondAdjustedTimestampUs = adjuster.adjustSampleTimestamp(/* timeUs= */ 6000); + + assertThat(firstAdjustedTimestampUs).isEqualTo(2000); + assertThat(secondAdjustedTimestampUs).isEqualTo(6000); + } + + @Test + public void adjustSampleTimestamp_afterResetToDifferentStartTime() { + TimestampAdjuster adjuster = new TimestampAdjuster(/* firstSampleTimestampUs= */ 0); + // Let the adjuster establish an offset, to make sure that reset really clears it. + adjuster.adjustSampleTimestamp(/* timeUs= */ 1000); + adjuster.reset(/* firstSampleTimestampUs= */ 5000); + long firstAdjustedTimestampUs = adjuster.adjustSampleTimestamp(/* timeUs= */ 2000); + long secondAdjustedTimestampUs = adjuster.adjustSampleTimestamp(/* timeUs= */ 6000); + + assertThat(firstAdjustedTimestampUs).isEqualTo(5000); + assertThat(secondAdjustedTimestampUs).isEqualTo(9000); + } +} diff --git a/library/common/src/test/java/com/google/android/exoplayer2/util/UtilTest.java b/library/common/src/test/java/com/google/android/exoplayer2/util/UtilTest.java index d4aaa869f3d..7ee41bb8957 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/util/UtilTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/util/UtilTest.java @@ -984,9 +984,8 @@ public void inflate_withDeflatedData_success() { assertThat(Arrays.copyOf(output.getData(), output.limit())).isEqualTo(testData); } - // TODO: Revert to @Config(sdk = Config.ALL_SDKS) once b/143232359 is resolved @Test - @Config(minSdk = Config.OLDEST_SDK, maxSdk = Config.TARGET_SDK) + @Config(sdk = Config.ALL_SDKS) public void normalizeLanguageCode_keepsUndefinedTagsUnchanged() { assertThat(Util.normalizeLanguageCode(null)).isNull(); assertThat(Util.normalizeLanguageCode("")).isEmpty(); @@ -994,9 +993,8 @@ public void normalizeLanguageCode_keepsUndefinedTagsUnchanged() { assertThat(Util.normalizeLanguageCode("DoesNotExist")).isEqualTo("doesnotexist"); } - // TODO: Revert to @Config(sdk = Config.ALL_SDKS) once b/143232359 is resolved @Test - @Config(minSdk = Config.OLDEST_SDK, maxSdk = Config.TARGET_SDK) + @Config(sdk = Config.ALL_SDKS) public void normalizeLanguageCode_normalizesCodeToTwoLetterISOAndLowerCase_keepingAllSubtags() { assertThat(Util.normalizeLanguageCode("es")).isEqualTo("es"); assertThat(Util.normalizeLanguageCode("spa")).isEqualTo("es"); @@ -1014,9 +1012,8 @@ public void normalizeLanguageCode_normalizesCodeToTwoLetterISOAndLowerCase_keepi assertThat(Util.normalizeLanguageCode("sv-illegalSubtag")).isEqualTo("sv-illegalsubtag"); } - // TODO: Revert to @Config(sdk = Config.ALL_SDKS) once b/143232359 is resolved @Test - @Config(minSdk = Config.OLDEST_SDK, maxSdk = Config.TARGET_SDK) + @Config(sdk = Config.ALL_SDKS) public void normalizeLanguageCode_iso6392BibliographicalAndTextualCodes_areNormalizedToSameTag() { // See https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes. assertThat(Util.normalizeLanguageCode("alb")).isEqualTo(Util.normalizeLanguageCode("sqi")); @@ -1042,9 +1039,8 @@ public void normalizeLanguageCode_iso6392BibliographicalAndTextualCodes_areNorma assertThat(Util.normalizeLanguageCode("wel")).isEqualTo(Util.normalizeLanguageCode("cym")); } - // TODO: Revert to @Config(sdk = Config.ALL_SDKS) once b/143232359 is resolved @Test - @Config(minSdk = Config.OLDEST_SDK, maxSdk = Config.TARGET_SDK) + @Config(sdk = Config.ALL_SDKS) public void normalizeLanguageCode_deprecatedLanguageTagsAndModernReplacement_areNormalizedToSameTag() { // See https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes, "ISO 639:1988" @@ -1081,9 +1077,8 @@ public void normalizeLanguageCode_iso6392BibliographicalAndTextualCodes_areNorma .isEqualTo(Util.normalizeLanguageCode("zh-hsn")); } - // TODO: Revert to @Config(sdk = Config.ALL_SDKS) once b/143232359 is resolved @Test - @Config(minSdk = Config.OLDEST_SDK, maxSdk = Config.TARGET_SDK) + @Config(sdk = Config.ALL_SDKS) public void normalizeLanguageCode_macrolanguageTags_areFullyMaintained() { // See https://en.wikipedia.org/wiki/ISO_639_macrolanguage assertThat(Util.normalizeLanguageCode("zh-cmn")).isEqualTo("zh-cmn"); @@ -1133,6 +1128,40 @@ public void getStringForTime_withNegativeTime_setsNegativePrefix() { .isEqualTo("-00:35"); } + @Test + public void getErrorCodeFromPlatformDiagnosticsInfo_withValidInput_returnsExpectedValue() { + assertThat(Util.getErrorCodeFromPlatformDiagnosticsInfo("android.media.MediaDrm.error_1")) + .isEqualTo(1); + assertThat(Util.getErrorCodeFromPlatformDiagnosticsInfo("android.media.MediaDrm.error_neg_1")) + .isEqualTo(-1); + assertThat(Util.getErrorCodeFromPlatformDiagnosticsInfo("android.media.MediaCodec2.error_3")) + .isEqualTo(3); + assertThat( + Util.getErrorCodeFromPlatformDiagnosticsInfo( + "android.media.MediaCodec.weird_error_neg_10000")) + .isEqualTo(-10000); + assertThat( + Util.getErrorCodeFromPlatformDiagnosticsInfo( + "android.media.MediaCodec.weird_error_negx_10000")) + .isEqualTo(10000); + assertThat( + Util.getErrorCodeFromPlatformDiagnosticsInfo( + "android.media.MediaCodec.weird_error_xneg_10000")) + .isEqualTo(10000); + } + + @Test + public void getErrorCodeFromPlatformDiagnosticsInfo_withInvalidInput_returnsZero() { + // TODO (internal b/192337376): Change 0 for ERROR_UNKNOWN once available. + assertThat(Util.getErrorCodeFromPlatformDiagnosticsInfo("")).isEqualTo(0); + assertThat(Util.getErrorCodeFromPlatformDiagnosticsInfo("android.media.MediaDrm.empty")) + .isEqualTo(0); + assertThat(Util.getErrorCodeFromPlatformDiagnosticsInfo("android.media.MediaDrm.error_neg_1a")) + .isEqualTo(0); + assertThat(Util.getErrorCodeFromPlatformDiagnosticsInfo("android.media.MediaDrm.error_a1")) + .isEqualTo(0); + } + private static void assertEscapeUnescapeFileName(String fileName, String escapedFileName) { assertThat(escapeFileName(fileName)).isEqualTo(escapedFileName); assertThat(unescapeFileName(escapedFileName)).isEqualTo(fileName); diff --git a/library/core/build.gradle b/library/core/build.gradle index a4cd3bd2a34..81e1a3d543c 100644 --- a/library/core/build.gradle +++ b/library/core/build.gradle @@ -48,7 +48,7 @@ dependencies { androidTestImplementation(project(modulePrefix + 'testutils')) { exclude module: modulePrefix.substring(1) + 'library-core' } - testImplementation 'com.squareup.okhttp3:mockwebserver:' + mockWebServerVersion + testImplementation 'com.squareup.okhttp3:mockwebserver:' + okhttpVersion testImplementation 'org.robolectric:robolectric:' + robolectricVersion testImplementation project(modulePrefix + 'testutils') testImplementation project(modulePrefix + 'robolectricutils') diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/ClippedPlaybackTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/ClippedPlaybackTest.java index 5a33dcf07c2..e5a2fac4d92 100644 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/ClippedPlaybackTest.java +++ b/library/core/src/androidTest/java/com/google/android/exoplayer2/ClippedPlaybackTest.java @@ -68,8 +68,8 @@ public void subtitlesRespectClipping_singlePeriod() throws Exception { .addListener( new Player.Listener() { @Override - public void onPlaybackStateChanged(@Player.State int state) { - if (state == Player.STATE_ENDED) { + public void onPlaybackStateChanged(@Player.State int playbackState) { + if (playbackState == Player.STATE_ENDED) { playbackEnded.open(); } } @@ -122,8 +122,8 @@ public void subtitlesRespectClipping_multiplePeriods() throws Exception { .addListener( new Player.Listener() { @Override - public void onPlaybackStateChanged(@Player.State int state) { - if (state == Player.STATE_ENDED) { + public void onPlaybackStateChanged(@Player.State int playbackState) { + if (playbackState == Player.STATE_ENDED) { playbackEnded.open(); } } diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/ContentDataSourceTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/ContentDataSourceTest.java index b59a6e1618c..3b65c2c84e1 100644 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/ContentDataSourceTest.java +++ b/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/ContentDataSourceTest.java @@ -90,8 +90,11 @@ private static void assertData(int offset, int length, boolean pipeMode) throws DataSpec dataSpec = new DataSpec(contentUri, offset, length); byte[] completeData = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), DATA_PATH); - byte[] expectedData = Arrays.copyOfRange(completeData, offset, - length == C.LENGTH_UNSET ? completeData.length : offset + length); + byte[] expectedData = + Arrays.copyOfRange( + completeData, + offset, + length == C.LENGTH_UNSET ? completeData.length : offset + length); TestUtil.assertDataSourceContent(dataSource, dataSpec, expectedData, !pipeMode); } finally { dataSource.close(); diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/TestContentProvider.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/TestContentProvider.java index 3d071c204ac..a5e53d02d3f 100644 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/TestContentProvider.java +++ b/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/TestContentProvider.java @@ -130,5 +130,4 @@ public void writeDataToPipe( private static String getFileName(Uri uri) { return uri.getPath().replaceFirst("/", ""); } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/AbstractConcatenatedTimeline.java b/library/core/src/main/java/com/google/android/exoplayer2/AbstractConcatenatedTimeline.java index 73bb49ed401..99fb0a41126 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/AbstractConcatenatedTimeline.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/AbstractConcatenatedTimeline.java @@ -32,7 +32,7 @@ public abstract class AbstractConcatenatedTimeline extends Timeline { * @param concatenatedUid UID of a period in a concatenated timeline. * @return UID of the child timeline this period belongs to. */ - @SuppressWarnings("nullness:return.type.incompatible") + @SuppressWarnings("nullness:return") public static Object getChildTimelineUidFromConcatenatedUid(Object concatenatedUid) { return ((Pair) concatenatedUid).first; } @@ -43,7 +43,7 @@ public static Object getChildTimelineUidFromConcatenatedUid(Object concatenatedU * @param concatenatedUid UID of a period in a concatenated timeline. * @return UID of the period in the child timeline. */ - @SuppressWarnings("nullness:return.type.incompatible") + @SuppressWarnings("nullness:return") public static Object getChildPeriodUidFromConcatenatedUid(Object concatenatedUid) { return ((Pair) concatenatedUid).second; } @@ -207,14 +207,14 @@ public final Window getWindow(int windowIndex, Window window, long defaultPositi } @Override - public final Period getPeriodByUid(Object uid, Period period) { - Object childUid = getChildTimelineUidFromConcatenatedUid(uid); - Object periodUid = getChildPeriodUidFromConcatenatedUid(uid); + public final Period getPeriodByUid(Object periodUid, Period period) { + Object childUid = getChildTimelineUidFromConcatenatedUid(periodUid); + Object childPeriodUid = getChildPeriodUidFromConcatenatedUid(periodUid); int childIndex = getChildIndexByChildUid(childUid); int firstWindowIndexInChild = getFirstWindowIndexByChildIndex(childIndex); - getTimelineByChildIndex(childIndex).getPeriodByUid(periodUid, period); + getTimelineByChildIndex(childIndex).getPeriodByUid(childPeriodUid, period); period.windowIndex += firstWindowIndexInChild; - period.uid = uid; + period.uid = periodUid; return period; } @@ -240,12 +240,12 @@ public final int getIndexOfPeriod(Object uid) { return C.INDEX_UNSET; } Object childUid = getChildTimelineUidFromConcatenatedUid(uid); - Object periodUid = getChildPeriodUidFromConcatenatedUid(uid); + Object childPeriodUid = getChildPeriodUidFromConcatenatedUid(uid); int childIndex = getChildIndexByChildUid(childUid); if (childIndex == C.INDEX_UNSET) { return C.INDEX_UNSET; } - int periodIndexInChild = getTimelineByChildIndex(childIndex).getIndexOfPeriod(periodUid); + int periodIndexInChild = getTimelineByChildIndex(childIndex).getIndexOfPeriod(childPeriodUid); return periodIndexInChild == C.INDEX_UNSET ? C.INDEX_UNSET : getFirstPeriodIndexByChildIndex(childIndex) + periodIndexInChild; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/BaseRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/BaseRenderer.java index 198244d9fea..23b5352ed21 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/BaseRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/BaseRenderer.java @@ -45,8 +45,8 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities { private boolean throwRendererExceptionIsExecuting; /** - * @param trackType The track type that the renderer handles. One of the {@link C} - * {@code TRACK_TYPE_*} constants. + * @param trackType The track type that the renderer handles. One of the {@link C} {@code + * TRACK_TYPE_*} constants. */ public BaseRenderer(int trackType) { this.trackType = trackType; @@ -113,7 +113,9 @@ public final void replaceStream( throws ExoPlaybackException { Assertions.checkState(!streamIsFinal); this.stream = stream; - readingPositionUs = offsetUs; + if (readingPositionUs == C.TIME_END_OF_SOURCE) { + readingPositionUs = startPositionUs; + } streamFormats = formats; streamOffsetUs = offsetUs; onStreamChanged(formats, startPositionUs, offsetUs); @@ -194,7 +196,7 @@ public int supportsMixedMimeTypeAdaptation() throws ExoPlaybackException { // PlayerMessage.Target implementation. @Override - public void handleMessage(int messageType, @Nullable Object payload) throws ExoPlaybackException { + public void handleMessage(int messageType, @Nullable Object message) throws ExoPlaybackException { // Do nothing. } @@ -253,8 +255,8 @@ protected void onPositionReset(long positionUs, boolean joining) throws ExoPlayb /** * Called when the renderer is started. - *

        - * The default implementation is a no-op. + * + *

        The default implementation is a no-op. * * @throws ExoPlaybackException If an error occurs. */ @@ -273,8 +275,8 @@ protected void onStopped() { /** * Called when the renderer is disabled. - *

        - * The default implementation is a no-op. + * + *

        The default implementation is a no-op. */ protected void onDisabled() { // Do nothing. @@ -325,9 +327,7 @@ protected final RendererConfiguration getConfiguration() { return Assertions.checkNotNull(configuration); } - /** - * Returns the index of the renderer within the player. - */ + /** Returns the index of the renderer within the player. */ protected final int getIndex() { return index; } @@ -338,10 +338,14 @@ protected final int getIndex() { * * @param cause The cause of the exception. * @param format The current format used by the renderer. May be null. + * @param errorCode A {@link PlaybackException.ErrorCode} to identify the cause of the playback + * failure. + * @return The created instance, in which {@link ExoPlaybackException#isRecoverable} is {@code + * false}. */ protected final ExoPlaybackException createRendererException( - Throwable cause, @Nullable Format format) { - return createRendererException(cause, format, /* isRecoverable= */ false); + Throwable cause, @Nullable Format format, @PlaybackException.ErrorCode int errorCode) { + return createRendererException(cause, format, /* isRecoverable= */ false, errorCode); } /** @@ -351,9 +355,15 @@ protected final ExoPlaybackException createRendererException( * @param cause The cause of the exception. * @param format The current format used by the renderer. May be null. * @param isRecoverable If the error is recoverable by disabling and re-enabling the renderer. + * @param errorCode A {@link PlaybackException.ErrorCode} to identify the cause of the playback + * failure. + * @return The created instance. */ protected final ExoPlaybackException createRendererException( - Throwable cause, @Nullable Format format, boolean isRecoverable) { + Throwable cause, + @Nullable Format format, + boolean isRecoverable, + @PlaybackException.ErrorCode int errorCode) { @C.FormatSupport int formatSupport = C.FORMAT_HANDLED; if (format != null && !throwRendererExceptionIsExecuting) { // Prevent recursive re-entry from subclass supportsFormat implementations. @@ -367,7 +377,7 @@ protected final ExoPlaybackException createRendererException( } } return ExoPlaybackException.createForRenderer( - cause, getName(), getIndex(), format, formatSupport, isRecoverable); + cause, getName(), getIndex(), format, formatSupport, isRecoverable, errorCode); } /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/DefaultMediaClock.java b/library/core/src/main/java/com/google/android/exoplayer2/DefaultMediaClock.java index 9ee1846fc12..412a6fdbff3 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/DefaultMediaClock.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/DefaultMediaClock.java @@ -22,8 +22,8 @@ import com.google.android.exoplayer2.util.StandaloneMediaClock; /** - * Default {@link MediaClock} which uses a renderer media clock and falls back to a - * {@link StandaloneMediaClock} if necessary. + * Default {@link MediaClock} which uses a renderer media clock and falls back to a {@link + * StandaloneMediaClock} if necessary. */ /* package */ final class DefaultMediaClock implements MediaClock { @@ -60,17 +60,13 @@ public DefaultMediaClock(PlaybackParametersListener listener, Clock clock) { isUsingStandaloneClock = true; } - /** - * Starts the standalone fallback clock. - */ + /** Starts the standalone fallback clock. */ public void start() { standaloneClockIsStarted = true; standaloneClock.start(); } - /** - * Stops the standalone fallback clock. - */ + /** Stops the standalone fallback clock. */ public void stop() { standaloneClockIsStarted = false; standaloneClock.stop(); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/DefaultRenderersFactory.java b/library/core/src/main/java/com/google/android/exoplayer2/DefaultRenderersFactory.java index d9958fd6084..8fd91986c15 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/DefaultRenderersFactory.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/DefaultRenderersFactory.java @@ -61,15 +61,13 @@ public class DefaultRenderersFactory implements RenderersFactory { @Retention(RetentionPolicy.SOURCE) @IntDef({EXTENSION_RENDERER_MODE_OFF, EXTENSION_RENDERER_MODE_ON, EXTENSION_RENDERER_MODE_PREFER}) public @interface ExtensionRendererMode {} - /** - * Do not allow use of extension renderers. - */ + /** Do not allow use of extension renderers. */ public static final int EXTENSION_RENDERER_MODE_OFF = 0; /** * Allow use of extension renderers. Extension renderers are indexed after core renderers of the * same type. A {@link TrackSelector} that prefers the first suitable renderer will therefore - * prefer to use a core renderer to an extension renderer in the case that both are able to play - * a given track. + * prefer to use a core renderer to an extension renderer in the case that both are able to play a + * given track. */ public static final int EXTENSION_RENDERER_MODE_ON = 1; /** @@ -331,10 +329,18 @@ public Renderer[] createRenderers( audioRendererEventListener, renderersList); } - buildTextRenderers(context, textRendererOutput, eventHandler.getLooper(), - extensionRendererMode, renderersList); - buildMetadataRenderers(context, metadataRendererOutput, eventHandler.getLooper(), - extensionRendererMode, renderersList); + buildTextRenderers( + context, + textRendererOutput, + eventHandler.getLooper(), + extensionRendererMode, + renderersList); + buildMetadataRenderers( + context, + metadataRendererOutput, + eventHandler.getLooper(), + extensionRendererMode, + renderersList); buildCameraMotionRenderers(context, extensionRendererMode, renderersList); buildMiscellaneousRenderers(context, eventHandler, extensionRendererMode, renderersList); return renderersList.toArray(new Renderer[0]); @@ -390,7 +396,6 @@ protected void buildVideoRenderers( try { // Full class names used for constructor args so the LINT rule triggers if any of them move. - // LINT.IfChange Class clazz = Class.forName("com.google.android.exoplayer2.ext.vp9.LibvpxVideoRenderer"); Constructor constructor = clazz.getConstructor( @@ -398,7 +403,6 @@ protected void buildVideoRenderers( android.os.Handler.class, com.google.android.exoplayer2.video.VideoRendererEventListener.class, int.class); - // LINT.ThenChange(../../../../../../../proguard-rules.txt) Renderer renderer = (Renderer) constructor.newInstance( @@ -417,7 +421,6 @@ protected void buildVideoRenderers( try { // Full class names used for constructor args so the LINT rule triggers if any of them move. - // LINT.IfChange Class clazz = Class.forName("com.google.android.exoplayer2.ext.av1.Libgav1VideoRenderer"); Constructor constructor = clazz.getConstructor( @@ -425,7 +428,6 @@ protected void buildVideoRenderers( android.os.Handler.class, com.google.android.exoplayer2.video.VideoRendererEventListener.class, int.class); - // LINT.ThenChange(../../../../../../../proguard-rules.txt) Renderer renderer = (Renderer) constructor.newInstance( @@ -491,14 +493,12 @@ protected void buildAudioRenderers( try { // Full class names used for constructor args so the LINT rule triggers if any of them move. - // LINT.IfChange Class clazz = Class.forName("com.google.android.exoplayer2.ext.opus.LibopusAudioRenderer"); Constructor constructor = clazz.getConstructor( android.os.Handler.class, com.google.android.exoplayer2.audio.AudioRendererEventListener.class, com.google.android.exoplayer2.audio.AudioSink.class); - // LINT.ThenChange(../../../../../../../proguard-rules.txt) Renderer renderer = (Renderer) constructor.newInstance(eventHandler, eventListener, audioSink); out.add(extensionRendererIndex++, renderer); @@ -512,14 +512,12 @@ protected void buildAudioRenderers( try { // Full class names used for constructor args so the LINT rule triggers if any of them move. - // LINT.IfChange Class clazz = Class.forName("com.google.android.exoplayer2.ext.flac.LibflacAudioRenderer"); Constructor constructor = clazz.getConstructor( android.os.Handler.class, com.google.android.exoplayer2.audio.AudioRendererEventListener.class, com.google.android.exoplayer2.audio.AudioSink.class); - // LINT.ThenChange(../../../../../../../proguard-rules.txt) Renderer renderer = (Renderer) constructor.newInstance(eventHandler, eventListener, audioSink); out.add(extensionRendererIndex++, renderer); @@ -533,7 +531,6 @@ protected void buildAudioRenderers( try { // Full class names used for constructor args so the LINT rule triggers if any of them move. - // LINT.IfChange Class clazz = Class.forName("com.google.android.exoplayer2.ext.ffmpeg.FfmpegAudioRenderer"); Constructor constructor = @@ -541,7 +538,6 @@ protected void buildAudioRenderers( android.os.Handler.class, com.google.android.exoplayer2.audio.AudioRendererEventListener.class, com.google.android.exoplayer2.audio.AudioSink.class); - // LINT.ThenChange(../../../../../../../proguard-rules.txt) Renderer renderer = (Renderer) constructor.newInstance(eventHandler, eventListener, audioSink); out.add(extensionRendererIndex++, renderer); @@ -610,8 +606,11 @@ protected void buildCameraMotionRenderers( * @param extensionRendererMode The extension renderer mode. * @param out An array to which the built renderers should be appended. */ - protected void buildMiscellaneousRenderers(Context context, Handler eventHandler, - @ExtensionRendererMode int extensionRendererMode, ArrayList out) { + protected void buildMiscellaneousRenderers( + Context context, + Handler eventHandler, + @ExtensionRendererMode int extensionRendererMode, + ArrayList out) { // Do nothing. } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/ExoPlaybackException.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlaybackException.java similarity index 60% rename from library/common/src/main/java/com/google/android/exoplayer2/ExoPlaybackException.java rename to library/core/src/main/java/com/google/android/exoplayer2/ExoPlaybackException.java index eb04eef9c6f..2d78d4409d8 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/ExoPlaybackException.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlaybackException.java @@ -16,7 +16,6 @@ package com.google.android.exoplayer2; import android.os.Bundle; -import android.os.RemoteException; import android.os.SystemClock; import android.text.TextUtils; import androidx.annotation.CheckResult; @@ -24,6 +23,7 @@ import androidx.annotation.Nullable; import com.google.android.exoplayer2.C.FormatSupport; import com.google.android.exoplayer2.source.MediaPeriodId; +import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Util; import java.io.IOException; @@ -32,7 +32,7 @@ import java.lang.annotation.RetentionPolicy; /** Thrown when a non locally recoverable playback failure occurs. */ -public final class ExoPlaybackException extends Exception implements Bundleable { +public final class ExoPlaybackException extends PlaybackException { /** * The type of source that produced the error. One of {@link #TYPE_SOURCE}, {@link #TYPE_RENDERER} @@ -44,23 +44,21 @@ public final class ExoPlaybackException extends Exception implements Bundleable @IntDef({TYPE_SOURCE, TYPE_RENDERER, TYPE_UNEXPECTED, TYPE_REMOTE}) public @interface Type {} /** - * The error occurred loading data from a {@code MediaSource}. + * The error occurred loading data from a {@link MediaSource}. * *

        Call {@link #getSourceException()} to retrieve the underlying cause. */ - // TODO(b/172315872) MediaSource was a link. Link to equivalent concept or remove @code. public static final int TYPE_SOURCE = 0; /** - * The error occurred in a {@code Renderer}. + * The error occurred in a {@link Renderer}. * *

        Call {@link #getRendererException()} to retrieve the underlying cause. */ - // TODO(b/172315872) Renderer was a link. Link to equivalent concept or remove @code. public static final int TYPE_RENDERER = 1; /** * The error was an unexpected {@link RuntimeException}. - *

        - * Call {@link #getUnexpectedException()} to retrieve the underlying cause. + * + *

        Call {@link #getUnexpectedException()} to retrieve the underlying cause. */ public static final int TYPE_UNEXPECTED = 2; /** @@ -73,16 +71,10 @@ public final class ExoPlaybackException extends Exception implements Bundleable /** The {@link Type} of the playback failure. */ @Type public final int type; - /** - * If {@link #type} is {@link #TYPE_RENDERER}, this is the name of the renderer, or null if - * unknown. - */ + /** If {@link #type} is {@link #TYPE_RENDERER}, this is the name of the renderer. */ @Nullable public final String rendererName; - /** - * If {@link #type} is {@link #TYPE_RENDERER}, this is the index of the renderer, or {@link - * C#INDEX_UNSET} if unknown. - */ + /** If {@link #type} is {@link #TYPE_RENDERER}, this is the index of the renderer. */ public final int rendererIndex; /** @@ -98,9 +90,6 @@ public final class ExoPlaybackException extends Exception implements Bundleable */ @FormatSupport public final int rendererFormatSupport; - /** The value of {@link SystemClock#elapsedRealtime()} when this exception was created. */ - public final long timestampMs; - /** The {@link MediaPeriodId} of the media associated with this error, or null if undetermined. */ @Nullable public final MediaPeriodId mediaPeriodId; @@ -111,60 +100,15 @@ public final class ExoPlaybackException extends Exception implements Bundleable */ /* package */ final boolean isRecoverable; - @Nullable private final Throwable cause; - /** * Creates an instance of type {@link #TYPE_SOURCE}. * * @param cause The cause of the failure. + * @param errorCode See {@link #errorCode}. * @return The created instance. */ - public static ExoPlaybackException createForSource(IOException cause) { - return new ExoPlaybackException(TYPE_SOURCE, cause); - } - - /** - * Creates an instance of type {@link #TYPE_RENDERER} for an unknown renderer. - * - * @param cause The cause of the failure. - * @return The created instance. - */ - public static ExoPlaybackException createForRenderer(Exception cause) { - return new ExoPlaybackException( - TYPE_RENDERER, - cause, - /* customMessage= */ null, - /* rendererName */ null, - /* rendererIndex= */ C.INDEX_UNSET, - /* rendererFormat= */ null, - /* rendererFormatSupport= */ C.FORMAT_HANDLED, - /* isRecoverable= */ false); - } - - /** - * Creates an instance of type {@link #TYPE_RENDERER}. - * - * @param cause The cause of the failure. - * @param rendererIndex The index of the renderer in which the failure occurred. - * @param rendererFormat The {@link Format} the renderer was using at the time of the exception, - * or null if the renderer wasn't using a {@link Format}. - * @param rendererFormatSupport The {@link FormatSupport} of the renderer for {@code - * rendererFormat}. Ignored if {@code rendererFormat} is null. - * @return The created instance. - */ - public static ExoPlaybackException createForRenderer( - Throwable cause, - String rendererName, - int rendererIndex, - @Nullable Format rendererFormat, - @FormatSupport int rendererFormatSupport) { - return createForRenderer( - cause, - rendererName, - rendererIndex, - rendererFormat, - rendererFormatSupport, - /* isRecoverable= */ false); + public static ExoPlaybackException createForSource(IOException cause, int errorCode) { + return new ExoPlaybackException(TYPE_SOURCE, cause, errorCode); } /** @@ -177,6 +121,7 @@ public static ExoPlaybackException createForRenderer( * @param rendererFormatSupport The {@link FormatSupport} of the renderer for {@code * rendererFormat}. Ignored if {@code rendererFormat} is null. * @param isRecoverable If the failure can be recovered by disabling and re-enabling the renderer. + * @param errorCode See {@link #errorCode}. * @return The created instance. */ public static ExoPlaybackException createForRenderer( @@ -185,11 +130,14 @@ public static ExoPlaybackException createForRenderer( int rendererIndex, @Nullable Format rendererFormat, @FormatSupport int rendererFormatSupport, - boolean isRecoverable) { + boolean isRecoverable, + @ErrorCode int errorCode) { + return new ExoPlaybackException( TYPE_RENDERER, cause, /* customMessage= */ null, + errorCode, rendererName, rendererIndex, rendererFormat, @@ -197,14 +145,25 @@ public static ExoPlaybackException createForRenderer( isRecoverable); } + /** + * @deprecated Use {@link #createForUnexpected(RuntimeException, int) + * createForUnexpected(RuntimeException, ERROR_CODE_UNSPECIFIED)} instead. + */ + @Deprecated + public static ExoPlaybackException createForUnexpected(RuntimeException cause) { + return createForUnexpected(cause, ERROR_CODE_UNSPECIFIED); + } + /** * Creates an instance of type {@link #TYPE_UNEXPECTED}. * * @param cause The cause of the failure. + * @param errorCode See {@link #errorCode}. * @return The created instance. */ - public static ExoPlaybackException createForUnexpected(RuntimeException cause) { - return new ExoPlaybackException(TYPE_UNEXPECTED, cause); + public static ExoPlaybackException createForUnexpected( + RuntimeException cause, @ErrorCode int errorCode) { + return new ExoPlaybackException(TYPE_UNEXPECTED, cause, errorCode); } /** @@ -214,14 +173,11 @@ public static ExoPlaybackException createForUnexpected(RuntimeException cause) { * @return The created instance. */ public static ExoPlaybackException createForRemote(String message) { - return new ExoPlaybackException(TYPE_REMOTE, message); - } - - private ExoPlaybackException(@Type int type, Throwable cause) { - this( - type, - cause, - /* customMessage= */ null, + return new ExoPlaybackException( + TYPE_REMOTE, + /* cause= */ null, + /* customMessage= */ message, + ERROR_CODE_REMOTE_ERROR, /* rendererName= */ null, /* rendererIndex= */ C.INDEX_UNSET, /* rendererFormat= */ null, @@ -229,11 +185,12 @@ private ExoPlaybackException(@Type int type, Throwable cause) { /* isRecoverable= */ false); } - private ExoPlaybackException(@Type int type, String message) { + private ExoPlaybackException(@Type int type, Throwable cause, @ErrorCode int errorCode) { this( type, - /* cause= */ null, - /* customMessage= */ message, + cause, + /* customMessage= */ null, + errorCode, /* rendererName= */ null, /* rendererIndex= */ C.INDEX_UNSET, /* rendererFormat= */ null, @@ -245,6 +202,7 @@ private ExoPlaybackException( @Type int type, @Nullable Throwable cause, @Nullable String customMessage, + @ErrorCode int errorCode, @Nullable String rendererName, int rendererIndex, @Nullable Format rendererFormat, @@ -259,6 +217,7 @@ private ExoPlaybackException( rendererFormat, rendererFormatSupport), cause, + errorCode, type, rendererName, rendererIndex, @@ -269,9 +228,24 @@ private ExoPlaybackException( isRecoverable); } + private ExoPlaybackException(Bundle bundle) { + super(bundle); + type = bundle.getInt(keyForField(FIELD_TYPE), /* defaultValue= */ TYPE_UNEXPECTED); + rendererName = bundle.getString(keyForField(FIELD_RENDERER_NAME)); + rendererIndex = + bundle.getInt(keyForField(FIELD_RENDERER_INDEX), /* defaultValue= */ C.INDEX_UNSET); + rendererFormat = bundle.getParcelable(keyForField(FIELD_RENDERER_FORMAT)); + rendererFormatSupport = + bundle.getInt( + keyForField(FIELD_RENDERER_FORMAT_SUPPORT), /* defaultValue= */ C.FORMAT_HANDLED); + isRecoverable = bundle.getBoolean(keyForField(FIELD_IS_RECOVERABLE), /* defaultValue= */ false); + mediaPeriodId = null; + } + private ExoPlaybackException( String message, @Nullable Throwable cause, + @ErrorCode int errorCode, @Type int type, @Nullable String rendererName, int rendererIndex, @@ -280,16 +254,15 @@ private ExoPlaybackException( @Nullable MediaPeriodId mediaPeriodId, long timestampMs, boolean isRecoverable) { - super(message, cause); + super(message, cause, errorCode, timestampMs); Assertions.checkArgument(!isRecoverable || type == TYPE_RENDERER); + Assertions.checkArgument(cause != null || type == TYPE_REMOTE); this.type = type; - this.cause = cause; this.rendererName = rendererName; this.rendererIndex = rendererIndex; this.rendererFormat = rendererFormat; this.rendererFormatSupport = rendererFormatSupport; this.mediaPeriodId = mediaPeriodId; - this.timestampMs = timestampMs; this.isRecoverable = isRecoverable; } @@ -300,7 +273,7 @@ private ExoPlaybackException( */ public IOException getSourceException() { Assertions.checkState(type == TYPE_SOURCE); - return (IOException) Assertions.checkNotNull(cause); + return (IOException) Assertions.checkNotNull(getCause()); } /** @@ -310,7 +283,7 @@ public IOException getSourceException() { */ public Exception getRendererException() { Assertions.checkState(type == TYPE_RENDERER); - return (Exception) Assertions.checkNotNull(cause); + return (Exception) Assertions.checkNotNull(getCause()); } /** @@ -320,7 +293,24 @@ public Exception getRendererException() { */ public RuntimeException getUnexpectedException() { Assertions.checkState(type == TYPE_UNEXPECTED); - return (RuntimeException) Assertions.checkNotNull(cause); + return (RuntimeException) Assertions.checkNotNull(getCause()); + } + + @Override + public boolean errorInfoEquals(@Nullable PlaybackException that) { + if (!super.errorInfoEquals(that)) { + return false; + } + // We know that is not null and is an ExoPlaybackException because of the super call returning + // true. + ExoPlaybackException other = (ExoPlaybackException) Util.castNonNull(that); + return type == other.type + && Util.areEqual(rendererName, other.rendererName) + && rendererIndex == other.rendererIndex + && Util.areEqual(rendererFormat, other.rendererFormat) + && rendererFormatSupport == other.rendererFormatSupport + && Util.areEqual(mediaPeriodId, other.mediaPeriodId) + && isRecoverable == other.isRecoverable; } /** @@ -333,7 +323,8 @@ public RuntimeException getUnexpectedException() { /* package */ ExoPlaybackException copyWithMediaPeriodId(@Nullable MediaPeriodId mediaPeriodId) { return new ExoPlaybackException( Util.castNonNull(getMessage()), - cause, + getCause(), + errorCode, type, rendererName, rendererIndex, @@ -382,33 +373,16 @@ private static String deriveMessage( } // Bundleable implementation. - // TODO(b/145954241): Revisit bundling fields when this class is split for Player and ExoPlayer. - @Documented - @Retention(RetentionPolicy.SOURCE) - @IntDef({ - FIELD_MESSAGE, - FIELD_TYPE, - FIELD_RENDERER_NAME, - FIELD_RENDERER_INDEX, - FIELD_RENDERER_FORMAT, - FIELD_RENDERER_FORMAT_SUPPORT, - FIELD_TIME_STAMP_MS, - FIELD_IS_RECOVERABLE, - FIELD_CAUSE_CLASS_NAME, - FIELD_CAUSE_MESSAGE - }) - private @interface FieldNumber {} - private static final int FIELD_MESSAGE = 0; - private static final int FIELD_TYPE = 1; - private static final int FIELD_RENDERER_NAME = 2; - private static final int FIELD_RENDERER_INDEX = 3; - private static final int FIELD_RENDERER_FORMAT = 4; - private static final int FIELD_RENDERER_FORMAT_SUPPORT = 5; - private static final int FIELD_TIME_STAMP_MS = 6; - private static final int FIELD_IS_RECOVERABLE = 7; - private static final int FIELD_CAUSE_CLASS_NAME = 8; - private static final int FIELD_CAUSE_MESSAGE = 9; + /** Object that can restore {@link ExoPlaybackException} from a {@link Bundle}. */ + public static final Creator CREATOR = ExoPlaybackException::new; + + private static final int FIELD_TYPE = FIELD_CUSTOM_ID_BASE + 1; + private static final int FIELD_RENDERER_NAME = FIELD_CUSTOM_ID_BASE + 2; + private static final int FIELD_RENDERER_INDEX = FIELD_CUSTOM_ID_BASE + 3; + private static final int FIELD_RENDERER_FORMAT = FIELD_CUSTOM_ID_BASE + 4; + private static final int FIELD_RENDERER_FORMAT_SUPPORT = FIELD_CUSTOM_ID_BASE + 5; + private static final int FIELD_IS_RECOVERABLE = FIELD_CUSTOM_ID_BASE + 6; /** * {@inheritDoc} @@ -418,98 +392,13 @@ private static String deriveMessage( */ @Override public Bundle toBundle() { - Bundle bundle = new Bundle(); - bundle.putString(keyForField(FIELD_MESSAGE), getMessage()); + Bundle bundle = super.toBundle(); bundle.putInt(keyForField(FIELD_TYPE), type); bundle.putString(keyForField(FIELD_RENDERER_NAME), rendererName); bundle.putInt(keyForField(FIELD_RENDERER_INDEX), rendererIndex); bundle.putParcelable(keyForField(FIELD_RENDERER_FORMAT), rendererFormat); bundle.putInt(keyForField(FIELD_RENDERER_FORMAT_SUPPORT), rendererFormatSupport); - bundle.putLong(keyForField(FIELD_TIME_STAMP_MS), timestampMs); bundle.putBoolean(keyForField(FIELD_IS_RECOVERABLE), isRecoverable); - if (cause != null) { - bundle.putString(keyForField(FIELD_CAUSE_CLASS_NAME), cause.getClass().getName()); - bundle.putString(keyForField(FIELD_CAUSE_MESSAGE), cause.getMessage()); - } return bundle; } - - /** Object that can restore {@link ExoPlaybackException} from a {@link Bundle}. */ - public static final Creator CREATOR = ExoPlaybackException::fromBundle; - - private static ExoPlaybackException fromBundle(Bundle bundle) { - int type = bundle.getInt(keyForField(FIELD_TYPE), /* defaultValue= */ TYPE_UNEXPECTED); - @Nullable String rendererName = bundle.getString(keyForField(FIELD_RENDERER_NAME)); - int rendererIndex = - bundle.getInt(keyForField(FIELD_RENDERER_INDEX), /* defaultValue= */ C.INDEX_UNSET); - @Nullable Format rendererFormat = bundle.getParcelable(keyForField(FIELD_RENDERER_FORMAT)); - int rendererFormatSupport = - bundle.getInt( - keyForField(FIELD_RENDERER_FORMAT_SUPPORT), /* defaultValue= */ C.FORMAT_HANDLED); - long timestampMs = - bundle.getLong( - keyForField(FIELD_TIME_STAMP_MS), /* defaultValue= */ SystemClock.elapsedRealtime()); - boolean isRecoverable = - bundle.getBoolean(keyForField(FIELD_IS_RECOVERABLE), /* defaultValue= */ false); - @Nullable String message = bundle.getString(keyForField(FIELD_MESSAGE)); - if (message == null) { - message = - deriveMessage( - type, - /* customMessage= */ null, - rendererName, - rendererIndex, - rendererFormat, - rendererFormatSupport); - } - - @Nullable String causeClassName = bundle.getString(keyForField(FIELD_CAUSE_CLASS_NAME)); - @Nullable String causeMessage = bundle.getString(keyForField(FIELD_CAUSE_MESSAGE)); - @Nullable Throwable cause = null; - if (!TextUtils.isEmpty(causeClassName)) { - final Class clazz; - try { - clazz = - Class.forName( - causeClassName, - /* initialize= */ true, - ExoPlaybackException.class.getClassLoader()); - if (Throwable.class.isAssignableFrom(clazz)) { - cause = createThrowable(clazz, causeMessage); - } - } catch (Throwable e) { - // Intentionally catch Throwable to catch both Exception and Error. - cause = createRemoteException(causeMessage); - } - } - - return new ExoPlaybackException( - message, - cause, - type, - rendererName, - rendererIndex, - rendererFormat, - rendererFormatSupport, - /* mediaPeriodId= */ null, - timestampMs, - isRecoverable); - } - - // Creates a new {@link Throwable} with possibly @{code null} message. - @SuppressWarnings("nullness:argument.type.incompatible") - private static Throwable createThrowable(Class throwableClazz, @Nullable String message) - throws Exception { - return (Throwable) throwableClazz.getConstructor(String.class).newInstance(message); - } - - // Creates a new {@link RemoteException} with possibly {@code null} message. - @SuppressWarnings("nullness:argument.type.incompatible") - private static RemoteException createRemoteException(@Nullable String message) { - return new RemoteException(message); - } - - private static String keyForField(@FieldNumber int field) { - return Integer.toString(field, Character.MAX_RADIX); - } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java index c98e78e1593..cd4d855f1ec 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java @@ -62,7 +62,7 @@ * An extensible media player that plays {@link MediaSource}s. Instances can be obtained from {@link * SimpleExoPlayer.Builder}. * - *

        Player components

        + *

        Player components

        * *

        ExoPlayer is designed to make few assumptions about (and hence impose few restrictions on) the * type of the media being played, how and where it is stored, and how it is rendered. Rather than @@ -106,7 +106,7 @@ * {@link DataSource} factories to be injected via their constructors. By providing a custom factory * it's possible to load data from a non-standard source, or through a different network stack. * - *

        Threading model

        + *

        Threading model

        * *

        The figure below shows ExoPlayer's threading model. * @@ -828,6 +828,8 @@ public ExoPlayer build() { analyticsCollector, useLazyPreparation, seekParameters, + C.DEFAULT_SEEK_BACK_INCREMENT_MS, + C.DEFAULT_SEEK_FORWARD_INCREMENT_MS, livePlaybackSpeedControl, releaseTimeoutMs, pauseAtEndOfMediaItems, @@ -843,6 +845,13 @@ public ExoPlayer build() { } } + /** + * Equivalent to {@link Player#getPlayerError()}, except the exception is guaranteed to be an + * {@link ExoPlaybackException}. + */ + @Override + ExoPlaybackException getPlayerError(); + /** Returns the component of this player for audio output, or null if audio is not supported. */ @Nullable AudioComponent getAudioComponent(); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java index 8ee7cf86876..85723c4deea 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java @@ -88,6 +88,8 @@ @Nullable private final AnalyticsCollector analyticsCollector; private final Looper applicationLooper; private final BandwidthMeter bandwidthMeter; + private final long seekBackIncrementMs; + private final long seekForwardIncrementMs; private final Clock clock; @RepeatMode private int repeatMode; @@ -102,6 +104,7 @@ private boolean pauseAtEndOfMediaItems; private Commands availableCommands; private MediaMetadata mediaMetadata; + private MediaMetadata playlistMetadata; // Playback information when there is no pending seek/set source operation. private PlaybackInfo playbackInfo; @@ -124,6 +127,8 @@ * loads and other initial preparation steps happen immediately. If true, these initial * preparations are triggered only when the player starts buffering the media. * @param seekParameters The {@link SeekParameters}. + * @param seekBackIncrementMs The {@link #seekBack()} increment in milliseconds. + * @param seekForwardIncrementMs The {@link #seekForward()} increment in milliseconds. * @param livePlaybackSpeedControl The {@link LivePlaybackSpeedControl}. * @param releaseTimeoutMs The timeout for calls to {@link #release()} in milliseconds. * @param pauseAtEndOfMediaItems Whether to pause playback at the end of each media item. @@ -145,6 +150,8 @@ public ExoPlayerImpl( @Nullable AnalyticsCollector analyticsCollector, boolean useLazyPreparation, SeekParameters seekParameters, + long seekBackIncrementMs, + long seekForwardIncrementMs, LivePlaybackSpeedControl livePlaybackSpeedControl, long releaseTimeoutMs, boolean pauseAtEndOfMediaItems, @@ -169,6 +176,8 @@ public ExoPlayerImpl( this.analyticsCollector = analyticsCollector; this.useLazyPreparation = useLazyPreparation; this.seekParameters = seekParameters; + this.seekBackIncrementMs = seekBackIncrementMs; + this.seekForwardIncrementMs = seekForwardIncrementMs; this.pauseAtEndOfMediaItems = pauseAtEndOfMediaItems; this.applicationLooper = applicationLooper; this.clock = clock; @@ -197,8 +206,9 @@ public ExoPlayerImpl( COMMAND_SET_SHUFFLE_MODE, COMMAND_SET_REPEAT_MODE, COMMAND_GET_CURRENT_MEDIA_ITEM, - COMMAND_GET_MEDIA_ITEMS, + COMMAND_GET_TIMELINE, COMMAND_GET_MEDIA_ITEMS_METADATA, + COMMAND_SET_MEDIA_ITEMS_METADATA, COMMAND_CHANGE_MEDIA_ITEMS) .addAll(additionalPermanentAvailableCommands) .build(); @@ -206,9 +216,10 @@ public ExoPlayerImpl( new Commands.Builder() .addAll(permanentAvailableCommands) .add(COMMAND_SEEK_TO_DEFAULT_POSITION) - .add(COMMAND_SEEK_TO_MEDIA_ITEM) + .add(COMMAND_SEEK_TO_WINDOW) .build(); mediaMetadata = MediaMetadata.EMPTY; + playlistMetadata = MediaMetadata.EMPTY; maskingWindowIndex = C.INDEX_UNSET; playbackInfoUpdateHandler = clock.createHandler(applicationLooper, /* callback= */ null); playbackInfoUpdateListener = @@ -709,6 +720,21 @@ public void seekTo(int windowIndex, long positionMs) { oldMaskingWindowIndex); } + @Override + public long getSeekBackIncrement() { + return seekBackIncrementMs; + } + + @Override + public long getSeekForwardIncrement() { + return seekForwardIncrementMs; + } + + @Override + public int getMaxSeekToPreviousPosition() { + return C.DEFAULT_MAX_SEEK_TO_PREVIOUS_POSITION_MS; + } + @Override public void setPlaybackParameters(PlaybackParameters playbackParameters) { if (playbackParameters == null) { @@ -760,9 +786,9 @@ public void setForegroundMode(boolean foregroundMode) { // One of the renderers timed out releasing its resources. stop( /* reset= */ false, - ExoPlaybackException.createForRenderer( - new ExoTimeoutException( - ExoTimeoutException.TIMEOUT_OPERATION_SET_FOREGROUND_MODE))); + ExoPlaybackException.createForUnexpected( + new ExoTimeoutException(ExoTimeoutException.TIMEOUT_OPERATION_SET_FOREGROUND_MODE), + PlaybackException.ERROR_CODE_TIMEOUT)); } } } @@ -829,8 +855,9 @@ public void release() { Player.EVENT_PLAYER_ERROR, listener -> listener.onPlayerError( - ExoPlaybackException.createForRenderer( - new ExoTimeoutException(ExoTimeoutException.TIMEOUT_OPERATION_RELEASE)))); + ExoPlaybackException.createForUnexpected( + new ExoTimeoutException(ExoTimeoutException.TIMEOUT_OPERATION_RELEASE), + PlaybackException.ERROR_CODE_TIMEOUT))); } listeners.release(); playbackInfoUpdateHandler.removeCallbacksAndMessages(null); @@ -977,6 +1004,7 @@ public TrackSelectionArray getCurrentTrackSelections() { return new TrackSelectionArray(playbackInfo.trackSelectorResult.selections); } + @Deprecated @Override public List getCurrentStaticMetadata() { return playbackInfo.staticMetadata; @@ -998,6 +1026,23 @@ public void onMetadata(Metadata metadata) { EVENT_MEDIA_METADATA_CHANGED, listener -> listener.onMediaMetadataChanged(mediaMetadata)); } + @Override + public MediaMetadata getPlaylistMetadata() { + return playlistMetadata; + } + + @Override + public void setPlaylistMetadata(MediaMetadata playlistMetadata) { + checkNotNull(playlistMetadata); + if (playlistMetadata.equals(this.playlistMetadata)) { + return; + } + this.playlistMetadata = playlistMetadata; + listeners.sendEvent( + EVENT_PLAYLIST_METADATA_CHANGED, + listener -> listener.onPlaylistMetadataChanged(this.playlistMetadata)); + } + @Override public Timeline getCurrentTimeline() { return playbackInfo.timeline; @@ -1220,7 +1265,7 @@ private void updatePlaybackInfo( .windowIndex; mediaItem = newPlaybackInfo.timeline.getWindow(windowIndex, window).mediaItem; } - mediaMetadata = mediaItem != null ? mediaItem.mediaMetadata : MediaMetadata.EMPTY; + newMediaMetadata = mediaItem != null ? mediaItem.mediaMetadata : MediaMetadata.EMPTY; } if (!previousPlaybackInfo.staticMetadata.equals(newPlaybackInfo.staticMetadata)) { newMediaMetadata = @@ -1232,16 +1277,7 @@ private void updatePlaybackInfo( if (!previousPlaybackInfo.timeline.equals(newPlaybackInfo.timeline)) { listeners.queueEvent( Player.EVENT_TIMELINE_CHANGED, - listener -> { - @Nullable Object manifest = null; - if (newPlaybackInfo.timeline.getWindowCount() == 1) { - // Legacy behavior was to report the manifest for single window timelines only. - Timeline.Window window = new Timeline.Window(); - manifest = newPlaybackInfo.timeline.getWindow(0, window).manifest; - } - listener.onTimelineChanged(newPlaybackInfo.timeline, manifest, timelineChangeReason); - listener.onTimelineChanged(newPlaybackInfo.timeline, timelineChangeReason); - }); + listener -> listener.onTimelineChanged(newPlaybackInfo.timeline, timelineChangeReason)); } if (positionDiscontinuity) { PositionInfo previousPositionInfo = @@ -1262,11 +1298,15 @@ private void updatePlaybackInfo( Player.EVENT_MEDIA_ITEM_TRANSITION, listener -> listener.onMediaItemTransition(finalMediaItem, mediaItemTransitionReason)); } - if (previousPlaybackInfo.playbackError != newPlaybackInfo.playbackError - && newPlaybackInfo.playbackError != null) { + if (previousPlaybackInfo.playbackError != newPlaybackInfo.playbackError) { listeners.queueEvent( Player.EVENT_PLAYER_ERROR, - listener -> listener.onPlayerError(newPlaybackInfo.playbackError)); + listener -> listener.onPlayerErrorChanged(newPlaybackInfo.playbackError)); + if (newPlaybackInfo.playbackError != null) { + listeners.queueEvent( + Player.EVENT_PLAYER_ERROR, + listener -> listener.onPlayerError(newPlaybackInfo.playbackError)); + } } if (previousPlaybackInfo.trackSelectorResult != newPlaybackInfo.trackSelectorResult) { trackSelector.onSelectionActivated(newPlaybackInfo.trackSelectorResult.info); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java index 116cb7d19fd..a497f20b095 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java @@ -29,12 +29,15 @@ import androidx.annotation.CheckResult; import androidx.annotation.Nullable; import com.google.android.exoplayer2.DefaultMediaClock.PlaybackParametersListener; +import com.google.android.exoplayer2.PlaybackException.ErrorCode; import com.google.android.exoplayer2.Player.DiscontinuityReason; import com.google.android.exoplayer2.Player.PlayWhenReadyChangeReason; import com.google.android.exoplayer2.Player.PlaybackSuppressionReason; import com.google.android.exoplayer2.Player.RepeatMode; import com.google.android.exoplayer2.analytics.AnalyticsCollector; +import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.metadata.Metadata; +import com.google.android.exoplayer2.source.BehindLiveWindowException; import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.source.SampleStream; @@ -45,6 +48,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelector; import com.google.android.exoplayer2.trackselection.TrackSelectorResult; import com.google.android.exoplayer2.upstream.BandwidthMeter; +import com.google.android.exoplayer2.upstream.DataSourceException; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Clock; import com.google.android.exoplayer2.util.HandlerWrapper; @@ -545,7 +549,6 @@ public boolean handleMessage(Message msg) { default: return false; } - maybeNotifyPlaybackInfoChanged(); } catch (ExoPlaybackException e) { if (e.type == ExoPlaybackException.TYPE_RENDERER) { @Nullable MediaPeriodHolder readingPeriod = queue.getReadingPeriod(); @@ -571,30 +574,60 @@ public boolean handleMessage(Message msg) { stopInternal(/* forceResetRenderers= */ true, /* acknowledgeStop= */ false); playbackInfo = playbackInfo.copyWithPlaybackError(e); } - maybeNotifyPlaybackInfoChanged(); - } catch (IOException e) { - ExoPlaybackException error = ExoPlaybackException.createForSource(e); - @Nullable MediaPeriodHolder playingPeriod = queue.getPlayingPeriod(); - if (playingPeriod != null) { - // We ensure that all IOException throwing methods are only executed for the playing period. - error = error.copyWithMediaPeriodId(playingPeriod.info.id); + } catch (DrmSession.DrmSessionException e) { + handleIoException(e, e.errorCode); + } catch (ParserException e) { + @ErrorCode int errorCode; + if (e.dataType == C.DATA_TYPE_MEDIA) { + errorCode = + e.contentIsMalformed + ? PlaybackException.ERROR_CODE_PARSING_CONTAINER_MALFORMED + : PlaybackException.ERROR_CODE_PARSING_CONTAINER_UNSUPPORTED; + } else if (e.dataType == C.DATA_TYPE_MANIFEST) { + errorCode = + e.contentIsMalformed + ? PlaybackException.ERROR_CODE_PARSING_MANIFEST_MALFORMED + : PlaybackException.ERROR_CODE_PARSING_MANIFEST_UNSUPPORTED; + } else { + errorCode = PlaybackException.ERROR_CODE_UNSPECIFIED; } - Log.e(TAG, "Playback error", error); - stopInternal(/* forceResetRenderers= */ false, /* acknowledgeStop= */ false); - playbackInfo = playbackInfo.copyWithPlaybackError(error); - maybeNotifyPlaybackInfoChanged(); + handleIoException(e, errorCode); + } catch (DataSourceException e) { + handleIoException(e, e.reason); + } catch (BehindLiveWindowException e) { + handleIoException(e, PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW); + } catch (IOException e) { + handleIoException(e, PlaybackException.ERROR_CODE_IO_UNSPECIFIED); } catch (RuntimeException e) { - ExoPlaybackException error = ExoPlaybackException.createForUnexpected(e); + @ErrorCode int errorCode; + if (e instanceof IllegalStateException || e instanceof IllegalArgumentException) { + errorCode = PlaybackException.ERROR_CODE_FAILED_RUNTIME_CHECK; + } else { + errorCode = PlaybackException.ERROR_CODE_UNSPECIFIED; + } + ExoPlaybackException error = ExoPlaybackException.createForUnexpected(e, errorCode); Log.e(TAG, "Playback error", error); stopInternal(/* forceResetRenderers= */ true, /* acknowledgeStop= */ false); playbackInfo = playbackInfo.copyWithPlaybackError(error); - maybeNotifyPlaybackInfoChanged(); } + maybeNotifyPlaybackInfoChanged(); return true; } // Private methods. + private void handleIoException(IOException e, @ErrorCode int errorCode) { + ExoPlaybackException error = ExoPlaybackException.createForSource(e, errorCode); + @Nullable MediaPeriodHolder playingPeriod = queue.getPlayingPeriod(); + if (playingPeriod != null) { + // We ensure that all IOException throwing methods are only executed for the playing period. + error = error.copyWithMediaPeriodId(playingPeriod.info.id); + } + Log.e(TAG, "Playback error", error); + stopInternal(/* forceResetRenderers= */ false, /* acknowledgeStop= */ false); + playbackInfo = playbackInfo.copyWithPlaybackError(error); + } + /** * Blocks the current thread until a condition becomes true or the specified amount of time has * elapsed. @@ -1369,7 +1402,7 @@ private void resetInternal( MediaPeriodId mediaPeriodId = playbackInfo.periodId; long startPositionUs = playbackInfo.positionUs; long requestedContentPositionUs = - shouldUseRequestedContentPosition(playbackInfo, period) + playbackInfo.periodId.isAd() || isUsingPlaceholderPeriod(playbackInfo, period) ? playbackInfo.requestedContentPositionUs : playbackInfo.positionUs; boolean resetTrackInfo = false; @@ -1799,6 +1832,7 @@ timeline, rendererPositionUs, getMaxRendererReadPositionUs())) { // Update the new playing media period info if it already exists. if (periodHolder.info.id.equals(newPeriodId)) { periodHolder.info = queue.getUpdatedMediaPeriodInfo(timeline, periodHolder.info); + periodHolder.updateClipping(); } periodHolder = periodHolder.getNext(); } @@ -2127,7 +2161,9 @@ private boolean hasReadingPeriodFinishedReading() { Renderer renderer = renderers[i]; SampleStream sampleStream = readingPeriodHolder.sampleStreams[i]; if (renderer.getStream() != sampleStream - || (sampleStream != null && !renderer.hasReadStreamToEnd())) { + || (sampleStream != null + && !renderer.hasReadStreamToEnd() + && !hasReachedServerSideInsertedAdsTransition(renderer, readingPeriodHolder))) { // The current reading period is still being read by at least one renderer. return false; } @@ -2135,6 +2171,20 @@ private boolean hasReadingPeriodFinishedReading() { return true; } + private boolean hasReachedServerSideInsertedAdsTransition( + Renderer renderer, MediaPeriodHolder reading) { + MediaPeriodHolder nextPeriod = reading.getNext(); + // We can advance the reading period early once we read beyond the transition point in a + // server-side inserted ads stream because we know the samples are read from the same underlying + // stream. This shortcut is helpful in case the transition point moved and renderers already + // read beyond the new transition point. But wait until the next period is actually prepared to + // allow a seamless transition. + return reading.info.isFollowedByTransitionToSameStream + && nextPeriod.prepared + && (renderer instanceof TextRenderer // [internal: b/181312195] + || renderer.getReadingPositionUs() >= nextPeriod.getStartPositionRendererTime()); + } + private void setAllRendererStreamsFinal(long streamEndPositionUs) { for (Renderer renderer : renderers) { if (renderer.getStream() != null) { @@ -2475,10 +2525,9 @@ private static PositionUpdateForPlaylistChange resolvePositionForPlaylistChange( } MediaPeriodId oldPeriodId = playbackInfo.periodId; Object newPeriodUid = oldPeriodId.periodUid; - boolean shouldUseRequestedContentPosition = - shouldUseRequestedContentPosition(playbackInfo, period); + boolean isUsingPlaceholderPeriod = isUsingPlaceholderPeriod(playbackInfo, period); long oldContentPositionUs = - shouldUseRequestedContentPosition + playbackInfo.periodId.isAd() || isUsingPlaceholderPeriod ? playbackInfo.requestedContentPositionUs : playbackInfo.positionUs; long newContentPositionUs = oldContentPositionUs; @@ -2541,28 +2590,27 @@ private static PositionUpdateForPlaylistChange resolvePositionForPlaylistChange( startAtDefaultPositionWindowIndex = timeline.getPeriodByUid(subsequentPeriodUid, period).windowIndex; } - } else if (shouldUseRequestedContentPosition) { - // We previously requested a content position, but haven't used it yet. Re-resolve the - // requested window position to the period uid and position in case they changed. - if (oldContentPositionUs == C.TIME_UNSET) { - startAtDefaultPositionWindowIndex = - timeline.getPeriodByUid(newPeriodUid, period).windowIndex; - } else { - playbackInfo.timeline.getPeriodByUid(oldPeriodId.periodUid, period); - if (playbackInfo.timeline.getWindow(period.windowIndex, window).firstPeriodIndex - == playbackInfo.timeline.getIndexOfPeriod(oldPeriodId.periodUid)) { - // Only need to resolve the first period in a window because subsequent periods must start - // at position 0 and don't need to be resolved. - long windowPositionUs = oldContentPositionUs + period.getPositionInWindowUs(); - int windowIndex = timeline.getPeriodByUid(newPeriodUid, period).windowIndex; - Pair periodPosition = - timeline.getPeriodPosition(window, period, windowIndex, windowPositionUs); - newPeriodUid = periodPosition.first; - newContentPositionUs = periodPosition.second; - } - // Use an explicitly requested content position as new target live offset. - setTargetLiveOffset = true; - } + } else if (oldContentPositionUs == C.TIME_UNSET) { + // The content was requested to start from its default position and we haven't used the + // resolved position yet. Re-resolve in case the default position changed. + startAtDefaultPositionWindowIndex = timeline.getPeriodByUid(newPeriodUid, period).windowIndex; + } else if (isUsingPlaceholderPeriod) { + // We previously requested a content position for a placeholder period, but haven't used it + // yet. Re-resolve the requested window position to the period position in case it changed. + playbackInfo.timeline.getPeriodByUid(oldPeriodId.periodUid, period); + if (playbackInfo.timeline.getWindow(period.windowIndex, window).firstPeriodIndex + == playbackInfo.timeline.getIndexOfPeriod(oldPeriodId.periodUid)) { + // Only need to resolve the first period in a window because subsequent periods must start + // at position 0 and don't need to be resolved. + long windowPositionUs = oldContentPositionUs + period.getPositionInWindowUs(); + int windowIndex = timeline.getPeriodByUid(newPeriodUid, period).windowIndex; + Pair periodPosition = + timeline.getPeriodPosition(window, period, windowIndex, windowPositionUs); + newPeriodUid = periodPosition.first; + newContentPositionUs = periodPosition.second; + } + // Use an explicitly requested content position as new target live offset. + setTargetLiveOffset = true; } // Set period uid for default positions and resolve position for ad resolution. @@ -2589,12 +2637,25 @@ private static PositionUpdateForPlaylistChange resolvePositionForPlaylistChange( // Drop update if we keep playing the same content (MediaPeriod.periodUid are identical) and // the only change is that MediaPeriodId.nextAdGroupIndex increased. This postpones a potential // discontinuity until we reach the former next ad group position. - boolean oldAndNewPeriodIdAreSame = - oldPeriodId.periodUid.equals(newPeriodUid) + boolean sameOldAndNewPeriodUid = oldPeriodId.periodUid.equals(newPeriodUid); + boolean onlyNextAdGroupIndexIncreased = + sameOldAndNewPeriodUid && !oldPeriodId.isAd() && !periodIdWithAds.isAd() && earliestCuePointIsUnchangedOrLater; - MediaPeriodId newPeriodId = oldAndNewPeriodIdAreSame ? oldPeriodId : periodIdWithAds; + // Drop update if the change is from/to server-side inserted ads at the same content position to + // avoid any unintentional renderer reset. + timeline.getPeriodByUid(newPeriodUid, period); + boolean isInStreamAdChange = + sameOldAndNewPeriodUid + && !isUsingPlaceholderPeriod + && oldContentPositionUs == newContentPositionUs + && ((periodIdWithAds.isAd() + && period.isServerSideInsertedAdGroup(periodIdWithAds.adGroupIndex)) + || (oldPeriodId.isAd() + && period.isServerSideInsertedAdGroup(oldPeriodId.adGroupIndex))); + MediaPeriodId newPeriodId = + onlyNextAdGroupIndexIncreased || isInStreamAdChange ? oldPeriodId : periodIdWithAds; long periodPositionUs = contentPositionForAdResolutionUs; if (newPeriodId.isAd()) { @@ -2618,15 +2679,11 @@ private static PositionUpdateForPlaylistChange resolvePositionForPlaylistChange( setTargetLiveOffset); } - private static boolean shouldUseRequestedContentPosition( + private static boolean isUsingPlaceholderPeriod( PlaybackInfo playbackInfo, Timeline.Period period) { - // Only use the actual position as content position if it's not an ad and we already have - // prepared media information. Otherwise use the requested position. MediaPeriodId periodId = playbackInfo.periodId; Timeline timeline = playbackInfo.timeline; - return periodId.isAd() - || timeline.isEmpty() - || timeline.getPeriodByUid(periodId.periodUid, period).isPlaceholder; + return timeline.isEmpty() || timeline.getPeriodByUid(periodId.periodUid, period).isPlaceholder; } /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoTimeoutException.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoTimeoutException.java index c35f6fa95e6..dbc86bdb3d3 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoTimeoutException.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoTimeoutException.java @@ -21,7 +21,7 @@ import java.lang.annotation.RetentionPolicy; /** A timeout of an operation on the ExoPlayer playback thread. */ -public final class ExoTimeoutException extends Exception { +public final class ExoTimeoutException extends RuntimeException { /** * The operation which produced the timeout error. One of {@link #TIMEOUT_OPERATION_RELEASE}, diff --git a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodHolder.java b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodHolder.java index d8569a544dc..2e0d193ee3e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodHolder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodHolder.java @@ -320,7 +320,7 @@ public long applyTrackSelection( /** Releases the media period. No other method should be called after the release. */ public void release() { disableTrackSelectionsInResult(); - releaseMediaPeriod(info.endPositionUs, mediaSourceList, mediaPeriod); + releaseMediaPeriod(mediaSourceList, mediaPeriod); } /** @@ -357,6 +357,15 @@ public TrackSelectorResult getTrackSelectorResult() { return trackSelectorResult; } + /** Updates the clipping to {@link MediaPeriodInfo#endPositionUs} if required. */ + public void updateClipping() { + if (mediaPeriod instanceof ClippingMediaPeriod) { + long endPositionUs = + info.endPositionUs == C.TIME_UNSET ? C.TIME_END_OF_SOURCE : info.endPositionUs; + ((ClippingMediaPeriod) mediaPeriod).updateClipping(/* startUs= */ 0, endPositionUs); + } + } + private void enableTrackSelectionsInResult() { if (!isLoadingMediaPeriod()) { return; @@ -422,7 +431,7 @@ private static MediaPeriod createMediaPeriod( long startPositionUs, long endPositionUs) { MediaPeriod mediaPeriod = mediaSourceList.createPeriod(id, allocator, startPositionUs); - if (endPositionUs != C.TIME_UNSET && endPositionUs != C.TIME_END_OF_SOURCE) { + if (endPositionUs != C.TIME_UNSET) { mediaPeriod = new ClippingMediaPeriod( mediaPeriod, /* enableInitialDiscontinuity= */ true, /* startUs= */ 0, endPositionUs); @@ -431,10 +440,9 @@ private static MediaPeriod createMediaPeriod( } /** Releases the given {@code mediaPeriod}, logging and suppressing any errors. */ - private static void releaseMediaPeriod( - long endPositionUs, MediaSourceList mediaSourceList, MediaPeriod mediaPeriod) { + private static void releaseMediaPeriod(MediaSourceList mediaSourceList, MediaPeriod mediaPeriod) { try { - if (endPositionUs != C.TIME_UNSET && endPositionUs != C.TIME_END_OF_SOURCE) { + if (mediaPeriod instanceof ClippingMediaPeriod) { mediaSourceList.releasePeriod(((ClippingMediaPeriod) mediaPeriod).mediaPeriod); } else { mediaSourceList.releasePeriod(mediaPeriod); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodInfo.java b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodInfo.java index b14af5e1de9..aa9455fcbef 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodInfo.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodInfo.java @@ -18,6 +18,7 @@ import androidx.annotation.Nullable; import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; +import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Util; /** Stores the information required to load and play a {@link MediaPeriod}. */ @@ -48,6 +49,12 @@ * known. */ public final long durationUs; + /** + * Whether this media period is followed by a transition to another media period of the same + * server-side inserted ad stream. If true, {@link #isLastInTimelinePeriod}, {@link + * #isLastInTimelineWindow} and {@link #isFinal} will all be false. + */ + public final boolean isFollowedByTransitionToSameStream; /** * Whether this is the last media period in its timeline period (e.g., a postroll ad, or a media * period corresponding to a timeline period without ads). @@ -67,14 +74,21 @@ long requestedContentPositionUs, long endPositionUs, long durationUs, + boolean isFollowedByTransitionToSameStream, boolean isLastInTimelinePeriod, boolean isLastInTimelineWindow, boolean isFinal) { + Assertions.checkArgument(!isFinal || isLastInTimelinePeriod); + Assertions.checkArgument(!isLastInTimelineWindow || isLastInTimelinePeriod); + Assertions.checkArgument( + !isFollowedByTransitionToSameStream + || (!isLastInTimelinePeriod && !isLastInTimelineWindow && !isFinal)); this.id = id; this.startPositionUs = startPositionUs; this.requestedContentPositionUs = requestedContentPositionUs; this.endPositionUs = endPositionUs; this.durationUs = durationUs; + this.isFollowedByTransitionToSameStream = isFollowedByTransitionToSameStream; this.isLastInTimelinePeriod = isLastInTimelinePeriod; this.isLastInTimelineWindow = isLastInTimelineWindow; this.isFinal = isFinal; @@ -93,6 +107,7 @@ public MediaPeriodInfo copyWithStartPositionUs(long startPositionUs) { requestedContentPositionUs, endPositionUs, durationUs, + isFollowedByTransitionToSameStream, isLastInTimelinePeriod, isLastInTimelineWindow, isFinal); @@ -111,6 +126,7 @@ public MediaPeriodInfo copyWithRequestedContentPositionUs(long requestedContentP requestedContentPositionUs, endPositionUs, durationUs, + isFollowedByTransitionToSameStream, isLastInTimelinePeriod, isLastInTimelineWindow, isFinal); @@ -129,6 +145,7 @@ public boolean equals(@Nullable Object o) { && requestedContentPositionUs == that.requestedContentPositionUs && endPositionUs == that.endPositionUs && durationUs == that.durationUs + && isFollowedByTransitionToSameStream == that.isFollowedByTransitionToSameStream && isLastInTimelinePeriod == that.isLastInTimelinePeriod && isLastInTimelineWindow == that.isLastInTimelineWindow && isFinal == that.isFinal @@ -143,6 +160,7 @@ public int hashCode() { result = 31 * result + (int) requestedContentPositionUs; result = 31 * result + (int) endPositionUs; result = 31 * result + (int) durationUs; + result = 31 * result + (isFollowedByTransitionToSameStream ? 1 : 0); result = 31 * result + (isLastInTimelinePeriod ? 1 : 0); result = 31 * result + (isLastInTimelineWindow ? 1 : 0); result = 31 * result + (isFinal ? 1 : 0); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java index d72eaa15dbe..18b258d7792 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java @@ -351,12 +351,14 @@ public boolean updateQueuedPeriods( if (!areDurationsCompatible(oldPeriodInfo.durationUs, newPeriodInfo.durationUs)) { // The period duration changed. Remove all subsequent periods and check whether we read // beyond the new duration. + periodHolder.updateClipping(); long newDurationInRendererTime = newPeriodInfo.durationUs == C.TIME_UNSET ? Long.MAX_VALUE : periodHolder.toRendererTime(newPeriodInfo.durationUs); boolean isReadingAndReadBeyondNewDuration = periodHolder == reading + && !periodHolder.info.isFollowedByTransitionToSameStream && (maxRendererReadPositionUs == C.TIME_END_OF_SOURCE || maxRendererReadPositionUs >= newDurationInRendererTime); boolean readingPeriodRemoved = removeAfter(periodHolder); @@ -384,18 +386,28 @@ public MediaPeriodInfo getUpdatedMediaPeriodInfo(Timeline timeline, MediaPeriodI boolean isLastInWindow = isLastInWindow(timeline, id); boolean isLastInTimeline = isLastInTimeline(timeline, id, isLastInPeriod); timeline.getPeriodByUid(info.id.periodUid, period); + long endPositionUs = + id.isAd() || id.nextAdGroupIndex == C.INDEX_UNSET + ? C.TIME_UNSET + : period.getAdGroupTimeUs(id.nextAdGroupIndex); long durationUs = id.isAd() ? period.getAdDurationUs(id.adGroupIndex, id.adIndexInAdGroup) - : (info.endPositionUs == C.TIME_UNSET || info.endPositionUs == C.TIME_END_OF_SOURCE + : (endPositionUs == C.TIME_UNSET || endPositionUs == C.TIME_END_OF_SOURCE ? period.getDurationUs() - : info.endPositionUs); + : endPositionUs); + boolean isFollowedByTransitionToSameStream = + id.isAd() + ? period.isServerSideInsertedAdGroup(id.adGroupIndex) + : (id.nextAdGroupIndex != C.INDEX_UNSET + && period.isServerSideInsertedAdGroup(id.nextAdGroupIndex)); return new MediaPeriodInfo( id, info.startPositionUs, info.requestedContentPositionUs, - info.endPositionUs, + endPositionUs, durationUs, + isFollowedByTransitionToSameStream, isLastInPeriod, isLastInWindow, isLastInTimeline); @@ -698,10 +710,13 @@ private MediaPeriodInfo getFollowingMediaPeriodInfo( } startPositionUs = defaultPosition.second; } + long minStartPositionUs = + getMinStartPositionAfterAdGroupUs( + timeline, currentPeriodId.periodUid, currentPeriodId.adGroupIndex); return getMediaPeriodInfoForContent( timeline, currentPeriodId.periodUid, - startPositionUs, + max(minStartPositionUs, startPositionUs), mediaPeriodInfo.requestedContentPositionUs, currentPeriodId.windowSequenceNumber); } @@ -710,10 +725,13 @@ private MediaPeriodInfo getFollowingMediaPeriodInfo( int adIndexInAdGroup = period.getFirstAdIndexToPlay(currentPeriodId.nextAdGroupIndex); if (adIndexInAdGroup == period.getAdCountInAdGroup(currentPeriodId.nextAdGroupIndex)) { // The next ad group has no ads left to play. Play content from the end position instead. + long startPositionUs = + getMinStartPositionAfterAdGroupUs( + timeline, currentPeriodId.periodUid, currentPeriodId.nextAdGroupIndex); return getMediaPeriodInfoForContent( timeline, currentPeriodId.periodUid, - /* startPositionUs= */ mediaPeriodInfo.durationUs, + startPositionUs, /* requestedContentPositionUs= */ mediaPeriodInfo.durationUs, currentPeriodId.windowSequenceNumber); } @@ -766,6 +784,8 @@ private MediaPeriodInfo getMediaPeriodInfoForAd( adIndexInAdGroup == period.getFirstAdIndexToPlay(adGroupIndex) ? period.getAdResumePositionUs() : 0; + boolean isFollowedByTransitionToSameStream = + period.isServerSideInsertedAdGroup(id.adGroupIndex); if (durationUs != C.TIME_UNSET && startPositionUs >= durationUs) { // Ensure start position doesn't exceed duration. startPositionUs = max(0, durationUs - 1); @@ -776,6 +796,7 @@ private MediaPeriodInfo getMediaPeriodInfoForAd( contentPositionUs, /* endPositionUs= */ C.TIME_UNSET, durationUs, + isFollowedByTransitionToSameStream, /* isLastInTimelinePeriod= */ false, /* isLastInTimelineWindow= */ false, /* isFinal= */ false); @@ -793,6 +814,8 @@ private MediaPeriodInfo getMediaPeriodInfoForContent( boolean isLastInPeriod = isLastInPeriod(id); boolean isLastInWindow = isLastInWindow(timeline, id); boolean isLastInTimeline = isLastInTimeline(timeline, id, isLastInPeriod); + boolean isFollowedByTransitionToSameStream = + nextAdGroupIndex != C.INDEX_UNSET && period.isServerSideInsertedAdGroup(nextAdGroupIndex); long endPositionUs = nextAdGroupIndex != C.INDEX_UNSET ? period.getAdGroupTimeUs(nextAdGroupIndex) @@ -811,6 +834,7 @@ private MediaPeriodInfo getMediaPeriodInfoForContent( requestedContentPositionUs, endPositionUs, durationUs, + isFollowedByTransitionToSameStream, isLastInPeriod, isLastInWindow, isLastInTimeline); @@ -837,4 +861,14 @@ private boolean isLastInTimeline( && timeline.isLastPeriod(periodIndex, period, window, repeatMode, shuffleModeEnabled) && isLastMediaPeriodInPeriod; } + + private long getMinStartPositionAfterAdGroupUs( + Timeline timeline, Object periodUid, int adGroupIndex) { + timeline.getPeriodByUid(periodUid, period); + long startPositionUs = period.getAdGroupTimeUs(adGroupIndex); + if (startPositionUs == C.TIME_END_OF_SOURCE) { + return period.durationUs; + } + return startPositionUs + period.getContentResumeOffsetUs(adGroupIndex); + } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/NoSampleRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/NoSampleRenderer.java index f3329b8ea77..39dd1110781 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/NoSampleRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/NoSampleRenderer.java @@ -122,8 +122,7 @@ public final boolean isCurrentStreamFinal() { } @Override - public final void maybeThrowStreamError() throws IOException { - } + public final void maybeThrowStreamError() throws IOException {} @Override public final void resetPosition(long positionUs) throws ExoPlaybackException { @@ -180,7 +179,7 @@ public int supportsMixedMimeTypeAdaptation() throws ExoPlaybackException { // PlayerMessage.Target implementation. @Override - public void handleMessage(int what, @Nullable Object object) throws ExoPlaybackException { + public void handleMessage(int messageType, @Nullable Object message) throws ExoPlaybackException { // Do nothing. } @@ -188,8 +187,8 @@ public void handleMessage(int what, @Nullable Object object) throws ExoPlaybackE /** * Called when the renderer is enabled. - *

        - * The default implementation is a no-op. + * + *

        The default implementation is a no-op. * * @param joining Whether this renderer is being enabled to join an ongoing playback. * @throws ExoPlaybackException If an error occurs. @@ -200,11 +199,11 @@ protected void onEnabled(boolean joining) throws ExoPlaybackException { /** * Called when the renderer's offset has been changed. - *

        - * The default implementation is a no-op. * - * @param offsetUs The offset that should be subtracted from {@code positionUs} in - * {@link #render(long, long)} to get the playback position with respect to the media. + *

        The default implementation is a no-op. + * + * @param offsetUs The offset that should be subtracted from {@code positionUs} in {@link + * #render(long, long)} to get the playback position with respect to the media. * @throws ExoPlaybackException If an error occurs. */ protected void onRendererOffsetChanged(long offsetUs) throws ExoPlaybackException { @@ -212,11 +211,11 @@ protected void onRendererOffsetChanged(long offsetUs) throws ExoPlaybackExceptio } /** - * Called when the position is reset. This occurs when the renderer is enabled after - * {@link #onRendererOffsetChanged(long)} has been called, and also when a position - * discontinuity is encountered. - *

        - * The default implementation is a no-op. + * Called when the position is reset. This occurs when the renderer is enabled after {@link + * #onRendererOffsetChanged(long)} has been called, and also when a position discontinuity is + * encountered. + * + *

        The default implementation is a no-op. * * @param positionUs The new playback position in microseconds. * @param joining Whether this renderer is being enabled to join an ongoing playback. @@ -228,8 +227,8 @@ protected void onPositionReset(long positionUs, boolean joining) throws ExoPlayb /** * Called when the renderer is started. - *

        - * The default implementation is a no-op. + * + *

        The default implementation is a no-op. * * @throws ExoPlaybackException If an error occurs. */ @@ -248,8 +247,8 @@ protected void onStopped() { /** * Called when the renderer is disabled. - *

        - * The default implementation is a no-op. + * + *

        The default implementation is a no-op. */ protected void onDisabled() { // Do nothing. @@ -275,11 +274,8 @@ protected final RendererConfiguration getConfiguration() { return configuration; } - /** - * Returns the index of the renderer within the player. - */ + /** Returns the index of the renderer within the player. */ protected final int getIndex() { return index; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/PlaybackInfo.java b/library/core/src/main/java/com/google/android/exoplayer2/PlaybackInfo.java index 9ccc2a5a408..e525b5130db 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/PlaybackInfo.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/PlaybackInfo.java @@ -25,9 +25,7 @@ import com.google.common.collect.ImmutableList; import java.util.List; -/** - * Information about an ongoing playback. - */ +/** Information about an ongoing playback. */ /* package */ final class PlaybackInfo { /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/PlayerMessage.java b/library/core/src/main/java/com/google/android/exoplayer2/PlayerMessage.java index 57c70cd5ca7..6ff7100ad18 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/PlayerMessage.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/PlayerMessage.java @@ -35,11 +35,11 @@ public interface Target { * Handles a message delivered to the target. * * @param messageType The message type. - * @param payload The message payload. + * @param message The message payload. * @throws ExoPlaybackException If an error occurred whilst handling the message. Should only be * thrown by targets that handle messages on the playback thread. */ - void handleMessage(int messageType, @Nullable Object payload) throws ExoPlaybackException; + void handleMessage(int messageType, @Nullable Object message) throws ExoPlaybackException; } /** A sender for messages. */ @@ -245,8 +245,7 @@ public boolean getDeleteAfterDelivery() { /** * Sends the message. If the target throws an {@link ExoPlaybackException} then it is propagated - * out of the player as an error using {@link - * Player.Listener#onPlayerError(ExoPlaybackException)}. + * out of the player as an error using {@link Player.Listener#onPlayerError(PlaybackException)}. * * @return This message. * @throws IllegalStateException If this message has already been sent. diff --git a/library/core/src/main/java/com/google/android/exoplayer2/Renderer.java b/library/core/src/main/java/com/google/android/exoplayer2/Renderer.java index f84fef50041..3e1d9138298 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/Renderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/Renderer.java @@ -302,9 +302,9 @@ void enable( /** * Starts the renderer, meaning that calls to {@link #render(long, long)} will cause media to be * rendered. - *

        - * This method may be called when the renderer is in the following states: - * {@link #STATE_ENABLED}. + * + *

        This method may be called when the renderer is in the following states: {@link + * #STATE_ENABLED}. * * @throws ExoPlaybackException If an error occurs. */ @@ -332,16 +332,15 @@ void replaceStream(Format[] formats, SampleStream stream, long startPositionUs, /** * Returns whether the renderer has read the current {@link SampleStream} to the end. - *

        - * This method may be called when the renderer is in the following states: - * {@link #STATE_ENABLED}, {@link #STATE_STARTED}. + * + *

        This method may be called when the renderer is in the following states: {@link + * #STATE_ENABLED}, {@link #STATE_STARTED}. */ boolean hasReadStreamToEnd(); /** - * Returns the renderer time up to which the renderer has read samples from the current {@link - * SampleStream}, in microseconds, or {@link C#TIME_END_OF_SOURCE} if the renderer has read the - * current {@link SampleStream} to the end. + * Returns the renderer time up to which the renderer has read samples, in microseconds, or {@link + * C#TIME_END_OF_SOURCE} if the renderer has read the current {@link SampleStream} to the end. * *

        This method may be called when the renderer is in the following states: {@link * #STATE_ENABLED}, {@link #STATE_STARTED}. @@ -351,9 +350,9 @@ void replaceStream(Format[] formats, SampleStream stream, long startPositionUs, /** * Signals to the renderer that the current {@link SampleStream} will be the final one supplied * before it is next disabled or reset. - *

        - * This method may be called when the renderer is in the following states: - * {@link #STATE_ENABLED}, {@link #STATE_STARTED}. + * + *

        This method may be called when the renderer is in the following states: {@link + * #STATE_ENABLED}, {@link #STATE_STARTED}. */ void setCurrentStreamFinal(); @@ -366,9 +365,9 @@ void replaceStream(Format[] formats, SampleStream stream, long startPositionUs, /** * Throws an error that's preventing the renderer from reading from its {@link SampleStream}. Does * nothing if no such error exists. - *

        - * This method may be called when the renderer is in the following states: - * {@link #STATE_ENABLED}, {@link #STATE_STARTED}. + * + *

        This method may be called when the renderer is in the following states: {@link + * #STATE_ENABLED}, {@link #STATE_STARTED}. * * @throws IOException An error that's preventing the renderer from making progress or buffering * more data. @@ -377,12 +376,12 @@ void replaceStream(Format[] formats, SampleStream stream, long startPositionUs, /** * Signals to the renderer that a position discontinuity has occurred. - *

        - * After a position discontinuity, the renderer's {@link SampleStream} is guaranteed to provide + * + *

        After a position discontinuity, the renderer's {@link SampleStream} is guaranteed to provide * samples starting from a key frame. - *

        - * This method may be called when the renderer is in the following states: - * {@link #STATE_ENABLED}, {@link #STATE_STARTED}. + * + *

        This method may be called when the renderer is in the following states: {@link + * #STATE_ENABLED}, {@link #STATE_STARTED}. * * @param positionUs The new playback position in microseconds. * @throws ExoPlaybackException If an error occurs handling the reset. @@ -433,16 +432,16 @@ default void setPlaybackSpeed(float currentPlaybackSpeed, float targetPlaybackSp /** * Whether the renderer is able to immediately render media from the current position. - *

        - * If the renderer is in the {@link #STATE_STARTED} state then returning true indicates that the - * renderer has everything that it needs to continue playback. Returning false indicates that + * + *

        If the renderer is in the {@link #STATE_STARTED} state then returning true indicates that + * the renderer has everything that it needs to continue playback. Returning false indicates that * the player should pause until the renderer is ready. - *

        - * If the renderer is in the {@link #STATE_ENABLED} state then returning true indicates that the - * renderer is ready for playback to be started. Returning false indicates that it is not. - *

        - * This method may be called when the renderer is in the following states: - * {@link #STATE_ENABLED}, {@link #STATE_STARTED}. + * + *

        If the renderer is in the {@link #STATE_ENABLED} state then returning true indicates that + * the renderer is ready for playback to be started. Returning false indicates that it is not. + * + *

        This method may be called when the renderer is in the following states: {@link + * #STATE_ENABLED}, {@link #STATE_STARTED}. * * @return Whether the renderer is ready to render media. */ @@ -470,9 +469,9 @@ default void setPlaybackSpeed(float currentPlaybackSpeed, float targetPlaybackSp /** * Disable the renderer, transitioning it to the {@link #STATE_DISABLED} state. - *

        - * This method may be called when the renderer is in the following states: - * {@link #STATE_ENABLED}. + * + *

        This method may be called when the renderer is in the following states: {@link + * #STATE_ENABLED}. */ void disable(); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/RendererCapabilities.java b/library/core/src/main/java/com/google/android/exoplayer2/RendererCapabilities.java index dc7a8f86420..37176cb752d 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/RendererCapabilities.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/RendererCapabilities.java @@ -61,18 +61,14 @@ public interface RendererCapabilities { /** A mask to apply to {@link Capabilities} to obtain the {@link AdaptiveSupport} only. */ int ADAPTIVE_SUPPORT_MASK = 0b11000; - /** - * The {@link Renderer} can seamlessly adapt between formats. - */ + /** The {@link Renderer} can seamlessly adapt between formats. */ int ADAPTIVE_SEAMLESS = 0b10000; /** * The {@link Renderer} can adapt between formats, but may suffer a brief discontinuity * (~50-100ms) when adaptation occurs. */ int ADAPTIVE_NOT_SEAMLESS = 0b01000; - /** - * The {@link Renderer} does not support adaptation between formats. - */ + /** The {@link Renderer} does not support adaptation between formats. */ int ADAPTIVE_NOT_SUPPORTED = 0b00000; /** @@ -86,13 +82,9 @@ public interface RendererCapabilities { /** A mask to apply to {@link Capabilities} to obtain the {@link TunnelingSupport} only. */ int TUNNELING_SUPPORT_MASK = 0b100000; - /** - * The {@link Renderer} supports tunneled output. - */ + /** The {@link Renderer} supports tunneled output. */ int TUNNELING_SUPPORTED = 0b100000; - /** - * The {@link Renderer} does not support tunneled output. - */ + /** The {@link Renderer} does not support tunneled output. */ int TUNNELING_NOT_SUPPORTED = 0b000000; /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java b/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java index bac2e82c604..04ded28f2fe 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java @@ -24,6 +24,7 @@ import static com.google.android.exoplayer2.Renderer.MSG_SET_VIDEO_FRAME_METADATA_LISTENER; import static com.google.android.exoplayer2.Renderer.MSG_SET_VIDEO_OUTPUT; import static com.google.android.exoplayer2.Renderer.MSG_SET_VOLUME; +import static com.google.android.exoplayer2.util.Assertions.checkArgument; import android.content.Context; import android.graphics.Rect; @@ -38,6 +39,7 @@ import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.TextureView; +import androidx.annotation.IntRange; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.google.android.exoplayer2.analytics.AnalyticsCollector; @@ -127,6 +129,8 @@ public static final class Builder { @C.VideoScalingMode private int videoScalingMode; private boolean useLazyPreparation; private SeekParameters seekParameters; + private long seekBackIncrementMs; + private long seekForwardIncrementMs; private LivePlaybackSpeedControl livePlaybackSpeedControl; private long releaseTimeoutMs; private long detachSurfaceTimeoutMs; @@ -163,6 +167,8 @@ public static final class Builder { *

      • {@link C.VideoScalingMode}: {@link C#VIDEO_SCALING_MODE_DEFAULT} *
      • {@code useLazyPreparation}: {@code true} *
      • {@link SeekParameters}: {@link SeekParameters#DEFAULT} + *
      • {@code seekBackIncrementMs}: {@link C#DEFAULT_SEEK_BACK_INCREMENT_MS} + *
      • {@code seekForwardIncrementMs}: {@link C#DEFAULT_SEEK_FORWARD_INCREMENT_MS} *
      • {@code releaseTimeoutMs}: {@link ExoPlayer#DEFAULT_RELEASE_TIMEOUT_MS} *
      • {@code detachSurfaceTimeoutMs}: {@link #DEFAULT_DETACH_SURFACE_TIMEOUT_MS} *
      • {@code pauseAtEndOfMediaItems}: {@code false} @@ -260,6 +266,8 @@ public Builder( videoScalingMode = C.VIDEO_SCALING_MODE_DEFAULT; useLazyPreparation = true; seekParameters = SeekParameters.DEFAULT; + seekBackIncrementMs = C.DEFAULT_SEEK_BACK_INCREMENT_MS; + seekForwardIncrementMs = C.DEFAULT_SEEK_FORWARD_INCREMENT_MS; livePlaybackSpeedControl = new DefaultLivePlaybackSpeedControl.Builder().build(); clock = Clock.DEFAULT; releaseTimeoutMs = ExoPlayer.DEFAULT_RELEASE_TIMEOUT_MS; @@ -495,6 +503,36 @@ public Builder setSeekParameters(SeekParameters seekParameters) { return this; } + /** + * Sets the {@link #seekBack()} increment. + * + * @param seekBackIncrementMs The seek back increment, in milliseconds. + * @return This builder. + * @throws IllegalArgumentException If {@code seekBackIncrementMs} is non-positive. + * @throws IllegalStateException If {@link #build()} has already been called. + */ + public Builder setSeekBackIncrementMs(@IntRange(from = 1) long seekBackIncrementMs) { + checkArgument(seekBackIncrementMs > 0); + Assertions.checkState(!buildCalled); + this.seekBackIncrementMs = seekBackIncrementMs; + return this; + } + + /** + * Sets the {@link #seekForward()} increment. + * + * @param seekForwardIncrementMs The seek forward increment, in milliseconds. + * @return This builder. + * @throws IllegalArgumentException If {@code seekForwardIncrementMs} is non-positive. + * @throws IllegalStateException If {@link #build()} has already been called. + */ + public Builder setSeekForwardIncrementMs(@IntRange(from = 1) long seekForwardIncrementMs) { + checkArgument(seekForwardIncrementMs > 0); + Assertions.checkState(!buildCalled); + this.seekForwardIncrementMs = seekForwardIncrementMs; + return this; + } + /** * Sets a timeout for calls to {@link #release} and {@link #setForegroundMode}. * @@ -724,6 +762,8 @@ protected SimpleExoPlayer(Builder builder) { analyticsCollector, builder.useLazyPreparation, builder.seekParameters, + builder.seekBackIncrementMs, + builder.seekForwardIncrementMs, builder.livePlaybackSpeedControl, builder.releaseTimeoutMs, builder.pauseAtEndOfMediaItems, @@ -1263,17 +1303,17 @@ public List getCurrentCues() { @Deprecated @Override - public void addMetadataOutput(MetadataOutput listener) { + public void addMetadataOutput(MetadataOutput output) { // Don't verify application thread. We allow calls to this method from any thread. - Assertions.checkNotNull(listener); - metadataOutputs.add(listener); + Assertions.checkNotNull(output); + metadataOutputs.add(output); } @Deprecated @Override - public void removeMetadataOutput(MetadataOutput listener) { + public void removeMetadataOutput(MetadataOutput output) { // Don't verify application thread. We allow calls to this method from any thread. - metadataOutputs.remove(listener); + metadataOutputs.remove(output); } // ExoPlayer implementation @@ -1562,6 +1602,24 @@ public void seekTo(int windowIndex, long positionMs) { player.seekTo(windowIndex, positionMs); } + @Override + public long getSeekBackIncrement() { + verifyApplicationThread(); + return player.getSeekBackIncrement(); + } + + @Override + public long getSeekForwardIncrement() { + verifyApplicationThread(); + return player.getSeekForwardIncrement(); + } + + @Override + public int getMaxSeekToPreviousPosition() { + verifyApplicationThread(); + return player.getMaxSeekToPreviousPosition(); + } + @Override public void setPlaybackParameters(PlaybackParameters playbackParameters) { verifyApplicationThread(); @@ -1665,6 +1723,7 @@ public TrackSelectionArray getCurrentTrackSelections() { return player.getCurrentTrackSelections(); } + @Deprecated @Override public List getCurrentStaticMetadata() { verifyApplicationThread(); @@ -1676,6 +1735,16 @@ public MediaMetadata getMediaMetadata() { return player.getMediaMetadata(); } + @Override + public MediaMetadata getPlaylistMetadata() { + return player.getPlaylistMetadata(); + } + + @Override + public void setPlaylistMetadata(MediaMetadata mediaMetadata) { + player.setPlaylistMetadata(mediaMetadata); + } + @Override public Timeline getCurrentTimeline() { verifyApplicationThread(); @@ -1919,6 +1988,7 @@ private void setVideoOutputInternal(@Nullable Object videoOutput) { .send()); } } + boolean messageDeliveryTimedOut = false; if (this.videoOutput != null && this.videoOutput != videoOutput) { // We're replacing an output. Block to ensure that this output will not be accessed by the // renderers after this method returns. @@ -1929,11 +1999,7 @@ private void setVideoOutputInternal(@Nullable Object videoOutput) { } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (TimeoutException e) { - // One of the renderers timed out releasing its resources. - player.stop( - /* reset= */ false, - ExoPlaybackException.createForRenderer( - new ExoTimeoutException(ExoTimeoutException.TIMEOUT_OPERATION_DETACH_SURFACE))); + messageDeliveryTimedOut = true; } if (this.videoOutput == ownedSurface) { // We're replacing a surface that we are responsible for releasing. @@ -1942,6 +2008,13 @@ private void setVideoOutputInternal(@Nullable Object videoOutput) { } } this.videoOutput = videoOutput; + if (messageDeliveryTimedOut) { + player.stop( + /* reset= */ false, + ExoPlaybackException.createForUnexpected( + new ExoTimeoutException(ExoTimeoutException.TIMEOUT_OPERATION_DETACH_SURFACE), + PlaybackException.ERROR_CODE_TIMEOUT)); + } } /** @@ -2424,16 +2497,16 @@ private static final class FrameMetadataListener @Nullable private CameraMotionListener internalCameraMotionListener; @Override - public void handleMessage(int messageType, @Nullable Object payload) { + public void handleMessage(int messageType, @Nullable Object message) { switch (messageType) { case MSG_SET_VIDEO_FRAME_METADATA_LISTENER: - videoFrameMetadataListener = (VideoFrameMetadataListener) payload; + videoFrameMetadataListener = (VideoFrameMetadataListener) message; break; case MSG_SET_CAMERA_MOTION_LISTENER: - cameraMotionListener = (CameraMotionListener) payload; + cameraMotionListener = (CameraMotionListener) message; break; case MSG_SET_SPHERICAL_SURFACE_VIEW: - SphericalGLSurfaceView surfaceView = (SphericalGLSurfaceView) payload; + SphericalGLSurfaceView surfaceView = (SphericalGLSurfaceView) message; if (surfaceView == null) { internalVideoFrameMetadataListener = null; internalCameraMotionListener = null; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsCollector.java b/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsCollector.java index 5d1c0a9c2f2..00d75472026 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsCollector.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsCollector.java @@ -16,6 +16,7 @@ package com.google.android.exoplayer2.analytics; import static com.google.android.exoplayer2.util.Assertions.checkNotNull; +import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull; import android.os.Looper; import android.util.SparseArray; @@ -26,6 +27,7 @@ import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.MediaMetadata; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player.PlaybackSuppressionReason; @@ -49,6 +51,7 @@ import com.google.android.exoplayer2.upstream.BandwidthMeter; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Clock; +import com.google.android.exoplayer2.util.HandlerWrapper; import com.google.android.exoplayer2.util.ListenerSet; import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.video.VideoRendererEventListener; @@ -81,6 +84,7 @@ public class AnalyticsCollector private ListenerSet listeners; private @MonotonicNonNull Player player; + private @MonotonicNonNull HandlerWrapper handler; private boolean isSeeking; /** @@ -130,6 +134,7 @@ public void setPlayer(Player player, Looper looper) { Assertions.checkState( this.player == null || mediaPeriodQueueTracker.mediaPeriodQueue.isEmpty()); this.player = checkNotNull(player); + handler = clock.createHandler(looper, null); listeners = listeners.copy( looper, @@ -145,10 +150,13 @@ public void setPlayer(Player player, Looper looper) { public void release() { EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime(); eventTimes.put(AnalyticsListener.EVENT_PLAYER_RELEASED, eventTime); + sendEvent( + eventTime, + AnalyticsListener.EVENT_PLAYER_RELEASED, + listener -> listener.onPlayerReleased(eventTime)); // Release listeners lazily so that all events that got triggered as part of player.release() // are still delivered to all listeners. - listeners.lazyRelease( - AnalyticsListener.EVENT_PLAYER_RELEASED, listener -> listener.onPlayerReleased(eventTime)); + checkStateNotNull(handler).post(() -> listeners.release()); } /** @@ -181,21 +189,6 @@ public final void notifySeekStarted() { } } - // MetadataOutput events. - - /** - * Called when there is metadata associated with current playback time. - * - * @param metadata The metadata. - */ - public final void onMetadata(Metadata metadata) { - EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime(); - sendEvent( - eventTime, - AnalyticsListener.EVENT_METADATA, - listener -> listener.onMetadata(eventTime, metadata)); - } - // AudioRendererEventListener implementation. @SuppressWarnings("deprecation") // Calling deprecated listener method. @@ -573,9 +566,9 @@ public final void onDownstreamFormatChanged( listener -> listener.onDownstreamFormatChanged(eventTime, mediaLoadData)); } - // Player.EventListener implementation. + // Player.Listener implementation. - // TODO: Use Player.EventListener.onEvents to know when a set of simultaneous callbacks finished. + // TODO: Use Player.Listener.onEvents to know when a set of simultaneous callbacks finished. // This helps to assign exactly the same EventTime to all of them instead of having slightly // different real times. @@ -609,6 +602,7 @@ public final void onTracksChanged( listener -> listener.onTracksChanged(eventTime, trackGroups, trackSelections)); } + @Deprecated @Override public final void onStaticMetadataChanged(List metadataList) { EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime(); @@ -631,6 +625,15 @@ public final void onIsLoadingChanged(boolean isLoading) { }); } + @Override + public void onAvailableCommandsChanged(Player.Commands availableCommands) { + EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime(); + sendEvent( + eventTime, + AnalyticsListener.EVENT_AVAILABLE_COMMANDS_CHANGED, + listener -> listener.onAvailableCommandsChanged(eventTime, availableCommands)); + } + @SuppressWarnings("deprecation") // Implementing and calling deprecated listener method. @Override public final void onPlayerStateChanged(boolean playWhenReady, @Player.State int playbackState) { @@ -642,12 +645,12 @@ public final void onPlayerStateChanged(boolean playWhenReady, @Player.State int } @Override - public final void onPlaybackStateChanged(@Player.State int state) { + public final void onPlaybackStateChanged(@Player.State int playbackState) { EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime(); sendEvent( eventTime, AnalyticsListener.EVENT_PLAYBACK_STATE_CHANGED, - listener -> listener.onPlaybackStateChanged(eventTime, state)); + listener -> listener.onPlaybackStateChanged(eventTime, playbackState)); } @Override @@ -699,15 +702,22 @@ public final void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) { } @Override - public final void onPlayerError(ExoPlaybackException error) { - EventTime eventTime = - error.mediaPeriodId != null - ? generateEventTime(new MediaPeriodId(error.mediaPeriodId)) - : generateCurrentPlayerMediaPeriodEventTime(); + public final void onPlayerError(PlaybackException error) { + @Nullable EventTime eventTime = null; + if (error instanceof ExoPlaybackException) { + ExoPlaybackException exoError = (ExoPlaybackException) error; + if (exoError.mediaPeriodId != null) { + eventTime = generateEventTime(new MediaPeriodId(exoError.mediaPeriodId)); + } + } + if (eventTime == null) { + eventTime = generateCurrentPlayerMediaPeriodEventTime(); + } + EventTime finalEventTime = eventTime; sendEvent( eventTime, AnalyticsListener.EVENT_PLAYER_ERROR, - listener -> listener.onPlayerError(eventTime, error)); + listener -> listener.onPlayerError(finalEventTime, error)); } // Calling deprecated callback. @@ -740,6 +750,34 @@ public final void onPlaybackParametersChanged(PlaybackParameters playbackParamet listener -> listener.onPlaybackParametersChanged(eventTime, playbackParameters)); } + @Override + public void onSeekBackIncrementChanged(long seekBackIncrementMs) { + EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime(); + sendEvent( + eventTime, + AnalyticsListener.EVENT_SEEK_BACK_INCREMENT_CHANGED, + listener -> listener.onSeekBackIncrementChanged(eventTime, seekBackIncrementMs)); + } + + @Override + public void onSeekForwardIncrementChanged(long seekForwardIncrementMs) { + EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime(); + sendEvent( + eventTime, + AnalyticsListener.EVENT_SEEK_FORWARD_INCREMENT_CHANGED, + listener -> listener.onSeekForwardIncrementChanged(eventTime, seekForwardIncrementMs)); + } + + @Override + public void onMaxSeekToPreviousPositionChanged(int maxSeekToPreviousPositionMs) { + EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime(); + sendEvent( + eventTime, + AnalyticsListener.EVENT_MAX_SEEK_TO_PREVIOUS_POSITION_CHANGED, + listener -> + listener.onMaxSeekToPreviousPositionChanged(eventTime, maxSeekToPreviousPositionMs)); + } + @Override public void onMediaMetadataChanged(MediaMetadata mediaMetadata) { EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime(); @@ -749,6 +787,24 @@ public void onMediaMetadataChanged(MediaMetadata mediaMetadata) { listener -> listener.onMediaMetadataChanged(eventTime, mediaMetadata)); } + @Override + public void onPlaylistMetadataChanged(MediaMetadata playlistMetadata) { + EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime(); + sendEvent( + eventTime, + AnalyticsListener.EVENT_PLAYLIST_METADATA_CHANGED, + listener -> listener.onPlaylistMetadataChanged(eventTime, playlistMetadata)); + } + + @Override + public final void onMetadata(Metadata metadata) { + EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime(); + sendEvent( + eventTime, + AnalyticsListener.EVENT_METADATA, + listener -> listener.onMetadata(eventTime, metadata)); + } + @SuppressWarnings("deprecation") // Implementing and calling deprecated listener method. @Override public final void onSeekProcessed() { @@ -757,18 +813,19 @@ public final void onSeekProcessed() { eventTime, /* eventFlag= */ C.INDEX_UNSET, listener -> listener.onSeekProcessed(eventTime)); } - // BandwidthMeter.Listener implementation. + // BandwidthMeter.EventListener implementation. @Override - public final void onBandwidthSample(int elapsedMs, long bytes, long bitrate) { + public final void onBandwidthSample(int elapsedMs, long bytesTransferred, long bitrateEstimate) { EventTime eventTime = generateLoadingMediaPeriodEventTime(); sendEvent( eventTime, AnalyticsListener.EVENT_BANDWIDTH_ESTIMATE, - listener -> listener.onBandwidthEstimate(eventTime, elapsedMs, bytes, bitrate)); + listener -> + listener.onBandwidthEstimate(eventTime, elapsedMs, bytesTransferred, bitrateEstimate)); } - // DefaultDrmSessionManager.EventListener implementation. + // DrmSessionEventListener implementation. @Override @SuppressWarnings("deprecation") // Calls deprecated listener method. @@ -830,6 +887,8 @@ public final void onDrmSessionReleased(int windowIndex, @Nullable MediaPeriodId listener -> listener.onDrmSessionReleased(eventTime)); } + // Internal methods. + /** * Sends an event to registered listeners. * @@ -892,8 +951,6 @@ protected final EventTime generateEventTime( player.getTotalBufferedDuration()); } - // Internal methods. - private EventTime generateEventTime(@Nullable MediaPeriodId mediaPeriodId) { checkNotNull(player); @Nullable diff --git a/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsListener.java b/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsListener.java index 6550c5ac05b..a8c9ed38a0a 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsListener.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsListener.java @@ -26,10 +26,10 @@ import androidx.annotation.IntDef; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.MediaMetadata; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player.DiscontinuityReason; @@ -48,8 +48,9 @@ import com.google.android.exoplayer2.source.MediaLoadData; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.source.TrackGroupArray; +import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelectionArray; -import com.google.android.exoplayer2.util.ExoFlags; +import com.google.android.exoplayer2.util.FlagSet; import com.google.android.exoplayer2.video.VideoDecoderOutputBufferRenderer; import com.google.android.exoplayer2.video.VideoSize; import com.google.common.base.Objects; @@ -76,18 +77,18 @@ public interface AnalyticsListener { /** A set of {@link EventFlags}. */ final class Events { - private final ExoFlags flags; + private final FlagSet flags; private final SparseArray eventTimes; /** * Creates an instance. * - * @param flags The {@link ExoFlags} containing the {@link EventFlags} in the set. + * @param flags The {@link FlagSet} containing the {@link EventFlags} in the set. * @param eventTimes A map from {@link EventFlags} to {@link EventTime}. Must at least contain * all the events recorded in {@code flags}. Events that are not recorded in {@code flags} * are ignored. */ - public Events(ExoFlags flags, SparseArray eventTimes) { + public Events(FlagSet flags, SparseArray eventTimes) { this.flags = flags; SparseArray flagsToTimes = new SparseArray<>(/* initialCapacity= */ flags.size()); for (int i = 0; i < flags.size(); i++) { @@ -169,7 +170,11 @@ public int get(int index) { EVENT_PLAYER_ERROR, EVENT_POSITION_DISCONTINUITY, EVENT_PLAYBACK_PARAMETERS_CHANGED, + EVENT_AVAILABLE_COMMANDS_CHANGED, EVENT_MEDIA_METADATA_CHANGED, + EVENT_PLAYLIST_METADATA_CHANGED, + EVENT_SEEK_BACK_INCREMENT_CHANGED, + EVENT_SEEK_FORWARD_INCREMENT_CHANGED, EVENT_LOAD_STARTED, EVENT_LOAD_COMPLETED, EVENT_LOAD_CANCELED, @@ -221,8 +226,8 @@ public int get(int index) { * {@link Player#getCurrentTrackGroups()} or {@link Player#getCurrentTrackSelections()} changed. */ int EVENT_TRACKS_CHANGED = Player.EVENT_TRACKS_CHANGED; - /** {@link Player#getCurrentStaticMetadata()} changed. */ - int EVENT_STATIC_METADATA_CHANGED = Player.EVENT_STATIC_METADATA_CHANGED; + /** @deprecated See {@link Player#EVENT_MEDIA_METADATA_CHANGED}. */ + @Deprecated int EVENT_STATIC_METADATA_CHANGED = Player.EVENT_STATIC_METADATA_CHANGED; /** {@link Player#isLoading()} ()} changed. */ int EVENT_IS_LOADING_CHANGED = Player.EVENT_IS_LOADING_CHANGED; /** {@link Player#getPlaybackState()} changed. */ @@ -246,8 +251,19 @@ public int get(int index) { int EVENT_POSITION_DISCONTINUITY = Player.EVENT_POSITION_DISCONTINUITY; /** {@link Player#getPlaybackParameters()} changed. */ int EVENT_PLAYBACK_PARAMETERS_CHANGED = Player.EVENT_PLAYBACK_PARAMETERS_CHANGED; + /** {@link Player#getAvailableCommands()} changed. */ + int EVENT_AVAILABLE_COMMANDS_CHANGED = Player.EVENT_AVAILABLE_COMMANDS_CHANGED; /** {@link Player#getMediaMetadata()} changed. */ int EVENT_MEDIA_METADATA_CHANGED = Player.EVENT_MEDIA_METADATA_CHANGED; + /** {@link Player#getPlaylistMetadata()} changed. */ + int EVENT_PLAYLIST_METADATA_CHANGED = Player.EVENT_PLAYLIST_METADATA_CHANGED; + /** {@link Player#getSeekBackIncrement()} changed. */ + int EVENT_SEEK_BACK_INCREMENT_CHANGED = Player.EVENT_SEEK_BACK_INCREMENT_CHANGED; + /** {@link Player#getSeekForwardIncrement()} changed. */ + int EVENT_SEEK_FORWARD_INCREMENT_CHANGED = Player.EVENT_SEEK_FORWARD_INCREMENT_CHANGED; + /** {@link Player#getMaxSeekToPreviousPosition()} changed. */ + int EVENT_MAX_SEEK_TO_PREVIOUS_POSITION_CHANGED = + Player.EVENT_MAX_SEEK_TO_PREVIOUS_POSITION_CHANGED; /** A source started loading data. */ int EVENT_LOAD_STARTED = 1000; // Intentional gap to leave space for new Player events /** A source started completed loading data. */ @@ -583,6 +599,32 @@ default void onSeekProcessed(EventTime eventTime) {} default void onPlaybackParametersChanged( EventTime eventTime, PlaybackParameters playbackParameters) {} + /** + * Called when the seek back increment changed. + * + * @param eventTime The event time. + * @param seekBackIncrementMs The seek back increment, in milliseconds. + */ + default void onSeekBackIncrementChanged(EventTime eventTime, long seekBackIncrementMs) {} + + /** + * Called when the seek forward increment changed. + * + * @param eventTime The event time. + * @param seekForwardIncrementMs The seek forward increment, in milliseconds. + */ + default void onSeekForwardIncrementChanged(EventTime eventTime, long seekForwardIncrementMs) {} + + /** + * Called when the maximum position for which {@link Player#seekToPrevious()} seeks to the + * previous window changes. + * + * @param eventTime The event time. + * @param maxSeekToPreviousPositionMs The maximum seek to previous position, in milliseconds. + */ + default void onMaxSeekToPreviousPositionChanged( + EventTime eventTime, int maxSeekToPreviousPositionMs) {} + /** * Called when the repeat mode changed. * @@ -611,13 +653,24 @@ default void onIsLoadingChanged(EventTime eventTime, boolean isLoading) {} @Deprecated default void onLoadingChanged(EventTime eventTime, boolean isLoading) {} + /** + * Called when the player's available commands changed. + * + * @param eventTime The event time. + * @param availableCommands The available commands. + */ + default void onAvailableCommandsChanged(EventTime eventTime, Player.Commands availableCommands) {} + /** * Called when a fatal player error occurred. * + *

        Implementations of {@link Player} may pass an instance of a subclass of {@link + * PlaybackException} to this method in order to include more information about the error. + * * @param eventTime The event time. * @param error The error. */ - default void onPlayerError(EventTime eventTime, ExoPlaybackException error) {} + default void onPlayerError(EventTime eventTime, PlaybackException error) {} /** * Called when the available or selected tracks for the renderers changed. @@ -630,34 +683,33 @@ default void onTracksChanged( EventTime eventTime, TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {} /** - * Called when the static metadata changes. - * - *

        The provided {@code metadataList} is an immutable list of {@link Metadata} instances, where - * the elements correspond to the current track selections (as returned by {@link - * #onTracksChanged(EventTime, TrackGroupArray, TrackSelectionArray)}, or an empty list if there - * are no track selections or the selected tracks contain no static metadata. - * - *

        The metadata is considered static in the sense that it comes from the tracks' declared - * Formats, rather than being timed (or dynamic) metadata, which is represented within a metadata - * track. - * - * @param eventTime The event time. - * @param metadataList The static metadata. + * @deprecated Use {@link Player#getMediaMetadata()} and {@link #onMediaMetadataChanged(EventTime, + * MediaMetadata)} for access to structured metadata, or access the raw static metadata + * directly from the {@link TrackSelection#getFormat(int) track selections' formats}. */ + @Deprecated default void onStaticMetadataChanged(EventTime eventTime, List metadataList) {} /** * Called when the combined {@link MediaMetadata} changes. * *

        The provided {@link MediaMetadata} is a combination of the {@link MediaItem#mediaMetadata} - * and the static and dynamic metadata sourced from {@link - * Player.Listener#onStaticMetadataChanged(List)} and {@link MetadataOutput#onMetadata(Metadata)}. + * and the static and dynamic metadata from the {@link TrackSelection#getFormat(int) track + * selections' formats} and {@link MetadataOutput#onMetadata(Metadata)}. * * @param eventTime The event time. * @param mediaMetadata The combined {@link MediaMetadata}. */ default void onMediaMetadataChanged(EventTime eventTime, MediaMetadata mediaMetadata) {} + /** + * Called when the playlist {@link MediaMetadata} changes. + * + * @param eventTime The event time. + * @param playlistMetadata The playlist {@link MediaMetadata}. + */ + default void onPlaylistMetadataChanged(EventTime eventTime, MediaMetadata playlistMetadata) {} + /** * Called when a media source started loading data. * @@ -776,10 +828,10 @@ default void onDecoderDisabled( * Called when an audio renderer is enabled. * * @param eventTime The event time. - * @param counters {@link DecoderCounters} that will be updated by the renderer for as long as it - * remains enabled. + * @param decoderCounters {@link DecoderCounters} that will be updated by the renderer for as long + * as it remains enabled. */ - default void onAudioEnabled(EventTime eventTime, DecoderCounters counters) {} + default void onAudioEnabled(EventTime eventTime, DecoderCounters decoderCounters) {} /** * Called when an audio renderer creates a decoder. @@ -855,9 +907,9 @@ default void onAudioDecoderReleased(EventTime eventTime, String decoderName) {} * Called when an audio renderer is disabled. * * @param eventTime The event time. - * @param counters {@link DecoderCounters} that were updated by the renderer. + * @param decoderCounters {@link DecoderCounters} that were updated by the renderer. */ - default void onAudioDisabled(EventTime eventTime, DecoderCounters counters) {} + default void onAudioDisabled(EventTime eventTime, DecoderCounters decoderCounters) {} /** * Called when the audio session ID changes. @@ -928,10 +980,10 @@ default void onVolumeChanged(EventTime eventTime, float volume) {} * Called when a video renderer is enabled. * * @param eventTime The event time. - * @param counters {@link DecoderCounters} that will be updated by the renderer for as long as it - * remains enabled. + * @param decoderCounters {@link DecoderCounters} that will be updated by the renderer for as long + * as it remains enabled. */ - default void onVideoEnabled(EventTime eventTime, DecoderCounters counters) {} + default void onVideoEnabled(EventTime eventTime, DecoderCounters decoderCounters) {} /** * Called when a video renderer creates a decoder. @@ -996,9 +1048,9 @@ default void onVideoDecoderReleased(EventTime eventTime, String decoderName) {} * Called when a video renderer is disabled. * * @param eventTime The event time. - * @param counters {@link DecoderCounters} that were updated by the renderer. + * @param decoderCounters {@link DecoderCounters} that were updated by the renderer. */ - default void onVideoDisabled(EventTime eventTime, DecoderCounters counters) {} + default void onVideoDisabled(EventTime eventTime, DecoderCounters decoderCounters) {} /** * Called when there is an update to the video frame processing offset reported by a video diff --git a/library/core/src/main/java/com/google/android/exoplayer2/analytics/PlaybackStatsListener.java b/library/core/src/main/java/com/google/android/exoplayer2/analytics/PlaybackStatsListener.java index 2ca886a5e61..fd349ea60ca 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/analytics/PlaybackStatsListener.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/analytics/PlaybackStatsListener.java @@ -22,8 +22,8 @@ import android.util.Pair; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline.Period; @@ -147,29 +147,33 @@ public PlaybackStats getPlaybackStats() { // PlaybackSessionManager.Listener implementation. @Override - public void onSessionCreated(EventTime eventTime, String session) { + public void onSessionCreated(EventTime eventTime, String sessionId) { PlaybackStatsTracker tracker = new PlaybackStatsTracker(keepHistory, eventTime); - playbackStatsTrackers.put(session, tracker); - sessionStartEventTimes.put(session, eventTime); + playbackStatsTrackers.put(sessionId, tracker); + sessionStartEventTimes.put(sessionId, eventTime); } @Override - public void onSessionActive(EventTime eventTime, String session) { - checkNotNull(playbackStatsTrackers.get(session)).onForeground(); + public void onSessionActive(EventTime eventTime, String sessionId) { + checkNotNull(playbackStatsTrackers.get(sessionId)).onForeground(); } @Override - public void onAdPlaybackStarted(EventTime eventTime, String contentSession, String adSession) { - checkNotNull(playbackStatsTrackers.get(contentSession)).onInterruptedByAd(); + public void onAdPlaybackStarted( + EventTime eventTime, String contentSessionId, String adSessionId) { + checkNotNull(playbackStatsTrackers.get(contentSessionId)).onInterruptedByAd(); } @Override - public void onSessionFinished(EventTime eventTime, String session, boolean automaticTransition) { - PlaybackStatsTracker tracker = checkNotNull(playbackStatsTrackers.remove(session)); - EventTime startEventTime = checkNotNull(sessionStartEventTimes.remove(session)); + public void onSessionFinished( + EventTime eventTime, String sessionId, boolean automaticTransitionToNextPlayback) { + PlaybackStatsTracker tracker = checkNotNull(playbackStatsTrackers.remove(sessionId)); + EventTime startEventTime = checkNotNull(sessionStartEventTimes.remove(sessionId)); long discontinuityFromPositionMs = - session.equals(discontinuityFromSession) ? this.discontinuityFromPositionMs : C.TIME_UNSET; - tracker.onFinished(eventTime, automaticTransition, discontinuityFromPositionMs); + sessionId.equals(discontinuityFromSession) + ? this.discontinuityFromPositionMs + : C.TIME_UNSET; + tracker.onFinished(eventTime, automaticTransitionToNextPlayback, discontinuityFromPositionMs); PlaybackStats playbackStats = tracker.build(/* isFinal= */ true); finishedPlaybackStats = PlaybackStats.merge(finishedPlaybackStats, playbackStats); if (callback != null) { @@ -182,12 +186,12 @@ public void onSessionFinished(EventTime eventTime, String session, boolean autom @Override public void onPositionDiscontinuity( EventTime eventTime, - Player.PositionInfo oldPositionInfo, - Player.PositionInfo newPositionInfo, + Player.PositionInfo oldPosition, + Player.PositionInfo newPosition, @Player.DiscontinuityReason int reason) { if (discontinuityFromSession == null) { discontinuityFromSession = sessionManager.getActiveSessionId(); - discontinuityFromPositionMs = oldPositionInfo.positionMs; + discontinuityFromPositionMs = oldPosition.positionMs; } discontinuityReason = reason; } @@ -489,7 +493,7 @@ public void onEvents( int droppedFrameCount, boolean hasAudioUnderun, boolean startedLoading, - @Nullable ExoPlaybackException fatalError, + @Nullable PlaybackException fatalError, @Nullable Exception nonFatalException, long bandwidthTimeMs, long bandwidthBytes, diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioCapabilities.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioCapabilities.java index 643f91078ee..a12f63deeba 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioCapabilities.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioCapabilities.java @@ -88,9 +88,12 @@ public static AudioCapabilities getCapabilities(Context context) { && Global.getInt(context.getContentResolver(), EXTERNAL_SURROUND_SOUND_KEY, 0) == 1) { return EXTERNAL_SURROUND_SOUND_CAPABILITIES; } - if (Util.SDK_INT >= 29) { + // AudioTrack.isDirectPlaybackSupported returns true for encodings that are supported for audio + // offload, as well as for encodings we want to list for passthrough mode. Therefore we only use + // it on TV devices, which generally shouldn't support audio offload for surround encodings. + if (Util.SDK_INT >= 29 && Util.isTv(context)) { return new AudioCapabilities( - AudioTrackWrapperV29.getDirectPlaybackSupportedEncodingsV29(), DEFAULT_MAX_CHANNEL_COUNT); + Api29.getDirectPlaybackSupportedEncodingsV29(), DEFAULT_MAX_CHANNEL_COUNT); } if (intent == null || intent.getIntExtra(AudioManager.EXTRA_AUDIO_PLUG_STATE, 0) == 0) { return DEFAULT_AUDIO_CAPABILITIES; @@ -147,9 +150,7 @@ public boolean supportsEncoding(@C.Encoding int encoding) { return Arrays.binarySearch(supportedEncodings, encoding) >= 0; } - /** - * Returns the maximum number of channels the device can play at the same time. - */ + /** Returns the maximum number of channels the device can play at the same time. */ public int getMaxChannelCount() { return maxChannelCount; } @@ -174,8 +175,11 @@ public int hashCode() { @Override public String toString() { - return "AudioCapabilities[maxChannelCount=" + maxChannelCount - + ", supportedEncodings=" + Arrays.toString(supportedEncodings) + "]"; + return "AudioCapabilities[maxChannelCount=" + + maxChannelCount + + ", supportedEncodings=" + + Arrays.toString(supportedEncodings) + + "]"; } private static boolean deviceMaySetExternalSurroundSoundGlobalSetting() { @@ -184,7 +188,7 @@ private static boolean deviceMaySetExternalSurroundSoundGlobalSetting() { } @RequiresApi(29) - private static final class AudioTrackWrapperV29 { + private static final class Api29 { @DoNotInline public static int[] getDirectPlaybackSupportedEncodingsV29() { ImmutableList.Builder supportedEncodingsListBuilder = ImmutableList.builder(); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioCapabilitiesReceiver.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioCapabilitiesReceiver.java index c9c78a7422a..caed07b6ad4 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioCapabilitiesReceiver.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioCapabilitiesReceiver.java @@ -34,9 +34,7 @@ */ public final class AudioCapabilitiesReceiver { - /** - * Listener notified when audio capabilities change. - */ + /** Listener notified when audio capabilities change. */ public interface Listener { /** @@ -45,7 +43,6 @@ public interface Listener { * @param audioCapabilities The current audio capabilities for the device. */ void onAudioCapabilitiesChanged(AudioCapabilities audioCapabilities); - } private final Context context; @@ -77,8 +74,8 @@ public AudioCapabilitiesReceiver(Context context, Listener listener) { /** * Registers the receiver, meaning it will notify the listener when audio capability changes - * occur. The current audio capabilities will be returned. It is important to call - * {@link #unregister} when the receiver is no longer required. + * occur. The current audio capabilities will be returned. It is important to call {@link + * #unregister} when the receiver is no longer required. * * @return The current audio capabilities for the device. */ @@ -162,5 +159,4 @@ public void onChange(boolean selfChange) { onNewAudioCapabilities(AudioCapabilities.getCapabilities(context)); } } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioProcessor.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioProcessor.java index f75b2cd3176..e0d856e47df 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioProcessor.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioProcessor.java @@ -76,7 +76,6 @@ final class UnhandledAudioFormatException extends Exception { public UnhandledAudioFormatException(AudioFormat inputAudioFormat) { super("Unhandled format: " + inputAudioFormat); } - } /** An empty, direct {@link ByteBuffer}. */ @@ -109,16 +108,16 @@ public UnhandledAudioFormatException(AudioFormat inputAudioFormat) { * The caller retains ownership of the provided buffer. Calling this method invalidates any * previous buffer returned by {@link #getOutput()}. * - * @param buffer The input buffer to process. + * @param inputBuffer The input buffer to process. */ - void queueInput(ByteBuffer buffer); + void queueInput(ByteBuffer inputBuffer); /** - * Queues an end of stream signal. After this method has been called, - * {@link #queueInput(ByteBuffer)} may not be called until after the next call to - * {@link #flush()}. Calling {@link #getOutput()} will return any remaining output data. Multiple - * calls may be required to read all of the remaining output data. {@link #isEnded()} will return - * {@code true} once all remaining output data has been read. + * Queues an end of stream signal. After this method has been called, {@link + * #queueInput(ByteBuffer)} may not be called until after the next call to {@link #flush()}. + * Calling {@link #getOutput()} will return any remaining output data. Multiple calls may be + * required to read all of the remaining output data. {@link #isEnded()} will return {@code true} + * once all remaining output data has been read. */ void queueEndOfStream(); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioSink.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioSink.java index adf475ef351..8f38dacf5d9 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioSink.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioSink.java @@ -21,6 +21,7 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player; import java.lang.annotation.Documented; @@ -57,9 +58,7 @@ */ public interface AudioSink { - /** - * Listener for audio sink events. - */ + /** Listener for audio sink events. */ interface Listener { /** @@ -124,7 +123,7 @@ default void onOffloadBufferFull(long bufferEmptyingDeadlineMs) {} * wishes to do so. * *

        Fatal errors that cannot be recovered will be reported wrapped in a {@link - * ExoPlaybackException} by {@link Player.Listener#onPlayerError(ExoPlaybackException)}. + * ExoPlaybackException} by {@link Player.Listener#onPlayerError(PlaybackException)}. * * @param audioSinkError The error that occurred. Typically an {@link InitializationException}, * a {@link WriteException}, or an {@link UnexpectedDiscontinuityException}. @@ -132,9 +131,7 @@ default void onOffloadBufferFull(long bufferEmptyingDeadlineMs) {} default void onAudioSinkError(Exception audioSinkError) {} } - /** - * Thrown when a failure occurs configuring the sink. - */ + /** Thrown when a failure occurs configuring the sink. */ final class ConfigurationException extends Exception { /** Input {@link Format} of the sink when the configuration failure occurs. */ @@ -200,8 +197,8 @@ final class WriteException extends Exception { /** * The error value returned from the sink implementation. If the sink writes to a platform - * {@link AudioTrack}, this will be the error value returned from - * {@link AudioTrack#write(byte[], int, int)} or {@link AudioTrack#write(ByteBuffer, int, int)}. + * {@link AudioTrack}, this will be the error value returned from {@link + * AudioTrack#write(byte[], int, int)} or {@link AudioTrack#write(ByteBuffer, int, int)}. * Otherwise, the meaning of the error code depends on the sink implementation. */ public final int errorCode; @@ -223,7 +220,6 @@ public WriteException(int errorCode, Format format, boolean isRecoverable) { this.errorCode = errorCode; this.format = format; } - } /** Thrown when the sink encounters an unexpected timestamp discontinuity. */ @@ -327,9 +323,7 @@ public UnexpectedDiscontinuityException( void configure(Format inputFormat, int specifiedBufferSize, @Nullable int[] outputChannels) throws ConfigurationException; - /** - * Starts or resumes consuming audio if initialized. - */ + /** Starts or resumes consuming audio if initialized. */ void play(); /** Signals to the sink that the next buffer may be discontinuous with the previous buffer. */ @@ -370,9 +364,7 @@ boolean handleBuffer(ByteBuffer buffer, long presentationTimeUs, int encodedAcce */ boolean isEnded(); - /** - * Returns whether the sink has data pending that has not been consumed yet. - */ + /** Returns whether the sink has data pending that has not been consumed yet. */ boolean hasPendingData(); /** @@ -395,8 +387,8 @@ boolean handleBuffer(ByteBuffer buffer, long presentationTimeUs, int encodedAcce /** * Sets attributes for audio playback. If the attributes have changed and if the sink is not * configured for use with tunneling, then it is reset and the audio session id is cleared. - *

        - * If the sink is configured for use with tunneling then the audio attributes are ignored. The + * + *

        If the sink is configured for use with tunneling then the audio attributes are ignored. The * sink is not reset and the audio session id is not cleared. The passed attributes will be used * if the sink is later re-configured into non-tunneled mode. * @@ -432,9 +424,7 @@ boolean handleBuffer(ByteBuffer buffer, long presentationTimeUs, int encodedAcce */ void setVolume(float volume); - /** - * Pauses playback. - */ + /** Pauses playback. */ void pause(); /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioTrackPositionTracker.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioTrackPositionTracker.java index 8891a6d8d1e..6c26d87fcfb 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioTrackPositionTracker.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioTrackPositionTracker.java @@ -409,8 +409,7 @@ public void handleEndOfStream(long writtenFrames) { * @return Whether the audio track has any pending data to play out. */ public boolean hasPendingData(long writtenFrames) { - return writtenFrames > getPlaybackHeadPosition() - || forceHasPendingData(); + return writtenFrames > getPlaybackHeadPosition() || forceHasPendingData(); } /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/ChannelMappingAudioProcessor.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/ChannelMappingAudioProcessor.java index c064c7e4594..74c78b1af36 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/ChannelMappingAudioProcessor.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/ChannelMappingAudioProcessor.java @@ -94,5 +94,4 @@ protected void onReset() { outputChannels = null; pendingOutputChannels = null; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/DecoderAudioRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/DecoderAudioRenderer.java index 4367883df93..286efe08e1c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/DecoderAudioRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/DecoderAudioRenderer.java @@ -32,6 +32,7 @@ import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.FormatHolder; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.PlayerMessage.Target; import com.google.android.exoplayer2.RendererCapabilities; @@ -94,9 +95,7 @@ public abstract class DecoderAudioRenderer< REINITIALIZATION_STATE_WAIT_END_OF_STREAM }) private @interface ReinitializationState {} - /** - * The decoder does not need to be re-initialized. - */ + /** The decoder does not need to be re-initialized. */ private static final int REINITIALIZATION_STATE_NONE = 0; /** * The input format has changed in a way that requires the decoder to be re-initialized, but we @@ -153,11 +152,7 @@ public DecoderAudioRenderer( @Nullable Handler eventHandler, @Nullable AudioRendererEventListener eventListener, AudioProcessor... audioProcessors) { - this( - eventHandler, - eventListener, - /* audioCapabilities= */ null, - audioProcessors); + this(eventHandler, eventListener, /* audioCapabilities= */ null, audioProcessors); } /** @@ -264,7 +259,8 @@ public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackEx try { audioSink.playToEndOfStream(); } catch (AudioSink.WriteException e) { - throw createRendererException(e, e.format, e.isRecoverable); + throw createRendererException( + e, e.format, e.isRecoverable, PlaybackException.ERROR_CODE_AUDIO_TRACK_WRITE_FAILED); } return; } @@ -284,7 +280,8 @@ public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackEx try { processEndOfStream(); } catch (AudioSink.WriteException e) { - throw createRendererException(e, /* format= */ null); + throw createRendererException( + e, /* format= */ null, PlaybackException.ERROR_CODE_AUDIO_TRACK_WRITE_FAILED); } return; } else { @@ -304,15 +301,19 @@ public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackEx while (feedInputBuffer()) {} TraceUtil.endSection(); } catch (DecoderException e) { + // Can happen with dequeueOutputBuffer, dequeueInputBuffer, queueInputBuffer Log.e(TAG, "Audio codec error", e); eventDispatcher.audioCodecError(e); - throw createRendererException(e, inputFormat); + throw createRendererException(e, inputFormat, PlaybackException.ERROR_CODE_DECODING_FAILED); } catch (AudioSink.ConfigurationException e) { - throw createRendererException(e, e.format); + throw createRendererException( + e, e.format, PlaybackException.ERROR_CODE_AUDIO_TRACK_INIT_FAILED); } catch (AudioSink.InitializationException e) { - throw createRendererException(e, e.format, e.isRecoverable); + throw createRendererException( + e, e.format, e.isRecoverable, PlaybackException.ERROR_CODE_AUDIO_TRACK_INIT_FAILED); } catch (AudioSink.WriteException e) { - throw createRendererException(e, e.format, e.isRecoverable); + throw createRendererException( + e, e.format, e.isRecoverable, PlaybackException.ERROR_CODE_AUDIO_TRACK_WRITE_FAILED); } decoderCounters.ensureUpdated(); } @@ -388,7 +389,8 @@ private boolean drainOutputBuffer() try { processEndOfStream(); } catch (AudioSink.WriteException e) { - throw createRendererException(e, e.format, e.isRecoverable); + throw createRendererException( + e, e.format, e.isRecoverable, PlaybackException.ERROR_CODE_AUDIO_TRACK_WRITE_FAILED); } } return false; @@ -417,7 +419,8 @@ private boolean drainOutputBuffer() } private boolean feedInputBuffer() throws DecoderException, ExoPlaybackException { - if (decoder == null || decoderReinitializationState == REINITIALIZATION_STATE_WAIT_END_OF_STREAM + if (decoder == null + || decoderReinitializationState == REINITIALIZATION_STATE_WAIT_END_OF_STREAM || inputStreamEnded) { // We need to reinitialize the decoder or the input stream has ended. return false; @@ -621,15 +624,19 @@ private void maybeInitDecoder() throws ExoPlaybackException { decoder = createDecoder(inputFormat, mediaCrypto); TraceUtil.endSection(); long codecInitializedTimestamp = SystemClock.elapsedRealtime(); - eventDispatcher.decoderInitialized(decoder.getName(), codecInitializedTimestamp, + eventDispatcher.decoderInitialized( + decoder.getName(), + codecInitializedTimestamp, codecInitializedTimestamp - codecInitializingTimestamp); decoderCounters.decoderInitCount++; } catch (DecoderException e) { Log.e(TAG, "Audio codec error", e); eventDispatcher.audioCodecError(e); - throw createRendererException(e, inputFormat); + throw createRendererException( + e, inputFormat, PlaybackException.ERROR_CODE_DECODER_INIT_FAILED); } catch (OutOfMemoryError e) { - throw createRendererException(e, inputFormat); + throw createRendererException( + e, inputFormat, PlaybackException.ERROR_CODE_DECODER_INIT_FAILED); } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java index 47bfba9efe4..376776575be 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java @@ -73,7 +73,6 @@ public static final class InvalidAudioTrackTimestampException extends RuntimeExc private InvalidAudioTrackTimestampException(String message) { super(message); } - } /** @@ -221,7 +220,8 @@ public long getSkippedOutputFrameCount() { @IntDef({ OFFLOAD_MODE_DISABLED, OFFLOAD_MODE_ENABLED_GAPLESS_REQUIRED, - OFFLOAD_MODE_ENABLED_GAPLESS_NOT_REQUIRED + OFFLOAD_MODE_ENABLED_GAPLESS_NOT_REQUIRED, + OFFLOAD_MODE_ENABLED_GAPLESS_DISABLED }) public @interface OffloadMode {} @@ -243,6 +243,13 @@ public long getSkippedOutputFrameCount() { * transitions between tracks of the same album. */ public static final int OFFLOAD_MODE_ENABLED_GAPLESS_NOT_REQUIRED = 2; + /** + * The audio sink will prefer offload playback, disabling gapless offload support. + * + *

        Use this option if gapless has undesirable side effects. For example if it introduces + * hardware issues. + */ + public static final int OFFLOAD_MODE_ENABLED_GAPLESS_DISABLED = 3; @Documented @Retention(RetentionPolicy.SOURCE) @@ -293,8 +300,8 @@ public long getSkippedOutputFrameCount() { /** * Whether to throw an {@link InvalidAudioTrackTimestampException} when a spurious timestamp is * reported from {@link AudioTrack#getTimestamp}. - *

        - * The flag must be set before creating a player. Should be set to {@code true} for testing and + * + *

        The flag must be set before creating a player. Should be set to {@code true} for testing and * debugging purposes only. */ public static boolean failOnSpuriousAudioTimestamp = false; @@ -653,8 +660,10 @@ private void initializeAudioTrack() throws InitializationException { audioTrack = buildAudioTrack(); if (isOffloadedPlayback(audioTrack)) { registerStreamEventCallbackV29(audioTrack); - audioTrack.setOffloadDelayPadding( - configuration.inputFormat.encoderDelay, configuration.inputFormat.encoderPadding); + if (offloadMode != OFFLOAD_MODE_ENABLED_GAPLESS_DISABLED) { + audioTrack.setOffloadDelayPadding( + configuration.inputFormat.encoderDelay, configuration.inputFormat.encoderPadding); + } } audioSessionId = audioTrack.getAudioSessionId(); audioTrackPositionTracker.setAudioTrack( @@ -710,7 +719,8 @@ public boolean handleBuffer( // The current audio track can be reused for the new configuration. configuration = pendingConfiguration; pendingConfiguration = null; - if (isOffloadedPlayback(audioTrack)) { + if (isOffloadedPlayback(audioTrack) + && offloadMode != OFFLOAD_MODE_ENABLED_GAPLESS_DISABLED) { audioTrack.setOffloadEndOfStream(); audioTrack.setOffloadDelayPadding( configuration.inputFormat.encoderDelay, configuration.inputFormat.encoderPadding); @@ -865,8 +875,10 @@ private void processBuffers(long avSyncPresentationTimeUs) throws WriteException int count = activeAudioProcessors.length; int index = count; while (index >= 0) { - ByteBuffer input = index > 0 ? outputBuffers[index - 1] - : (inputBuffer != null ? inputBuffer : AudioProcessor.EMPTY_BUFFER); + ByteBuffer input = + index > 0 + ? outputBuffers[index - 1] + : (inputBuffer != null ? inputBuffer : AudioProcessor.EMPTY_BUFFER); if (index == count) { writeBuffer(input, avSyncPresentationTimeUs); } else { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java index 2fc8667bc5a..0e3aa17212b 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java @@ -34,6 +34,7 @@ import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.FormatHolder; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.PlayerMessage.Target; import com.google.android.exoplayer2.RendererCapabilities; @@ -477,7 +478,8 @@ protected void onOutputFormatChanged(Format format, @Nullable MediaFormat mediaF try { audioSink.configure(audioSinkInputFormat, /* specifiedBufferSize= */ 0, channelMap); } catch (AudioSink.ConfigurationException e) { - throw createRendererException(e, e.format); + throw createRendererException( + e, e.format, PlaybackException.ERROR_CODE_AUDIO_TRACK_INIT_FAILED); } } @@ -636,9 +638,11 @@ protected boolean processOutputBuffer( try { fullyConsumed = audioSink.handleBuffer(buffer, bufferPresentationTimeUs, sampleCount); } catch (InitializationException e) { - throw createRendererException(e, e.format, e.isRecoverable); + throw createRendererException( + e, e.format, e.isRecoverable, PlaybackException.ERROR_CODE_AUDIO_TRACK_INIT_FAILED); } catch (WriteException e) { - throw createRendererException(e, format, e.isRecoverable); + throw createRendererException( + e, format, e.isRecoverable, PlaybackException.ERROR_CODE_AUDIO_TRACK_WRITE_FAILED); } if (fullyConsumed) { @@ -657,7 +661,8 @@ protected void renderToEndOfStream() throws ExoPlaybackException { try { audioSink.playToEndOfStream(); } catch (AudioSink.WriteException e) { - throw createRendererException(e, e.format, e.isRecoverable); + throw createRendererException( + e, e.format, e.isRecoverable, PlaybackException.ERROR_CODE_AUDIO_TRACK_WRITE_FAILED); } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/ResamplingAudioProcessor.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/ResamplingAudioProcessor.java index a4d2a1b67ac..14ba4788e37 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/ResamplingAudioProcessor.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/ResamplingAudioProcessor.java @@ -135,5 +135,4 @@ public void queueInput(ByteBuffer inputBuffer) { inputBuffer.position(inputBuffer.limit()); buffer.flip(); } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/Sonic.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/Sonic.java index 5ddedd7bd7a..58cd145e352 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/Sonic.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/Sonic.java @@ -24,8 +24,8 @@ /** * Sonic audio stream processor for time/pitch stretching. - *

        - * Based on https://github.com/waywardgeek/sonic. + * + *

        Based on https://github.com/waywardgeek/sonic. */ /* package */ final class Sonic { @@ -512,5 +512,4 @@ private static void overlapAdd( } } } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/SonicAudioProcessor.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/SonicAudioProcessor.java index bbfd77469d4..b7d14667be8 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/SonicAudioProcessor.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/SonicAudioProcessor.java @@ -255,5 +255,4 @@ public void reset() { outputBytes = 0; inputEnded = false; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/TrimmingAudioProcessor.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/TrimmingAudioProcessor.java index ed51726530f..bd3017bf531 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/TrimmingAudioProcessor.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/TrimmingAudioProcessor.java @@ -178,5 +178,4 @@ protected void onFlush() { protected void onReset() { endBuffer = Util.EMPTY_BYTE_ARRAY; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/decoder/Decoder.java b/library/core/src/main/java/com/google/android/exoplayer2/decoder/Decoder.java index c94eb2c38a5..68852182aea 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/decoder/Decoder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/decoder/Decoder.java @@ -65,9 +65,6 @@ public interface Decoder { */ void flush(); - /** - * Releases the decoder. Must be called when the decoder is no longer needed. - */ + /** Releases the decoder. Must be called when the decoder is no longer needed. */ void release(); - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/decoder/DecoderCounters.java b/library/core/src/main/java/com/google/android/exoplayer2/decoder/DecoderCounters.java index 698e329be5e..779513d4123 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/decoder/DecoderCounters.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/decoder/DecoderCounters.java @@ -26,53 +26,45 @@ */ public final class DecoderCounters { - /** - * The number of times a decoder has been initialized. - */ + /** The number of times a decoder has been initialized. */ public int decoderInitCount; - /** - * The number of times a decoder has been released. - */ + /** The number of times a decoder has been released. */ public int decoderReleaseCount; - /** - * The number of queued input buffers. - */ + /** The number of queued input buffers. */ public int inputBufferCount; /** * The number of skipped input buffers. - *

        - * A skipped input buffer is an input buffer that was deliberately not sent to the decoder. + * + *

        A skipped input buffer is an input buffer that was deliberately not sent to the decoder. */ public int skippedInputBufferCount; - /** - * The number of rendered output buffers. - */ + /** The number of rendered output buffers. */ public int renderedOutputBufferCount; /** * The number of skipped output buffers. - *

        - * A skipped output buffer is an output buffer that was deliberately not rendered. + * + *

        A skipped output buffer is an output buffer that was deliberately not rendered. */ public int skippedOutputBufferCount; /** * The number of dropped buffers. - *

        - * A dropped buffer is an buffer that was supposed to be decoded/rendered, but was instead + * + *

        A dropped buffer is an buffer that was supposed to be decoded/rendered, but was instead * dropped because it could not be rendered in time. */ public int droppedBufferCount; /** * The maximum number of dropped buffers without an interleaving rendered output buffer. - *

        - * Skipped output buffers are ignored for the purposes of calculating this value. + * + *

        Skipped output buffers are ignored for the purposes of calculating this value. */ public int maxConsecutiveDroppedBufferCount; /** * The number of times all buffers to a keyframe were dropped. - *

        - * Each time buffers to a keyframe are dropped, this counter is increased by one, and the dropped - * buffer counters are increased by one (for the current output buffer) plus the number of buffers - * dropped from the source to advance to the keyframe. + * + *

        Each time buffers to a keyframe are dropped, this counter is increased by one, and the + * dropped buffer counters are increased by one (for the current output buffer) plus the number of + * buffers dropped from the source to advance to the keyframe. */ public int droppedToKeyframeCount; /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/decoder/OutputBuffer.java b/library/core/src/main/java/com/google/android/exoplayer2/decoder/OutputBuffer.java index 073f6ecca70..bce21cca9c6 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/decoder/OutputBuffer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/decoder/OutputBuffer.java @@ -29,9 +29,7 @@ public interface Owner { void releaseOutputBuffer(S outputBuffer); } - /** - * The presentation timestamp for the buffer, in microseconds. - */ + /** The presentation timestamp for the buffer, in microseconds. */ public long timeUs; /** @@ -39,8 +37,6 @@ public interface Owner { */ public int skippedOutputBufferCount; - /** - * Releases the output buffer for reuse. Must be called when the buffer is no longer needed. - */ + /** Releases the output buffer for reuse. Must be called when the buffer is no longer needed. */ public abstract void release(); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/decoder/SimpleDecoder.java b/library/core/src/main/java/com/google/android/exoplayer2/decoder/SimpleDecoder.java index da69924e031..896fb065682 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/decoder/SimpleDecoder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/decoder/SimpleDecoder.java @@ -77,8 +77,8 @@ public void run() { /** * Sets the initial size of each input buffer. - *

        - * This method should only be called before the decoder is used (i.e. before the first call to + * + *

        This method should only be called before the decoder is used (i.e. before the first call to * {@link #dequeueInputBuffer()}. * * @param size The required input buffer size. @@ -96,8 +96,10 @@ public final I dequeueInputBuffer() throws E { synchronized (lock) { maybeThrowException(); Assertions.checkState(dequeuedInputBuffer == null); - dequeuedInputBuffer = availableInputBufferCount == 0 ? null - : availableInputBuffers[--availableInputBufferCount]; + dequeuedInputBuffer = + availableInputBufferCount == 0 + ? null + : availableInputBuffers[--availableInputBufferCount]; return dequeuedInputBuffer; } } @@ -184,8 +186,8 @@ private void maybeThrowException() throws E { /** * Notifies the decode loop if there exists a queued input buffer and an available output buffer * to decode into. - *

        - * Should only be called whilst synchronized on the lock object. + * + *

        Should only be called whilst synchronized on the lock object. */ private void maybeNotifyDecodeLoop() { if (canDecodeBuffer()) { @@ -282,14 +284,10 @@ private void releaseOutputBufferInternal(O outputBuffer) { availableOutputBuffers[availableOutputBufferCount++] = outputBuffer; } - /** - * Creates a new input buffer. - */ + /** Creates a new input buffer. */ protected abstract I createInputBuffer(); - /** - * Creates a new output buffer. - */ + /** Creates a new output buffer. */ protected abstract O createOutputBuffer(); /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/decoder/SimpleOutputBuffer.java b/library/core/src/main/java/com/google/android/exoplayer2/decoder/SimpleOutputBuffer.java index 12d3c8ca264..81561701e2f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/decoder/SimpleOutputBuffer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/decoder/SimpleOutputBuffer.java @@ -59,5 +59,4 @@ public void clear() { public void release() { owner.releaseOutputBuffer(this); } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/ClearKeyUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/ClearKeyUtil.java index 1c64570f9ef..0aace3f95f3 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/ClearKeyUtil.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/ClearKeyUtil.java @@ -21,9 +21,7 @@ import org.json.JSONException; import org.json.JSONObject; -/** - * Utility methods for ClearKey. - */ +/** Utility methods for ClearKey. */ /* package */ final class ClearKeyUtil { private static final String TAG = "ClearKeyUtil"; @@ -93,5 +91,4 @@ private static String base64ToBase64Url(String base64) { private static String base64UrlToBase64(String base64Url) { return base64Url.replace('-', '+').replace('_', '/'); } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/DecryptionException.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/DecryptionException.java index f144cc1ac2a..eddaba3d934 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/DecryptionException.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/DecryptionException.java @@ -18,9 +18,7 @@ /** Thrown when a non-platform component fails to decrypt data. */ public class DecryptionException extends Exception { - /** - * A component specific error code. - */ + /** A component specific error code. */ public final int errorCode; /** @@ -31,5 +29,4 @@ public DecryptionException(int errorCode, String message) { super(message); this.errorCode = errorCode; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSession.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSession.java index f4932590ab9..ca7a657a0ff 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSession.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSession.java @@ -82,8 +82,10 @@ public interface ProvisioningManager { * Called by a session when it fails to perform a provisioning operation. * * @param error The error that occurred. + * @param thrownByExoMediaDrm Whether the error originated in an {@link ExoMediaDrm} operation. + * False when the error originated in the provisioning request. */ - void onProvisionError(Exception error); + void onProvisionError(Exception error, boolean thrownByExoMediaDrm); /** Called by a session when it successfully completes a provisioning operation. */ void onProvisionCompleted(); @@ -235,8 +237,12 @@ public void onProvisionCompleted() { } } - public void onProvisionError(Exception error) { - onError(error); + public void onProvisionError(Exception error, boolean thrownByExoMediaDrm) { + onError( + error, + thrownByExoMediaDrm + ? DrmUtil.ERROR_SOURCE_EXO_MEDIA_DRM + : DrmUtil.ERROR_SOURCE_PROVISIONING); } // DrmSession implementation. @@ -359,7 +365,7 @@ private boolean openInternal() { } catch (NotProvisionedException e) { provisioningManager.provisionRequired(this); } catch (Exception e) { - onError(e); + onError(e, DrmUtil.ERROR_SOURCE_EXO_MEDIA_DRM); } return false; @@ -373,14 +379,14 @@ private void onProvisionResponse(Object request, Object response) { currentProvisionRequest = null; if (response instanceof Exception) { - provisioningManager.onProvisionError((Exception) response); + provisioningManager.onProvisionError((Exception) response, /* thrownByExoMediaDrm= */ false); return; } try { mediaDrm.provideProvisionResponse((byte[]) response); } catch (Exception e) { - provisioningManager.onProvisionError(e); + provisioningManager.onProvisionError(e, /* thrownByExoMediaDrm= */ true); return; } @@ -409,7 +415,7 @@ private void doLicense(boolean allowRetry) { + licenseDurationRemainingSec); postKeyRequest(sessionId, ExoMediaDrm.KEY_TYPE_OFFLINE, allowRetry); } else if (licenseDurationRemainingSec <= 0) { - onError(new KeysExpiredException()); + onError(new KeysExpiredException(), DrmUtil.ERROR_SOURCE_LICENSE_ACQUISITION); } else { state = STATE_OPENED_WITH_KEYS; dispatchEvent(DrmSessionEventListener.EventDispatcher::drmKeysRestored); @@ -437,7 +443,7 @@ private boolean restoreKeys() { mediaDrm.restoreKeys(sessionId, offlineLicenseKeySetId); return true; } catch (Exception e) { - onError(e); + onError(e, DrmUtil.ERROR_SOURCE_EXO_MEDIA_DRM); } return false; } @@ -457,7 +463,7 @@ private void postKeyRequest(byte[] scope, int type, boolean allowRetry) { Util.castNonNull(requestHandler) .post(MSG_KEYS, Assertions.checkNotNull(currentKeyRequest), allowRetry); } catch (Exception e) { - onKeysError(e); + onKeysError(e, /* thrownByExoMediaDrm= */ true); } } @@ -469,7 +475,7 @@ private void onKeyResponse(Object request, Object response) { currentKeyRequest = null; if (response instanceof Exception) { - onKeysError((Exception) response); + onKeysError((Exception) response, /* thrownByExoMediaDrm= */ false); return; } @@ -491,7 +497,7 @@ private void onKeyResponse(Object request, Object response) { dispatchEvent(DrmSessionEventListener.EventDispatcher::drmKeysLoaded); } } catch (Exception e) { - onKeysError(e); + onKeysError(e, /* thrownByExoMediaDrm= */ true); } } @@ -502,16 +508,21 @@ private void onKeysRequired() { } } - private void onKeysError(Exception e) { + private void onKeysError(Exception e, boolean thrownByExoMediaDrm) { if (e instanceof NotProvisionedException) { provisioningManager.provisionRequired(this); } else { - onError(e); + onError( + e, + thrownByExoMediaDrm + ? DrmUtil.ERROR_SOURCE_EXO_MEDIA_DRM + : DrmUtil.ERROR_SOURCE_LICENSE_ACQUISITION); } } - private void onError(final Exception e) { - lastException = new DrmSessionException(e); + private void onError(Exception e, @DrmUtil.ErrorSource int errorSource) { + lastException = + new DrmSessionException(e, DrmUtil.getErrorCodeForMediaDrmException(e, errorSource)); Log.e(TAG, "DRM session error", e); dispatchEvent(eventDispatcher -> eventDispatcher.drmSessionManagerError(e)); if (state != STATE_OPENED_WITH_KEYS) { @@ -520,7 +531,7 @@ private void onError(final Exception e) { } @EnsuresNonNullIf(result = true, expression = "sessionId") - @SuppressWarnings("contracts.conditional.postcondition.not.satisfied") + @SuppressWarnings("nullness:contracts.conditional.postcondition") private boolean isOpen() { return state == STATE_OPENED || state == STATE_OPENED_WITH_KEYS; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java index 5680627b325..774e91eee86 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java @@ -30,6 +30,7 @@ import androidx.annotation.RequiresApi; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.drm.DrmInitData.SchemeData; import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException; import com.google.android.exoplayer2.drm.ExoMediaDrm.OnEventListener; @@ -539,7 +540,8 @@ private DrmSession acquireSession( if (eventDispatcher != null) { eventDispatcher.drmSessionManagerError(error); } - return new ErrorStateDrmSession(new DrmSessionException(error)); + return new ErrorStateDrmSession( + new DrmSessionException(error, PlaybackException.ERROR_CODE_DRM_CONTENT_ERROR)); } } @@ -873,14 +875,14 @@ public void onProvisionCompleted() { } @Override - public void onProvisionError(Exception error) { + public void onProvisionError(Exception error, boolean thrownByExoMediaDrm) { provisioningSession = null; ImmutableList sessionsToNotify = ImmutableList.copyOf(sessionsAwaitingProvisioning); // Clear the list before calling onProvisionError in case provisioning is re-requested. sessionsAwaitingProvisioning.clear(); for (DefaultDrmSession session : sessionsToNotify) { - session.onProvisionError(error); + session.onProvisionError(error, thrownByExoMediaDrm); } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSession.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSession.java index e72d552a684..b9933456130 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSession.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSession.java @@ -18,6 +18,7 @@ import android.media.MediaDrm; import androidx.annotation.IntDef; import androidx.annotation.Nullable; +import com.google.android.exoplayer2.PlaybackException; import java.io.IOException; import java.lang.annotation.Documented; import java.lang.annotation.Retention; @@ -53,10 +54,13 @@ static void replaceSession( /** Wraps the throwable which is the cause of the error state. */ class DrmSessionException extends IOException { - public DrmSessionException(Throwable cause) { + /** The {@link PlaybackException.ErrorCode} that corresponds to the failure. */ + @PlaybackException.ErrorCode public final int errorCode; + + public DrmSessionException(Throwable cause, @PlaybackException.ErrorCode int errorCode) { super(cause); + this.errorCode = errorCode; } - } /** @@ -74,9 +78,7 @@ public DrmSessionException(Throwable cause) { * This is a terminal state. */ int STATE_ERROR = 1; - /** - * The session is being opened. - */ + /** The session is being opened. */ int STATE_OPENING = 2; /** The session is open, but does not have keys required for decryption. */ int STATE_OPENED = 3; @@ -84,11 +86,12 @@ public DrmSessionException(Throwable cause) { int STATE_OPENED_WITH_KEYS = 4; /** - * Returns the current state of the session, which is one of {@link #STATE_ERROR}, - * {@link #STATE_RELEASED}, {@link #STATE_OPENING}, {@link #STATE_OPENED} and - * {@link #STATE_OPENED_WITH_KEYS}. + * Returns the current state of the session, which is one of {@link #STATE_ERROR}, {@link + * #STATE_RELEASED}, {@link #STATE_OPENING}, {@link #STATE_OPENED} and {@link + * #STATE_OPENED_WITH_KEYS}. */ - @State int getState(); + @State + int getState(); /** Returns whether this session allows playback of clear samples prior to keys being loaded. */ default boolean playClearSamplesWithoutKeys() { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSessionManager.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSessionManager.java index 4b3ee553d86..b056f6ab0d0 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSessionManager.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSessionManager.java @@ -18,6 +18,7 @@ import android.os.Looper; import androidx.annotation.Nullable; import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.PlaybackException; /** Manages a DRM session. */ public interface DrmSessionManager { @@ -54,8 +55,8 @@ public DrmSession acquireSession( } else { return new ErrorStateDrmSession( new DrmSession.DrmSessionException( - new UnsupportedDrmException( - UnsupportedDrmException.REASON_UNSUPPORTED_SCHEME))); + new UnsupportedDrmException(UnsupportedDrmException.REASON_UNSUPPORTED_SCHEME), + PlaybackException.ERROR_CODE_DRM_SCHEME_UNSUPPORTED)); } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmUtil.java new file mode 100644 index 00000000000..cb920101107 --- /dev/null +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmUtil.java @@ -0,0 +1,144 @@ +/* + * 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 com.google.android.exoplayer2.drm; + +import android.media.DeniedByServerException; +import android.media.MediaDrm; +import android.media.MediaDrmResetException; +import android.media.NotProvisionedException; +import androidx.annotation.DoNotInline; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; +import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.PlaybackException; +import com.google.android.exoplayer2.util.Util; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** DRM-related utility methods. */ +public final class DrmUtil { + + /** Identifies the operation which caused a DRM-related error. */ + @Documented + @Retention(RetentionPolicy.SOURCE) + @IntDef( + value = { + ERROR_SOURCE_EXO_MEDIA_DRM, + ERROR_SOURCE_LICENSE_ACQUISITION, + ERROR_SOURCE_PROVISIONING + }) + public @interface ErrorSource {} + + /** Corresponds to failures caused by an {@link ExoMediaDrm} method call. */ + public static final int ERROR_SOURCE_EXO_MEDIA_DRM = 1; + /** Corresponds to failures caused by an operation related to obtaining DRM licenses. */ + public static final int ERROR_SOURCE_LICENSE_ACQUISITION = 2; + /** Corresponds to failures caused by an operation related to provisioning the device. */ + public static final int ERROR_SOURCE_PROVISIONING = 3; + + /** + * Returns the {@link PlaybackException.ErrorCode} that corresponds to the given DRM-related + * exception. + * + * @param exception The DRM-related exception for which to obtain a corresponding {@link + * PlaybackException.ErrorCode}. + * @param errorSource The {@link ErrorSource} for the given {@code exception}. + * @return The {@link PlaybackException.ErrorCode} that corresponds to the given DRM-related + * exception. + */ + @PlaybackException.ErrorCode + public static int getErrorCodeForMediaDrmException( + Exception exception, @ErrorSource int errorSource) { + if (Util.SDK_INT >= 21 && PlatformOperationsWrapperV21.isMediaDrmStateException(exception)) { + return PlatformOperationsWrapperV21.mediaDrmStateExceptionToErrorCode(exception); + } else if (Util.SDK_INT >= 23 + && PlatformOperationsWrapperV23.isMediaDrmResetException(exception)) { + return PlaybackException.ERROR_CODE_DRM_SYSTEM_ERROR; + } else if (Util.SDK_INT >= 18 + && PlatformOperationsWrapperV18.isNotProvisionedException(exception)) { + return PlaybackException.ERROR_CODE_DRM_PROVISIONING_FAILED; + } else if (Util.SDK_INT >= 18 + && PlatformOperationsWrapperV18.isDeniedByServerException(exception)) { + return PlaybackException.ERROR_CODE_DRM_DEVICE_REVOKED; + } else if (exception instanceof UnsupportedDrmException) { + return PlaybackException.ERROR_CODE_DRM_SCHEME_UNSUPPORTED; + } else if (exception instanceof DefaultDrmSessionManager.MissingSchemeDataException) { + return PlaybackException.ERROR_CODE_DRM_CONTENT_ERROR; + } else if (exception instanceof KeysExpiredException) { + return PlaybackException.ERROR_CODE_DRM_LICENSE_EXPIRED; + } else if (errorSource == ERROR_SOURCE_EXO_MEDIA_DRM) { + // A MediaDrm exception was thrown but it was impossible to determine the cause. Because no + // better diagnosis tools were provided, we treat this as a system error. + return PlaybackException.ERROR_CODE_DRM_SYSTEM_ERROR; + } else if (errorSource == ERROR_SOURCE_LICENSE_ACQUISITION) { + return PlaybackException.ERROR_CODE_DRM_LICENSE_ACQUISITION_FAILED; + } else if (errorSource == ERROR_SOURCE_PROVISIONING) { + return PlaybackException.ERROR_CODE_DRM_PROVISIONING_FAILED; + } else { + // Should never happen. + throw new IllegalArgumentException(); + } + } + + // Internal classes. + + @RequiresApi(18) + private static final class PlatformOperationsWrapperV18 { + + @DoNotInline + public static boolean isNotProvisionedException(@Nullable Throwable throwable) { + return throwable instanceof NotProvisionedException; + } + + @DoNotInline + public static boolean isDeniedByServerException(@Nullable Throwable throwable) { + return throwable instanceof DeniedByServerException; + } + } + + @RequiresApi(21) + private static final class PlatformOperationsWrapperV21 { + + @DoNotInline + public static boolean isMediaDrmStateException(@Nullable Throwable throwable) { + return throwable instanceof MediaDrm.MediaDrmStateException; + } + + @DoNotInline + @PlaybackException.ErrorCode + public static int mediaDrmStateExceptionToErrorCode(Throwable throwable) { + @Nullable + String diagnosticsInfo = ((MediaDrm.MediaDrmStateException) throwable).getDiagnosticInfo(); + int drmErrorCode = Util.getErrorCodeFromPlatformDiagnosticsInfo(diagnosticsInfo); + return C.getErrorCodeForMediaDrmErrorCode(drmErrorCode); + } + } + + @RequiresApi(23) + private static final class PlatformOperationsWrapperV23 { + + @DoNotInline + public static boolean isMediaDrmResetException(@Nullable Throwable throwable) { + return throwable instanceof MediaDrmResetException; + } + } + + // Prevent instantiation. + + private DrmUtil() {} +} diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/ExoMediaDrm.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/ExoMediaDrm.java index 6a5dffc6b88..b20fc916c4e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/ExoMediaDrm.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/ExoMediaDrm.java @@ -37,7 +37,7 @@ /** * Used to obtain keys for decrypting protected media streams. * - *

        Reference counting

        + *

        Reference counting

        * *

        Access to an instance is managed by reference counting, where {@link #acquire()} increments * the reference count and {@link #release()} decrements it. When the reference count drops to 0 diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaDrm.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaDrm.java index a54975392b3..48255714bd5 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaDrm.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaDrm.java @@ -292,13 +292,15 @@ public void setPropertyByteArray(String propertyName, byte[] value) { } @Override - public FrameworkMediaCrypto createMediaCrypto(byte[] initData) throws MediaCryptoException { + public FrameworkMediaCrypto createMediaCrypto(byte[] sessionId) throws MediaCryptoException { // Work around a bug prior to Lollipop where L1 Widevine forced into L3 mode would still // indicate that it required secure video decoders [Internal ref: b/11428937]. - boolean forceAllowInsecureDecoderComponents = Util.SDK_INT < 21 - && C.WIDEVINE_UUID.equals(uuid) && "L3".equals(getPropertyString("securityLevel")); + boolean forceAllowInsecureDecoderComponents = + Util.SDK_INT < 21 + && C.WIDEVINE_UUID.equals(uuid) + && "L3".equals(getPropertyString("securityLevel")); return new FrameworkMediaCrypto( - adjustUuid(uuid), initData, forceAllowInsecureDecoderComponents); + adjustUuid(uuid), sessionId, forceAllowInsecureDecoderComponents); } @Override diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/HttpMediaDrmCallback.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/HttpMediaDrmCallback.java index 6a20cf7bdaf..d5288a1b352 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/HttpMediaDrmCallback.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/HttpMediaDrmCallback.java @@ -102,9 +102,7 @@ public void clearKeyRequestProperty(String name) { } } - /** - * Clears all headers for key requests made by the callback. - */ + /** Clears all headers for key requests made by the callback. */ public void clearAllKeyRequestProperties() { synchronized (keyRequestProperties) { keyRequestProperties.clear(); @@ -139,12 +137,14 @@ public byte[] executeKeyRequest(UUID uuid, KeyRequest request) throws MediaDrmCa } Map requestProperties = new HashMap<>(); // Add standard request properties for supported schemes. - String contentType = C.PLAYREADY_UUID.equals(uuid) ? "text/xml" - : (C.CLEARKEY_UUID.equals(uuid) ? "application/json" : "application/octet-stream"); + String contentType = + C.PLAYREADY_UUID.equals(uuid) + ? "text/xml" + : (C.CLEARKEY_UUID.equals(uuid) ? "application/json" : "application/octet-stream"); requestProperties.put("Content-Type", contentType); if (C.PLAYREADY_UUID.equals(uuid)) { - requestProperties.put("SOAPAction", - "http://schemas.microsoft.com/DRM/2007/03/protocols/AcquireLicense"); + requestProperties.put( + "SOAPAction", "http://schemas.microsoft.com/DRM/2007/03/protocols/AcquireLicense"); } // Add additional request properties. synchronized (keyRequestProperties) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/LocalMediaDrmCallback.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/LocalMediaDrmCallback.java index d141b6c4c1c..a95291413f7 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/LocalMediaDrmCallback.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/LocalMediaDrmCallback.java @@ -30,9 +30,7 @@ public final class LocalMediaDrmCallback implements MediaDrmCallback { private final byte[] keyResponse; - /** - * @param keyResponse The fixed response for all key requests. - */ + /** @param keyResponse The fixed response for all key requests. */ public LocalMediaDrmCallback(byte[] keyResponse) { this.keyResponse = Assertions.checkNotNull(keyResponse); } @@ -46,5 +44,4 @@ public byte[] executeProvisionRequest(UUID uuid, ProvisionRequest request) { public byte[] executeKeyRequest(UUID uuid, KeyRequest request) { return keyResponse; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/OfflineLicenseHelper.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/OfflineLicenseHelper.java index b218d0cadbf..bfa9d191c44 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/OfflineLicenseHelper.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/OfflineLicenseHelper.java @@ -133,10 +133,10 @@ public OfflineLicenseHelper( @Nullable Map optionalKeyRequestParameters, DrmSessionEventListener.EventDispatcher eventDispatcher) { this( - new DefaultDrmSessionManager.Builder() - .setUuidAndExoMediaDrmProvider(uuid, mediaDrmProvider) - .setKeyRequestParameters(optionalKeyRequestParameters) - .build(callback), + new DefaultDrmSessionManager.Builder() + .setUuidAndExoMediaDrmProvider(uuid, mediaDrmProvider) + .setKeyRequestParameters(optionalKeyRequestParameters) + .build(callback), eventDispatcher); } @@ -255,9 +255,7 @@ public synchronized Pair getLicenseDurationRemainingSec(byte[] offli return Assertions.checkNotNull(licenseDurationRemainingSec); } - /** - * Releases the helper. Should be called when the helper is no longer required. - */ + /** Releases the helper. Should be called when the helper is no longer required. */ public void release() { handlerThread.quit(); } @@ -288,5 +286,4 @@ private DrmSession openBlockingKeyRequest( conditionVariable.block(); return Assertions.checkNotNull(drmSession); } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/UnsupportedDrmException.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/UnsupportedDrmException.java index cd728df1b23..e52c7703889 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/UnsupportedDrmException.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/UnsupportedDrmException.java @@ -31,9 +31,7 @@ public final class UnsupportedDrmException extends Exception { @Retention(RetentionPolicy.SOURCE) @IntDef({REASON_UNSUPPORTED_SCHEME, REASON_INSTANTIATION_ERROR}) public @interface Reason {} - /** - * The requested DRM scheme is unsupported by the device. - */ + /** The requested DRM scheme is unsupported by the device. */ public static final int REASON_UNSUPPORTED_SCHEME = 1; /** * There device advertises support for the requested DRM scheme, but there was an error @@ -41,14 +39,10 @@ public final class UnsupportedDrmException extends Exception { */ public static final int REASON_INSTANTIATION_ERROR = 2; - /** - * Either {@link #REASON_UNSUPPORTED_SCHEME} or {@link #REASON_INSTANTIATION_ERROR}. - */ + /** Either {@link #REASON_UNSUPPORTED_SCHEME} or {@link #REASON_INSTANTIATION_ERROR}. */ @Reason public final int reason; - /** - * @param reason {@link #REASON_UNSUPPORTED_SCHEME} or {@link #REASON_INSTANTIATION_ERROR}. - */ + /** @param reason {@link #REASON_UNSUPPORTED_SCHEME} or {@link #REASON_INSTANTIATION_ERROR}. */ public UnsupportedDrmException(@Reason int reason) { this.reason = reason; } @@ -61,5 +55,4 @@ public UnsupportedDrmException(@Reason int reason, Exception cause) { super(cause); this.reason = reason; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/WidevineUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/WidevineUtil.java index a5998488f22..2af6a5cd1b5 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/WidevineUtil.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/WidevineUtil.java @@ -42,7 +42,8 @@ private WidevineUtil() {} if (keyStatus == null) { return null; } - return new Pair<>(getDurationRemainingSec(keyStatus, PROPERTY_LICENSE_DURATION_REMAINING), + return new Pair<>( + getDurationRemainingSec(keyStatus, PROPERTY_LICENSE_DURATION_REMAINING), getDurationRemainingSec(keyStatus, PROPERTY_PLAYBACK_DURATION_REMAINING)); } @@ -59,5 +60,4 @@ private static long getDurationRemainingSec(Map keyStatus, Strin } return C.TIME_UNSET; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapter.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapter.java index 6d77cdac8d8..dffdef4280b 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapter.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapter.java @@ -114,16 +114,11 @@ public AsynchronousMediaCodecAdapter createAdapter(Configuration configuration) forceQueueingSynchronizationWorkaround, synchronizeCodecInteractionsWithQueueing); TraceUtil.endSection(); - TraceUtil.beginSection("configureCodec"); - codecAdapter.configure( + codecAdapter.initialize( configuration.mediaFormat, configuration.surface, configuration.crypto, configuration.flags); - TraceUtil.endSection(); - TraceUtil.beginSection("startCodec"); - codecAdapter.start(); - TraceUtil.endSection(); return codecAdapter; } catch (Exception e) { if (codecAdapter != null) { @@ -138,13 +133,12 @@ public AsynchronousMediaCodecAdapter createAdapter(Configuration configuration) @Documented @Retention(RetentionPolicy.SOURCE) - @IntDef({STATE_CREATED, STATE_CONFIGURED, STATE_STARTED, STATE_SHUT_DOWN}) + @IntDef({STATE_CREATED, STATE_INITIALIZED, STATE_SHUT_DOWN}) private @interface State {} private static final int STATE_CREATED = 0; - private static final int STATE_CONFIGURED = 1; - private static final int STATE_STARTED = 2; - private static final int STATE_SHUT_DOWN = 3; + private static final int STATE_INITIALIZED = 1; + private static final int STATE_SHUT_DOWN = 2; private final MediaCodec codec; private final AsynchronousMediaCodecCallback asynchronousMediaCodecCallback; @@ -168,20 +162,25 @@ private AsynchronousMediaCodecAdapter( this.state = STATE_CREATED; } - private void configure( + private void initialize( @Nullable MediaFormat mediaFormat, @Nullable Surface surface, @Nullable MediaCrypto crypto, int flags) { asynchronousMediaCodecCallback.initialize(codec); + TraceUtil.beginSection("configureCodec"); codec.configure(mediaFormat, surface, crypto, flags); - state = STATE_CONFIGURED; - } - - private void start() { + TraceUtil.endSection(); bufferEnqueuer.start(); + TraceUtil.beginSection("startCodec"); codec.start(); - state = STATE_STARTED; + TraceUtil.endSection(); + state = STATE_INITIALIZED; + } + + @Override + public boolean needsReconfiguration() { + return false; } @Override @@ -248,10 +247,8 @@ public void flush() { @Override public void release() { try { - if (state == STATE_STARTED) { + if (state == STATE_INITIALIZED) { bufferEnqueuer.shutdown(); - } - if (state == STATE_CONFIGURED || state == STATE_STARTED) { asynchronousMediaCodecCallback.shutdown(); } state = STATE_SHUT_DOWN; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecAdapter.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecAdapter.java index 368444f81d6..0b8fffd6e95 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecAdapter.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecAdapter.java @@ -214,4 +214,7 @@ void queueSecureInputBuffer( * @see MediaCodec#setVideoScalingMode(int) */ void setVideoScalingMode(@C.VideoScalingMode int scalingMode); + + /** Whether the adapter needs to be reconfigured before it is used. */ + boolean needsReconfiguration(); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java index 99396af2f4d..6d4c11603ae 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java @@ -214,7 +214,8 @@ public String toString() { * @return The profile levels supported by the decoder. */ public CodecProfileLevel[] getProfileLevels() { - return capabilities == null || capabilities.profileLevels == null ? new CodecProfileLevel[0] + return capabilities == null || capabilities.profileLevels == null + ? new CodecProfileLevel[0] : capabilities.profileLevels; } @@ -571,8 +572,8 @@ public boolean isAudioChannelCountSupportedV21(int channelCount) { logNoSupport("channelCount.aCaps"); return false; } - int maxInputChannelCount = adjustMaxInputChannelCount(name, mimeType, - audioCapabilities.getMaxInputChannelCount()); + int maxInputChannelCount = + adjustMaxInputChannelCount(name, mimeType, audioCapabilities.getMaxInputChannelCount()); if (maxInputChannelCount < channelCount) { logNoSupport("channelCount.support, " + channelCount); return false; @@ -581,13 +582,31 @@ public boolean isAudioChannelCountSupportedV21(int channelCount) { } private void logNoSupport(String message) { - Log.d(TAG, "NoSupport [" + message + "] [" + name + ", " + mimeType + "] [" - + Util.DEVICE_DEBUG_INFO + "]"); + Log.d( + TAG, + "NoSupport [" + + message + + "] [" + + name + + ", " + + mimeType + + "] [" + + Util.DEVICE_DEBUG_INFO + + "]"); } private void logAssumedSupport(String message) { - Log.d(TAG, "AssumedSupport [" + message + "] [" + name + ", " + mimeType + "] [" - + Util.DEVICE_DEBUG_INFO + "]"); + Log.d( + TAG, + "AssumedSupport [" + + message + + "] [" + + name + + ", " + + mimeType + + "] [" + + Util.DEVICE_DEBUG_INFO + + "]"); } private static int adjustMaxInputChannelCount(String name, String mimeType, int maxChannelCount) { @@ -619,8 +638,15 @@ private static int adjustMaxInputChannelCount(String name, String mimeType, int // Default to the platform limit, which is 30. assumedMaxChannelCount = 30; } - Log.w(TAG, "AssumedMaxChannelAdjustment: " + name + ", [" + maxChannelCount + " to " - + assumedMaxChannelCount + "]"); + Log.w( + TAG, + "AssumedMaxChannelAdjustment: " + + name + + ", [" + + maxChannelCount + + " to " + + assumedMaxChannelCount + + "]"); return assumedMaxChannelCount; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java index da97a60c0ad..9d689faa038 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java @@ -49,6 +49,7 @@ import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.FormatHolder; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.decoder.DecoderCounters; import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer.InsufficientCapacityException; @@ -89,14 +90,10 @@ public static class DecoderInitializationException extends Exception { private static final int NO_SUITABLE_DECODER_ERROR = CUSTOM_ERROR_CODE_BASE + 1; private static final int DECODER_QUERY_ERROR = CUSTOM_ERROR_CODE_BASE + 2; - /** - * The mime type for which a decoder was being initialized. - */ + /** The mime type for which a decoder was being initialized. */ public final String mimeType; - /** - * Whether it was required that the decoder support a secure output path. - */ + /** Whether it was required that the decoder support a secure output path. */ public final boolean secureDecoderRequired; /** @@ -197,9 +194,10 @@ private static String buildCustomDiagnosticInfo(int errorCode) { * If the {@link MediaCodec} is hotswapped (i.e. replaced during playback), this is the period of * time during which {@link #isReady()} will report true regardless of whether the new codec has * output frames that are ready to be rendered. - *

        - * This allows codec hotswapping to be performed seamlessly, without interrupting the playback of - * other renderers, provided the new codec is able to decode some frames within this time period. + * + *

        This allows codec hotswapping to be performed seamlessly, without interrupting the playback + * of other renderers, provided the new codec is able to decode some frames within this time + * period. */ private static final long MAX_CODEC_HOTSWAP_TIME_MS = 1000; @@ -215,13 +213,9 @@ private static String buildCustomDiagnosticInfo(int errorCode) { RECONFIGURATION_STATE_QUEUE_PENDING }) private @interface ReconfigurationState {} - /** - * There is no pending adaptive reconfiguration work. - */ + /** There is no pending adaptive reconfiguration work. */ private static final int RECONFIGURATION_STATE_NONE = 0; - /** - * Codec configuration data needs to be written into the next buffer. - */ + /** Codec configuration data needs to be written into the next buffer. */ private static final int RECONFIGURATION_STATE_WRITE_PENDING = 1; /** * Codec configuration data has been written into the next buffer, but that buffer still needs to @@ -267,17 +261,13 @@ private static String buildCustomDiagnosticInfo(int errorCode) { }) private @interface AdaptationWorkaroundMode {} - /** - * The adaptation workaround is never used. - */ + /** The adaptation workaround is never used. */ private static final int ADAPTATION_WORKAROUND_MODE_NEVER = 0; /** * The adaptation workaround is used when adapting between formats of the same resolution only. */ private static final int ADAPTATION_WORKAROUND_MODE_SAME_RESOLUTION = 1; - /** - * The adaptation workaround is always used when adapting between formats. - */ + /** The adaptation workaround is always used when adapting between formats. */ private static final int ADAPTATION_WORKAROUND_MODE_ALWAYS = 2; /** @@ -363,7 +353,6 @@ private static String buildCustomDiagnosticInfo(int errorCode) { private boolean enableAsynchronousBufferQueueing; private boolean forceAsyncQueueingSynchronizationWorkaround; private boolean enableSynchronizeCodecInteractionsWithQueueing; - private boolean enableSkipAndContinueIfSampleTooLarge; @Nullable private ExoPlaybackException pendingPlaybackException; protected DecoderCounters decoderCounters; private long outputStreamStartPositionUs; @@ -480,18 +469,6 @@ public void experimentalSetSynchronizeCodecInteractionsWithQueueingEnabled(boole enableSynchronizeCodecInteractionsWithQueueing = enabled; } - /** - * Enables skipping and continuing playback from the next key frame if a sample is encountered - * that's too large to fit into one of the decoder's input buffers. When not enabled, playback - * will fail in this case. - * - *

        This method is experimental, and will be renamed or removed in a future release. It should - * only be called before the renderer is used. - */ - public void experimentalSetSkipAndContinueIfSampleTooLarge(boolean enabled) { - enableSkipAndContinueIfSampleTooLarge = enabled; - } - @Override @AdaptiveSupport public final int supportsMixedMimeTypeAdaptation() { @@ -504,7 +481,7 @@ public final int supportsFormat(Format format) throws ExoPlaybackException { try { return supportsFormat(mediaCodecSelector, format); } catch (DecoderQueryException e) { - throw createRendererException(e, format); + throw createRendererException(e, format, PlaybackException.ERROR_CODE_DECODER_QUERY_FAILED); } } @@ -517,9 +494,7 @@ public final int supportsFormat(Format format) throws ExoPlaybackException { * @throws DecoderQueryException If there was an error querying decoders. */ @Capabilities - protected abstract int supportsFormat( - MediaCodecSelector mediaCodecSelector, - Format format) + protected abstract int supportsFormat(MediaCodecSelector mediaCodecSelector, Format format) throws DecoderQueryException; /** @@ -584,7 +559,8 @@ protected final void maybeInitCodecOrBypass() throws ExoPlaybackException { try { mediaCrypto = new MediaCrypto(sessionMediaCrypto.uuid, sessionMediaCrypto.sessionId); } catch (MediaCryptoException e) { - throw createRendererException(e, inputFormat); + throw createRendererException( + e, inputFormat, PlaybackException.ERROR_CODE_DRM_SYSTEM_ERROR); } mediaCryptoRequiresSecureDecoder = !sessionMediaCrypto.forceAllowInsecureDecoderComponents @@ -594,7 +570,10 @@ protected final void maybeInitCodecOrBypass() throws ExoPlaybackException { if (FrameworkMediaCrypto.WORKAROUND_DEVICE_NEEDS_KEYS_TO_CONFIGURE_CODEC) { @DrmSession.State int drmSessionState = codecDrmSession.getState(); if (drmSessionState == DrmSession.STATE_ERROR) { - throw createRendererException(codecDrmSession.getError(), inputFormat); + DrmSessionException drmSessionException = + Assertions.checkNotNull(codecDrmSession.getError()); + throw createRendererException( + drmSessionException, inputFormat, drmSessionException.errorCode); } else if (drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS) { // Wait for keys. return; @@ -605,7 +584,8 @@ protected final void maybeInitCodecOrBypass() throws ExoPlaybackException { try { maybeInitCodecWithFallback(mediaCrypto, mediaCryptoRequiresSecureDecoder); } catch (DecoderInitializationException e) { - throw createRendererException(e, inputFormat); + throw createRendererException( + e, inputFormat, PlaybackException.ERROR_CODE_DECODER_INIT_FAILED); } } @@ -861,7 +841,10 @@ && shouldContinueRendering(renderStartTimeMs)) {} releaseCodec(); } throw createRendererException( - createDecoderException(e, getCodecInfo()), inputFormat, isRecoverable); + createDecoderException(e, getCodecInfo()), + inputFormat, + isRecoverable, + PlaybackException.ERROR_CODE_DECODING_FAILED); } throw e; } @@ -1051,6 +1034,7 @@ private void maybeInitCodecWithFallback( DecoderInitializationException exception = new DecoderInitializationException( inputFormat, e, mediaCryptoRequiresSecureDecoder, codecInfo); + onCodecError(exception); if (preferredDecoderInitializationException == null) { preferredDecoderInitializationException = exception; } else { @@ -1154,6 +1138,12 @@ private void initCodec(MediaCodecInfo codecInfo, MediaCrypto crypto) throws Exce codecNeedsMonoChannelCountWorkaround(codecName, codecInputFormat); codecNeedsEosPropagation = codecNeedsEosPropagationWorkaround(codecInfo) || getCodecNeedsEosPropagation(); + if (codecAdapter.needsReconfiguration()) { + this.codecReconfigured = true; + this.codecReconfigurationState = RECONFIGURATION_STATE_WRITE_PENDING; + this.codecNeedsAdaptationWorkaroundBuffer = + codecAdaptationWorkaroundMode != ADAPTATION_WORKAROUND_MODE_NEVER; + } if ("c2.android.mp3.decoder".equals(codecInfo.name)) { c2Mp3TimestampTracker = new C2Mp3TimestampTracker(); } @@ -1255,16 +1245,11 @@ private boolean feedInputBuffer() throws ExoPlaybackException { result = readSource(formatHolder, buffer, /* readFlags= */ 0); } catch (InsufficientCapacityException e) { onCodecError(e); - if (enableSkipAndContinueIfSampleTooLarge) { - // Skip the sample that's too large by reading it without its data. Then flush the codec so - // that rendering will resume from the next key frame. - readSourceOmittingSampleData(/* readFlags= */ 0); - flushCodec(); - return true; - } else { - throw createRendererException( - createDecoderException(e, getCodecInfo()), inputFormat, /* isRecoverable= */ false); - } + // Skip the sample that's too large by reading it without its data. Then flush the codec so + // that rendering will resume from the next key frame. + readSourceOmittingSampleData(/* readFlags= */ 0); + flushCodec(); + return true; } if (hasReadStreamToEnd()) { @@ -1314,7 +1299,8 @@ private boolean feedInputBuffer() throws ExoPlaybackException { resetInputBuffer(); } } catch (CryptoException e) { - throw createRendererException(e, inputFormat); + throw createRendererException( + e, inputFormat, C.getErrorCodeForMediaDrmErrorCode(e.getErrorCode())); } return false; } @@ -1384,7 +1370,8 @@ private boolean feedInputBuffer() throws ExoPlaybackException { inputIndex, /* offset= */ 0, buffer.data.limit(), presentationTimeUs, /* flags= */ 0); } } catch (CryptoException e) { - throw createRendererException(e, inputFormat); + throw createRendererException( + e, inputFormat, C.getErrorCodeForMediaDrmErrorCode(e.getErrorCode())); } resetInputBuffer(); @@ -1396,16 +1383,16 @@ private boolean feedInputBuffer() throws ExoPlaybackException { /** * Called when a {@link MediaCodec} has been created and configured. - *

        - * The default implementation is a no-op. + * + *

        The default implementation is a no-op. * * @param name The name of the codec that was initialized. * @param initializedTimestampMs {@link SystemClock#elapsedRealtime()} when initialization * finished. * @param initializationDurationMs The time taken to initialize the codec in milliseconds. */ - protected void onCodecInitialized(String name, long initializedTimestampMs, - long initializationDurationMs) { + protected void onCodecInitialized( + String name, long initializedTimestampMs, long initializationDurationMs) { // Do nothing. } @@ -1448,7 +1435,11 @@ protected DecoderReuseEvaluation onInputFormatChanged(FormatHolder formatHolder) if (newFormat.sampleMimeType == null) { // If the new format is invalid, it is either a media bug or it is not intended to be played. // See also https://github.com/google/ExoPlayer/issues/8283. - throw createRendererException(new IllegalArgumentException(), newFormat); + + throw createRendererException( + new IllegalArgumentException(), + newFormat, + PlaybackException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED); } setSourceDrmSession(formatHolder.drmSession); inputFormat = newFormat; @@ -1459,9 +1450,7 @@ protected DecoderReuseEvaluation onInputFormatChanged(FormatHolder formatHolder) } if (codec == null) { - if (!legacyKeepAvailableCodecInfosWithoutCodec()) { - availableCodecInfos = null; - } + availableCodecInfos = null; maybeInitCodecOrBypass(); return null; } @@ -1550,14 +1539,6 @@ protected DecoderReuseEvaluation onInputFormatChanged(FormatHolder formatHolder) return evaluation; } - /** - * Returns whether to keep available codec infos when the codec hasn't been initialized, which is - * the behavior before a bug fix. See also [Internal: b/162837741]. - */ - protected boolean legacyKeepAvailableCodecInfosWithoutCodec() { - return false; - } - /** * Called when one of the output formats changes. * @@ -2012,8 +1993,8 @@ protected abstract boolean processOutputBuffer( /** * Incrementally renders any remaining output. - *

        - * The default implementation is a no-op. + * + *

        The default implementation is a no-op. * * @throws ExoPlaybackException Thrown if an error occurs rendering remaining output. */ @@ -2176,7 +2157,7 @@ private void updateDrmSessionV23() throws ExoPlaybackException { try { mediaCrypto.setMediaDrmSession(getFrameworkMediaCrypto(sourceDrmSession).sessionId); } catch (MediaCryptoException e) { - throw createRendererException(e, inputFormat); + throw createRendererException(e, inputFormat, PlaybackException.ERROR_CODE_DRM_SYSTEM_ERROR); } setCodecDrmSession(sourceDrmSession); codecDrainState = DRAIN_STATE_NONE; @@ -2192,7 +2173,8 @@ private FrameworkMediaCrypto getFrameworkMediaCrypto(DrmSession drmSession) // selection. throw createRendererException( new IllegalArgumentException("Expecting FrameworkMediaCrypto but found: " + mediaCrypto), - inputFormat); + inputFormat, + PlaybackException.ERROR_CODE_DRM_SCHEME_UNSUPPORTED); } return (FrameworkMediaCrypto) mediaCrypto; } @@ -2335,11 +2317,11 @@ private static boolean isRecoverableMediaCodecExceptionV21(IllegalStateException /** * Returns whether the decoder is known to fail when flushed. - *

        - * If true is returned, the renderer will work around the issue by releasing the decoder and + * + *

        If true is returned, the renderer will work around the issue by releasing the decoder and * instantiating a new one rather than flushing the current instance. - *

        - * See [Internal: b/8347958, b/8543366]. + * + *

        See [Internal: b/8347958, b/8543366]. * * @param name The name of the decoder. * @return True if the decoder is known to fail when flushed. @@ -2347,9 +2329,10 @@ private static boolean isRecoverableMediaCodecExceptionV21(IllegalStateException private static boolean codecNeedsFlushWorkaround(String name) { return Util.SDK_INT < 18 || (Util.SDK_INT == 18 - && ("OMX.SEC.avc.dec".equals(name) || "OMX.SEC.avc.dec.secure".equals(name))) - || (Util.SDK_INT == 19 && Util.MODEL.startsWith("SM-G800") - && ("OMX.Exynos.avc.dec".equals(name) || "OMX.Exynos.avc.dec.secure".equals(name))); + && ("OMX.SEC.avc.dec".equals(name) || "OMX.SEC.avc.dec.secure".equals(name))) + || (Util.SDK_INT == 19 + && Util.MODEL.startsWith("SM-G800") + && ("OMX.Exynos.avc.dec".equals(name) || "OMX.Exynos.avc.dec.secure".equals(name))); } /** @@ -2366,14 +2349,19 @@ private static boolean codecNeedsFlushWorkaround(String name) { * @return The mode specifying when the adaptation workaround should be enabled. */ private @AdaptationWorkaroundMode int codecAdaptationWorkaroundMode(String name) { - if (Util.SDK_INT <= 25 && "OMX.Exynos.avc.dec.secure".equals(name) - && (Util.MODEL.startsWith("SM-T585") || Util.MODEL.startsWith("SM-A510") - || Util.MODEL.startsWith("SM-A520") || Util.MODEL.startsWith("SM-J700"))) { + if (Util.SDK_INT <= 25 + && "OMX.Exynos.avc.dec.secure".equals(name) + && (Util.MODEL.startsWith("SM-T585") + || Util.MODEL.startsWith("SM-A510") + || Util.MODEL.startsWith("SM-A520") + || Util.MODEL.startsWith("SM-J700"))) { return ADAPTATION_WORKAROUND_MODE_ALWAYS; } else if (Util.SDK_INT < 24 && ("OMX.Nvidia.h264.decode".equals(name) || "OMX.Nvidia.h264.decode.secure".equals(name)) - && ("flounder".equals(Util.DEVICE) || "flounder_lte".equals(Util.DEVICE) - || "grouper".equals(Util.DEVICE) || "tilapia".equals(Util.DEVICE))) { + && ("flounder".equals(Util.DEVICE) + || "flounder_lte".equals(Util.DEVICE) + || "grouper".equals(Util.DEVICE) + || "tilapia".equals(Util.DEVICE))) { return ADAPTATION_WORKAROUND_MODE_SAME_RESOLUTION; } else { return ADAPTATION_WORKAROUND_MODE_NEVER; @@ -2392,7 +2380,8 @@ private static boolean codecNeedsFlushWorkaround(String name) { * @return True if the decoder is known to fail if NAL units are queued before CSD. */ private static boolean codecNeedsDiscardToSpsWorkaround(String name, Format format) { - return Util.SDK_INT < 21 && format.initializationData.isEmpty() + return Util.SDK_INT < 21 + && format.initializationData.isEmpty() && "OMX.MTK.VIDEO.DECODER.AVC".equals(name); } @@ -2438,11 +2427,11 @@ private static boolean codecNeedsEosPropagationWorkaround(MediaCodecInfo codecIn /** * Returns whether the decoder is known to behave incorrectly if flushed after receiving an input * buffer with {@link MediaCodec#BUFFER_FLAG_END_OF_STREAM} set. - *

        - * If true is returned, the renderer will work around the issue by instantiating a new decoder + * + *

        If true is returned, the renderer will work around the issue by instantiating a new decoder * when this case occurs. - *

        - * See [Internal: b/8578467, b/23361053]. + * + *

        See [Internal: b/8578467, b/23361053]. * * @param name The name of the decoder. * @return True if the decoder is known to behave incorrectly if flushed after receiving an input @@ -2504,7 +2493,8 @@ private static boolean codecNeedsEosOutputExceptionWorkaround(String name) { * channel. False otherwise. */ private static boolean codecNeedsMonoChannelCountWorkaround(String name, Format format) { - return Util.SDK_INT <= 18 && format.channelCount == 1 + return Util.SDK_INT <= 18 + && format.channelCount == 1 && "OMX.MTK.AUDIO.DECODER.MP3".equals(name); } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java index 7eac7a21c2b..ad16170b0b1 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java @@ -48,8 +48,8 @@ public final class MediaCodecUtil { /** * Thrown when an error occurs querying the device for its underlying media capabilities. - *

        - * Such failures are not expected in normal operation and are normally temporary (e.g. if the + * + *

        Such failures are not expected in normal operation and are normally temporary (e.g. if the * mediaserver process has crashed and is yet to restart). */ public static class DecoderQueryException extends Exception { @@ -57,7 +57,6 @@ public static class DecoderQueryException extends Exception { private DecoderQueryException(Throwable cause) { super("Failed to query underlying media codecs", cause); } - } private static final String TAG = "MediaCodecUtil"; @@ -175,8 +174,12 @@ public static synchronized List getDecoderInfos( mediaCodecList = new MediaCodecListCompatV16(); decoderInfos = getDecoderInfosInternal(key, mediaCodecList); if (!decoderInfos.isEmpty()) { - Log.w(TAG, "MediaCodecList API didn't list secure decoder for: " + mimeType - + ". Assuming: " + decoderInfos.get(0).name); + Log.w( + TAG, + "MediaCodecList API didn't list secure decoder for: " + + mimeType + + ". Assuming: " + + decoderInfos.get(0).name); } } applyWorkarounds(mimeType, decoderInfos); @@ -383,9 +386,7 @@ private static ArrayList getDecoderInfosInternal( */ @Nullable private static String getCodecMimeType( - android.media.MediaCodecInfo info, - String name, - String mimeType) { + android.media.MediaCodecInfo info, String name, String mimeType) { String[] supportedTypes = info.getSupportedTypes(); for (String supportedType : supportedTypes) { if (supportedType.equalsIgnoreCase(mimeType)) { @@ -507,7 +508,8 @@ private static boolean isCodecUsableDecoder( } // VP8 decoder on Samsung Galaxy S4 cannot be queried. - if (Util.SDK_INT <= 19 && Util.DEVICE.startsWith("jflte") + if (Util.SDK_INT <= 19 + && Util.DEVICE.startsWith("jflte") && "OMX.qcom.video.decoder.vp8".equals(name)) { return false; } @@ -920,9 +922,7 @@ private interface ScoreProvider { private interface MediaCodecListCompat { - /** - * The number of codecs in the list. - */ + /** The number of codecs in the list. */ int getCodecCount(); /** @@ -932,9 +932,7 @@ private interface MediaCodecListCompat { */ android.media.MediaCodecInfo getCodecInfoAt(int index); - /** - * Returns whether secure decoders are explicitly listed, if present. - */ + /** Returns whether secure decoders are explicitly listed, if present. */ boolean secureDecodersExplicit(); /** Whether the specified {@link CodecCapabilities} {@code feature} is supported. */ @@ -993,7 +991,6 @@ private void ensureMediaCodecInfosInitialized() { mediaCodecInfos = new MediaCodecList(codecKind).getCodecInfos(); } } - } private static final class MediaCodecListCompatV16 implements MediaCodecListCompat { @@ -1027,7 +1024,6 @@ public boolean isFeatureRequired( String feature, String mimeType, CodecCapabilities capabilities) { return false; } - } private static final class CodecKey { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/SynchronousMediaCodecAdapter.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/SynchronousMediaCodecAdapter.java index 67fb24f1ddc..90bf99fa064 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/SynchronousMediaCodecAdapter.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/SynchronousMediaCodecAdapter.java @@ -88,6 +88,11 @@ private SynchronousMediaCodecAdapter(MediaCodec mediaCodec) { } } + @Override + public boolean needsReconfiguration() { + return false; + } + @Override public int dequeueInputBufferIndex() { return codec.dequeueInputBuffer(0); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/MetadataRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/MetadataRenderer.java index 182e4e53032..afb32ee2118 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/MetadataRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/MetadataRenderer.java @@ -233,5 +233,4 @@ private void invokeRenderer(Metadata metadata) { private void invokeRendererInternal(Metadata metadata) { output.onMetadata(metadata); } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/PrivateCommand.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/PrivateCommand.java index f1ceaa3bb4b..a849851aa04 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/PrivateCommand.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/PrivateCommand.java @@ -23,17 +23,11 @@ /** Represents a private command as defined in SCTE35, Section 9.3.6. */ public final class PrivateCommand extends SpliceCommand { - /** - * The {@code pts_adjustment} as defined in SCTE35, Section 9.2. - */ + /** The {@code pts_adjustment} as defined in SCTE35, Section 9.2. */ public final long ptsAdjustment; - /** - * The identifier as defined in SCTE35, Section 9.3.6. - */ + /** The identifier as defined in SCTE35, Section 9.3.6. */ public final long identifier; - /** - * The private bytes as defined in SCTE35, Section 9.3.6. - */ + /** The private bytes as defined in SCTE35, Section 9.3.6. */ public final byte[] commandBytes; private PrivateCommand(long identifier, byte[] commandBytes, long ptsAdjustment) { @@ -48,8 +42,8 @@ private PrivateCommand(Parcel in) { commandBytes = Util.castNonNull(in.createByteArray()); } - /* package */ static PrivateCommand parseFromSection(ParsableByteArray sectionData, - int commandLength, long ptsAdjustment) { + /* package */ static PrivateCommand parseFromSection( + ParsableByteArray sectionData, int commandLength, long ptsAdjustment) { long identifier = sectionData.readUnsignedInt(); byte[] privateBytes = new byte[commandLength - 4 /* identifier size */]; sectionData.readBytes(privateBytes, 0, privateBytes.length); @@ -68,16 +62,14 @@ public void writeToParcel(Parcel dest, int flags) { public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override - public PrivateCommand createFromParcel(Parcel in) { - return new PrivateCommand(in); - } - - @Override - public PrivateCommand[] newArray(int size) { - return new PrivateCommand[size]; - } - - }; + @Override + public PrivateCommand createFromParcel(Parcel in) { + return new PrivateCommand(in); + } + @Override + public PrivateCommand[] newArray(int size) { + return new PrivateCommand[size]; + } + }; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceCommand.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceCommand.java index 8cb4dcec2be..40da002c04f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceCommand.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceCommand.java @@ -31,5 +31,4 @@ public String toString() { public int describeContents() { return 0; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceInfoDecoder.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceInfoDecoder.java index fbcf9da6f39..f26d446b800 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceInfoDecoder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceInfoDecoder.java @@ -78,8 +78,8 @@ protected Metadata decode(MetadataInputBuffer inputBuffer, ByteBuffer buffer) { command = SpliceScheduleCommand.parseFromSection(sectionData); break; case TYPE_SPLICE_INSERT: - command = SpliceInsertCommand.parseFromSection(sectionData, ptsAdjustment, - timestampAdjuster); + command = + SpliceInsertCommand.parseFromSection(sectionData, ptsAdjustment, timestampAdjuster); break; case TYPE_TIME_SIGNAL: command = TimeSignalCommand.parseFromSection(sectionData, ptsAdjustment, timestampAdjuster); @@ -93,5 +93,4 @@ protected Metadata decode(MetadataInputBuffer inputBuffer, ByteBuffer buffer) { } return command == null ? new Metadata() : new Metadata(command); } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceInsertCommand.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceInsertCommand.java index 8c8c6a1ffb3..e5df2b963bb 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceInsertCommand.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceInsertCommand.java @@ -27,13 +27,9 @@ /** Represents a splice insert command defined in SCTE35, Section 9.3.3. */ public final class SpliceInsertCommand extends SpliceCommand { - /** - * The splice event id. - */ + /** The splice event id. */ public final long spliceEventId; - /** - * True if the event with id {@link #spliceEventId} has been canceled. - */ + /** True if the event with id {@link #spliceEventId} has been canceled. */ public final boolean spliceEventCancelIndicator; /** * If true, the splice event is an opportunity to exit from the network feed. If false, indicates @@ -47,53 +43,53 @@ public final class SpliceInsertCommand extends SpliceCommand { public final boolean programSpliceFlag; /** * Whether splicing should be done at the nearest opportunity. If false, splicing should be done - * at the moment indicated by {@link #programSplicePlaybackPositionUs} or - * {@link ComponentSplice#componentSplicePlaybackPositionUs}, depending on - * {@link #programSpliceFlag}. + * at the moment indicated by {@link #programSplicePlaybackPositionUs} or {@link + * ComponentSplice#componentSplicePlaybackPositionUs}, depending on {@link #programSpliceFlag}. */ public final boolean spliceImmediateFlag; /** - * If {@link #programSpliceFlag} is true, the PTS at which the program splice should occur. - * {@link C#TIME_UNSET} otherwise. + * If {@link #programSpliceFlag} is true, the PTS at which the program splice should occur. {@link + * C#TIME_UNSET} otherwise. */ public final long programSplicePts; - /** - * Equivalent to {@link #programSplicePts} but in the playback timebase. - */ + /** Equivalent to {@link #programSplicePts} but in the playback timebase. */ public final long programSplicePlaybackPositionUs; /** - * If {@link #programSpliceFlag} is false, a non-empty list containing the - * {@link ComponentSplice}s. Otherwise, an empty list. + * If {@link #programSpliceFlag} is false, a non-empty list containing the {@link + * ComponentSplice}s. Otherwise, an empty list. */ public final List componentSpliceList; /** - * If {@link #breakDurationUs} is not {@link C#TIME_UNSET}, defines whether - * {@link #breakDurationUs} should be used to know when to return to the network feed. If - * {@link #breakDurationUs} is {@link C#TIME_UNSET}, the value is undefined. + * If {@link #breakDurationUs} is not {@link C#TIME_UNSET}, defines whether {@link + * #breakDurationUs} should be used to know when to return to the network feed. If {@link + * #breakDurationUs} is {@link C#TIME_UNSET}, the value is undefined. */ public final boolean autoReturn; /** * The duration of the splice in microseconds, or {@link C#TIME_UNSET} if no duration is present. */ public final long breakDurationUs; - /** - * The unique program id as defined in SCTE35, Section 9.3.3. - */ + /** The unique program id as defined in SCTE35, Section 9.3.3. */ public final int uniqueProgramId; - /** - * Holds the value of {@code avail_num} as defined in SCTE35, Section 9.3.3. - */ + /** Holds the value of {@code avail_num} as defined in SCTE35, Section 9.3.3. */ public final int availNum; - /** - * Holds the value of {@code avails_expected} as defined in SCTE35, Section 9.3.3. - */ + /** Holds the value of {@code avails_expected} as defined in SCTE35, Section 9.3.3. */ public final int availsExpected; - private SpliceInsertCommand(long spliceEventId, boolean spliceEventCancelIndicator, - boolean outOfNetworkIndicator, boolean programSpliceFlag, boolean spliceImmediateFlag, - long programSplicePts, long programSplicePlaybackPositionUs, - List componentSpliceList, boolean autoReturn, long breakDurationUs, - int uniqueProgramId, int availNum, int availsExpected) { + private SpliceInsertCommand( + long spliceEventId, + boolean spliceEventCancelIndicator, + boolean outOfNetworkIndicator, + boolean programSpliceFlag, + boolean spliceImmediateFlag, + long programSplicePts, + long programSplicePlaybackPositionUs, + List componentSpliceList, + boolean autoReturn, + long breakDurationUs, + int uniqueProgramId, + int availNum, + int availsExpected) { this.spliceEventId = spliceEventId; this.spliceEventCancelIndicator = spliceEventCancelIndicator; this.outOfNetworkIndicator = outOfNetworkIndicator; @@ -130,8 +126,8 @@ private SpliceInsertCommand(Parcel in) { availsExpected = in.readInt(); } - /* package */ static SpliceInsertCommand parseFromSection(ParsableByteArray sectionData, - long ptsAdjustment, TimestampAdjuster timestampAdjuster) { + /* package */ static SpliceInsertCommand parseFromSection( + ParsableByteArray sectionData, long ptsAdjustment, TimestampAdjuster timestampAdjuster) { long spliceEventId = sectionData.readUnsignedInt(); // splice_event_cancel_indicator(1), reserved(7). boolean spliceEventCancelIndicator = (sectionData.readUnsignedByte() & 0x80) != 0; @@ -163,8 +159,11 @@ private SpliceInsertCommand(Parcel in) { if (!spliceImmediateFlag) { componentSplicePts = TimeSignalCommand.parseSpliceTime(sectionData, ptsAdjustment); } - componentSplices.add(new ComponentSplice(componentTag, componentSplicePts, - timestampAdjuster.adjustTsTimestamp(componentSplicePts))); + componentSplices.add( + new ComponentSplice( + componentTag, + componentSplicePts, + timestampAdjuster.adjustTsTimestamp(componentSplicePts))); } } if (durationFlag) { @@ -177,23 +176,31 @@ private SpliceInsertCommand(Parcel in) { availNum = sectionData.readUnsignedByte(); availsExpected = sectionData.readUnsignedByte(); } - return new SpliceInsertCommand(spliceEventId, spliceEventCancelIndicator, outOfNetworkIndicator, - programSpliceFlag, spliceImmediateFlag, programSplicePts, - timestampAdjuster.adjustTsTimestamp(programSplicePts), componentSplices, autoReturn, - breakDurationUs, uniqueProgramId, availNum, availsExpected); + return new SpliceInsertCommand( + spliceEventId, + spliceEventCancelIndicator, + outOfNetworkIndicator, + programSpliceFlag, + spliceImmediateFlag, + programSplicePts, + timestampAdjuster.adjustTsTimestamp(programSplicePts), + componentSplices, + autoReturn, + breakDurationUs, + uniqueProgramId, + availNum, + availsExpected); } - /** - * Holds splicing information for specific splice insert command components. - */ + /** Holds splicing information for specific splice insert command components. */ public static final class ComponentSplice { public final int componentTag; public final long componentSplicePts; public final long componentSplicePlaybackPositionUs; - private ComponentSplice(int componentTag, long componentSplicePts, - long componentSplicePlaybackPositionUs) { + private ComponentSplice( + int componentTag, long componentSplicePts, long componentSplicePlaybackPositionUs) { this.componentTag = componentTag; this.componentSplicePts = componentSplicePts; this.componentSplicePlaybackPositionUs = componentSplicePlaybackPositionUs; @@ -208,7 +215,6 @@ public void writeToParcel(Parcel dest) { public static ComponentSplice createFromParcel(Parcel in) { return new ComponentSplice(in.readInt(), in.readLong(), in.readLong()); } - } // Parcelable implementation. @@ -237,16 +243,14 @@ public void writeToParcel(Parcel dest, int flags) { public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override - public SpliceInsertCommand createFromParcel(Parcel in) { - return new SpliceInsertCommand(in); - } - - @Override - public SpliceInsertCommand[] newArray(int size) { - return new SpliceInsertCommand[size]; - } - - }; + @Override + public SpliceInsertCommand createFromParcel(Parcel in) { + return new SpliceInsertCommand(in); + } + @Override + public SpliceInsertCommand[] newArray(int size) { + return new SpliceInsertCommand[size]; + } + }; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceNullCommand.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceNullCommand.java index aed0a0e2bc5..196f2979700 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceNullCommand.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceNullCommand.java @@ -30,16 +30,14 @@ public void writeToParcel(Parcel dest, int flags) { public static final Creator CREATOR = new Creator() { - @Override - public SpliceNullCommand createFromParcel(Parcel in) { - return new SpliceNullCommand(); - } - - @Override - public SpliceNullCommand[] newArray(int size) { - return new SpliceNullCommand[size]; - } - - }; - + @Override + public SpliceNullCommand createFromParcel(Parcel in) { + return new SpliceNullCommand(); + } + + @Override + public SpliceNullCommand[] newArray(int size) { + return new SpliceNullCommand[size]; + } + }; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceScheduleCommand.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceScheduleCommand.java index e252ae7354f..6e62177fc7f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceScheduleCommand.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceScheduleCommand.java @@ -26,18 +26,12 @@ /** Represents a splice schedule command as defined in SCTE35, Section 9.3.2. */ public final class SpliceScheduleCommand extends SpliceCommand { - /** - * Represents a splice event as contained in a {@link SpliceScheduleCommand}. - */ + /** Represents a splice event as contained in a {@link SpliceScheduleCommand}. */ public static final class Event { - /** - * The splice event id. - */ + /** The splice event id. */ public final long spliceEventId; - /** - * True if the event with id {@link #spliceEventId} has been canceled. - */ + /** True if the event with id {@link #spliceEventId} has been canceled. */ public final boolean spliceEventCancelIndicator; /** * If true, the splice event is an opportunity to exit from the network feed. If false, @@ -55,14 +49,14 @@ public static final class Event { */ public final long utcSpliceTime; /** - * If {@link #programSpliceFlag} is false, a non-empty list containing the - * {@link ComponentSplice}s. Otherwise, an empty list. + * If {@link #programSpliceFlag} is false, a non-empty list containing the {@link + * ComponentSplice}s. Otherwise, an empty list. */ public final List componentSpliceList; /** - * If {@link #breakDurationUs} is not {@link C#TIME_UNSET}, defines whether - * {@link #breakDurationUs} should be used to know when to return to the network feed. If - * {@link #breakDurationUs} is {@link C#TIME_UNSET}, the value is undefined. + * If {@link #breakDurationUs} is not {@link C#TIME_UNSET}, defines whether {@link + * #breakDurationUs} should be used to know when to return to the network feed. If {@link + * #breakDurationUs} is {@link C#TIME_UNSET}, the value is undefined. */ public final boolean autoReturn; /** @@ -70,23 +64,25 @@ public static final class Event { * present. */ public final long breakDurationUs; - /** - * The unique program id as defined in SCTE35, Section 9.3.2. - */ + /** The unique program id as defined in SCTE35, Section 9.3.2. */ public final int uniqueProgramId; - /** - * Holds the value of {@code avail_num} as defined in SCTE35, Section 9.3.2. - */ + /** Holds the value of {@code avail_num} as defined in SCTE35, Section 9.3.2. */ public final int availNum; - /** - * Holds the value of {@code avails_expected} as defined in SCTE35, Section 9.3.2. - */ + /** Holds the value of {@code avails_expected} as defined in SCTE35, Section 9.3.2. */ public final int availsExpected; - private Event(long spliceEventId, boolean spliceEventCancelIndicator, - boolean outOfNetworkIndicator, boolean programSpliceFlag, - List componentSpliceList, long utcSpliceTime, boolean autoReturn, - long breakDurationUs, int uniqueProgramId, int availNum, int availsExpected) { + private Event( + long spliceEventId, + boolean spliceEventCancelIndicator, + boolean outOfNetworkIndicator, + boolean programSpliceFlag, + List componentSpliceList, + long utcSpliceTime, + boolean autoReturn, + long breakDurationUs, + int uniqueProgramId, + int availNum, + int availsExpected) { this.spliceEventId = spliceEventId; this.spliceEventCancelIndicator = spliceEventCancelIndicator; this.outOfNetworkIndicator = outOfNetworkIndicator; @@ -159,9 +155,18 @@ private static Event parseFromSection(ParsableByteArray sectionData) { availNum = sectionData.readUnsignedByte(); availsExpected = sectionData.readUnsignedByte(); } - return new Event(spliceEventId, spliceEventCancelIndicator, outOfNetworkIndicator, - programSpliceFlag, componentSplices, utcSpliceTime, autoReturn, breakDurationUs, - uniqueProgramId, availNum, availsExpected); + return new Event( + spliceEventId, + spliceEventCancelIndicator, + outOfNetworkIndicator, + programSpliceFlag, + componentSplices, + utcSpliceTime, + autoReturn, + breakDurationUs, + uniqueProgramId, + availNum, + availsExpected); } private void writeToParcel(Parcel dest) { @@ -185,12 +190,9 @@ private void writeToParcel(Parcel dest) { private static Event createFromParcel(Parcel in) { return new Event(in); } - } - /** - * Holds splicing information for specific splice schedule command components. - */ + /** Holds splicing information for specific splice schedule command components. */ public static final class ComponentSplice { public final int componentTag; @@ -209,12 +211,9 @@ private void writeToParcel(Parcel dest) { dest.writeInt(componentTag); dest.writeLong(utcSpliceTime); } - } - /** - * The list of scheduled events. - */ + /** The list of scheduled events. */ public final List events; private SpliceScheduleCommand(List events) { @@ -253,16 +252,14 @@ public void writeToParcel(Parcel dest, int flags) { public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override - public SpliceScheduleCommand createFromParcel(Parcel in) { - return new SpliceScheduleCommand(in); - } - - @Override - public SpliceScheduleCommand[] newArray(int size) { - return new SpliceScheduleCommand[size]; - } - - }; + @Override + public SpliceScheduleCommand createFromParcel(Parcel in) { + return new SpliceScheduleCommand(in); + } + @Override + public SpliceScheduleCommand[] newArray(int size) { + return new SpliceScheduleCommand[size]; + } + }; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/TimeSignalCommand.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/TimeSignalCommand.java index 5115b7a7227..aec2a91731c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/TimeSignalCommand.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/TimeSignalCommand.java @@ -23,13 +23,9 @@ /** Represents a time signal command as defined in SCTE35, Section 9.3.4. */ public final class TimeSignalCommand extends SpliceCommand { - /** - * A PTS value, as defined in SCTE35, Section 9.3.4. - */ + /** A PTS value, as defined in SCTE35, Section 9.3.4. */ public final long ptsTime; - /** - * Equivalent to {@link #ptsTime} but in the playback timebase. - */ + /** Equivalent to {@link #ptsTime} but in the playback timebase. */ public final long playbackPositionUs; private TimeSignalCommand(long ptsTime, long playbackPositionUs) { @@ -37,8 +33,8 @@ private TimeSignalCommand(long ptsTime, long playbackPositionUs) { this.playbackPositionUs = playbackPositionUs; } - /* package */ static TimeSignalCommand parseFromSection(ParsableByteArray sectionData, - long ptsAdjustment, TimestampAdjuster timestampAdjuster) { + /* package */ static TimeSignalCommand parseFromSection( + ParsableByteArray sectionData, long ptsAdjustment, TimestampAdjuster timestampAdjuster) { long ptsTime = parseSpliceTime(sectionData, ptsAdjustment); long playbackPositionUs = timestampAdjuster.adjustTsTimestamp(ptsTime); return new TimeSignalCommand(ptsTime, playbackPositionUs); @@ -76,16 +72,14 @@ public void writeToParcel(Parcel dest, int flags) { public static final Creator CREATOR = new Creator() { - @Override - public TimeSignalCommand createFromParcel(Parcel in) { - return new TimeSignalCommand(in.readLong(), in.readLong()); - } - - @Override - public TimeSignalCommand[] newArray(int size) { - return new TimeSignalCommand[size]; - } - - }; + @Override + public TimeSignalCommand createFromParcel(Parcel in) { + return new TimeSignalCommand(in.readLong(), in.readLong()); + } + @Override + public TimeSignalCommand[] newArray(int size) { + return new TimeSignalCommand[size]; + } + }; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloadIndex.java b/library/core/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloadIndex.java index 2a62b0602c9..3388424e6e8 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloadIndex.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloadIndex.java @@ -15,12 +15,15 @@ */ package com.google.android.exoplayer2.offline; +import static com.google.android.exoplayer2.util.Assertions.checkNotNull; + import android.content.ContentValues; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.net.Uri; +import android.text.TextUtils; import androidx.annotation.GuardedBy; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; @@ -371,7 +374,7 @@ private List loadDownloadsFromVersion2(SQLiteDatabase database) { } /** Infers the MIME type from a v2 table row. */ - private static String inferMimeType(String downloadType) { + private static String inferMimeType(@Nullable String downloadType) { if ("dash".equals(downloadType)) { return MimeTypes.APPLICATION_MPD; } else if ("hls".equals(downloadType)) { @@ -441,8 +444,8 @@ private static Download getDownloadForCurrentRow(Cursor cursor) { byte[] keySetId = cursor.getBlob(COLUMN_INDEX_KEY_SET_ID); DownloadRequest request = new DownloadRequest.Builder( - /* id= */ cursor.getString(COLUMN_INDEX_ID), - /* uri= */ Uri.parse(cursor.getString(COLUMN_INDEX_URI))) + /* id= */ checkNotNull(cursor.getString(COLUMN_INDEX_ID)), + /* uri= */ Uri.parse(checkNotNull(cursor.getString(COLUMN_INDEX_URI)))) .setMimeType(cursor.getString(COLUMN_INDEX_MIME_TYPE)) .setStreamKeys(decodeStreamKeys(cursor.getString(COLUMN_INDEX_STREAM_KEYS))) .setKeySetId(keySetId.length > 0 ? keySetId : null) @@ -493,7 +496,8 @@ private static Download getDownloadForCurrentRowV2(Cursor cursor) { */ DownloadRequest request = new DownloadRequest.Builder( - /* id= */ cursor.getString(0), /* uri= */ Uri.parse(cursor.getString(2))) + /* id= */ checkNotNull(cursor.getString(0)), + /* uri= */ Uri.parse(checkNotNull(cursor.getString(2)))) .setMimeType(inferMimeType(cursor.getString(1))) .setStreamKeys(decodeStreamKeys(cursor.getString(3))) .setCustomCacheKey(cursor.getString(4)) @@ -519,9 +523,9 @@ private static Download getDownloadForCurrentRowV2(Cursor cursor) { downloadProgress); } - private static List decodeStreamKeys(String encodedStreamKeys) { + private static List decodeStreamKeys(@Nullable String encodedStreamKeys) { ArrayList streamKeys = new ArrayList<>(); - if (encodedStreamKeys.isEmpty()) { + if (TextUtils.isEmpty(encodedStreamKeys)) { return streamKeys; } String[] streamKeysStrings = Util.split(encodedStreamKeys, ","); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloaderFactory.java b/library/core/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloaderFactory.java index 365a4439a13..bed0bb26a3b 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloaderFactory.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloaderFactory.java @@ -108,7 +108,6 @@ private Downloader createDownloader(DownloadRequest request, @C.ContentType int } } - // LINT.IfChange private static SparseArray> createDownloaderConstructors() { SparseArray> array = new SparseArray<>(); try { @@ -150,5 +149,4 @@ private static Constructor getDownloaderConstructor(Class< throw new IllegalStateException("Downloader constructor missing", e); } } - // LINT.ThenChange(../../../../../../../../proguard-rules.txt) } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadException.java b/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadException.java index 983727c14de..2f7d7eba89e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadException.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadException.java @@ -29,5 +29,4 @@ public DownloadException(String message) { public DownloadException(Throwable cause) { super(cause); } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadHelper.java b/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadHelper.java index 27ff0a7956a..38448f61b60 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadHelper.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadHelper.java @@ -822,7 +822,7 @@ private void setPreparedWithMedia() { "mediaPreparer.timeline", "mediaPreparer.mediaPeriods" }) - @SuppressWarnings("nullness:contracts.postcondition.not.satisfied") + @SuppressWarnings("nullness:contracts.postcondition") private void assertPreparedWithMedia() { Assertions.checkState(isPreparedWithMedia); } @@ -931,7 +931,7 @@ public MediaPreparer(MediaSource mediaSource, DownloadHelper downloadHelper) { this.downloadHelper = downloadHelper; allocator = new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE); pendingMediaPeriods = new ArrayList<>(); - @SuppressWarnings("methodref.receiver.bound.invalid") + @SuppressWarnings("nullness:methodref.receiver.bound") Handler downloadThreadHandler = Util.createHandlerForCurrentOrMainLooper(this::handleDownloadHelperCallbackMessage); this.downloadHelperHandler = downloadThreadHandler; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java b/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java index a989e2575f7..95705a9caaf 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java @@ -255,7 +255,7 @@ public DownloadManager( downloads = Collections.emptyList(); listeners = new CopyOnWriteArraySet<>(); - @SuppressWarnings("methodref.receiver.bound.invalid") + @SuppressWarnings("nullness:methodref.receiver.bound") Handler mainHandler = Util.createHandlerForCurrentOrMainLooper(this::handleMainMessage); this.applicationHandler = mainHandler; HandlerThread internalThread = new HandlerThread("ExoPlayer:DownloadManager"); @@ -270,7 +270,7 @@ public DownloadManager( minRetryCount, downloadsPaused); - @SuppressWarnings("methodref.receiver.bound.invalid") + @SuppressWarnings("nullness:methodref.receiver.bound") RequirementsWatcher.Listener requirementsListener = this::onRequirementsStateChanged; this.requirementsListener = requirementsListener; requirementsWatcher = @@ -1316,7 +1316,7 @@ private Task( contentLength = C.LENGTH_UNSET; } - @SuppressWarnings("nullness:assignment.type.incompatible") + @SuppressWarnings("nullness:assignment") public void cancel(boolean released) { if (released) { // Download threads are GC roots for as long as they're running. The time taken for diff --git a/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloaderFactory.java b/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloaderFactory.java index f98ca3eac33..435c5aa00cf 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloaderFactory.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloaderFactory.java @@ -21,8 +21,8 @@ public interface DownloaderFactory { /** * Creates a {@link Downloader} to perform the given {@link DownloadRequest}. * - * @param action The action. + * @param request The download request. * @return The downloader. */ - Downloader createDownloader(DownloadRequest action); + Downloader createDownloader(DownloadRequest request); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/offline/ProgressiveDownloader.java b/library/core/src/main/java/com/google/android/exoplayer2/offline/ProgressiveDownloader.java index 35a3e788f53..5be5ea785df 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/offline/ProgressiveDownloader.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/offline/ProgressiveDownloader.java @@ -15,7 +15,6 @@ */ package com.google.android.exoplayer2.offline; -import android.net.Uri; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.MediaItem; @@ -45,14 +44,6 @@ public final class ProgressiveDownloader implements Downloader { private volatile @MonotonicNonNull RunnableFutureTask downloadRunnable; private volatile boolean isCanceled; - /** @deprecated Use {@link #ProgressiveDownloader(MediaItem, CacheDataSource.Factory)} instead. */ - @SuppressWarnings("deprecation") - @Deprecated - public ProgressiveDownloader( - Uri uri, @Nullable String customCacheKey, CacheDataSource.Factory cacheDataSourceFactory) { - this(uri, customCacheKey, cacheDataSourceFactory, Runnable::run); - } - /** * Creates a new instance. * @@ -65,22 +56,6 @@ public ProgressiveDownloader( this(mediaItem, cacheDataSourceFactory, Runnable::run); } - /** - * @deprecated Use {@link #ProgressiveDownloader(MediaItem, CacheDataSource.Factory, Executor)} - * instead. - */ - @Deprecated - public ProgressiveDownloader( - Uri uri, - @Nullable String customCacheKey, - CacheDataSource.Factory cacheDataSourceFactory, - Executor executor) { - this( - new MediaItem.Builder().setUri(uri).setCustomCacheKey(customCacheKey).build(), - cacheDataSourceFactory, - executor); - } - /** * Creates a new instance. * @@ -102,14 +77,10 @@ public ProgressiveDownloader( .setFlags(DataSpec.FLAG_ALLOW_CACHE_FRAGMENTATION) .build(); dataSource = cacheDataSourceFactory.createDataSourceForDownloading(); - @SuppressWarnings("methodref.receiver.bound.invalid") + @SuppressWarnings("nullness:methodref.receiver.bound") CacheWriter.ProgressListener progressListener = this::onProgress; cacheWriter = - new CacheWriter( - dataSource, - dataSpec, - /* temporaryBuffer= */ null, - progressListener); + new CacheWriter(dataSource, dataSpec, /* temporaryBuffer= */ null, progressListener); priorityTaskManager = cacheDataSourceFactory.getUpstreamPriorityTaskManager(); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/offline/SegmentDownloader.java b/library/core/src/main/java/com/google/android/exoplayer2/offline/SegmentDownloader.java index 74df93d82f7..7156f50a22c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/offline/SegmentDownloader.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/offline/SegmentDownloader.java @@ -469,11 +469,7 @@ public SegmentDownloadRunnable( this.progressNotifier = progressNotifier; this.temporaryBuffer = temporaryBuffer; this.cacheWriter = - new CacheWriter( - dataSource, - segment.dataSpec, - temporaryBuffer, - progressNotifier); + new CacheWriter(dataSource, segment.dataSpec, temporaryBuffer, progressNotifier); } @Override diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/BehindLiveWindowException.java b/library/core/src/main/java/com/google/android/exoplayer2/source/BehindLiveWindowException.java index 2d56762175f..743659773ad 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/BehindLiveWindowException.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/BehindLiveWindowException.java @@ -23,5 +23,4 @@ public final class BehindLiveWindowException extends IOException { public BehindLiveWindowException() { super(); } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaSource.java index 6a586054804..1a9ad2dae99 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaSource.java @@ -59,9 +59,7 @@ public static final class IllegalClippingException extends IOException { /** The reason clipping failed. */ public final @Reason int reason; - /** - * @param reason The reason clipping failed. - */ + /** @param reason The reason clipping failed. */ public IllegalClippingException(@Reason int reason) { super("Illegal clipping: " + getReasonDescription(reason)); this.reason = reason; @@ -188,17 +186,6 @@ public ClippingMediaSource( window = new Timeline.Window(); } - /** - * @deprecated Use {@link #getMediaItem()} and {@link MediaItem.PlaybackProperties#tag} instead. - */ - @SuppressWarnings("deprecation") - @Deprecated - @Override - @Nullable - public Object getTag() { - return mediaSource.getTag(); - } - @Override public MediaItem getMediaItem() { return mediaSource.getMediaItem(); @@ -293,9 +280,7 @@ private void refreshClippedTimeline(Timeline timeline) { refreshSourceInfo(clippingTimeline); } - /** - * Provides a clipped view of a specified timeline. - */ + /** Provides a clipped view of a specified timeline. */ private static final class ClippingTimeline extends ForwardingTimeline { private final long startUs; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/CompositeSequenceableLoaderFactory.java b/library/core/src/main/java/com/google/android/exoplayer2/source/CompositeSequenceableLoaderFactory.java index 1507068664c..84922454429 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/CompositeSequenceableLoaderFactory.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/CompositeSequenceableLoaderFactory.java @@ -25,5 +25,4 @@ public interface CompositeSequenceableLoaderFactory { * @return A composite {@link SequenceableLoader} that comprises the given loaders. */ SequenceableLoader createCompositeSequenceableLoader(SequenceableLoader... loaders); - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java index 48305bc9166..bb9098be4d5 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java @@ -86,8 +86,8 @@ public final class ConcatenatingMediaSource extends CompositeMediaSource to the app). *

      • {@link ProgressiveMediaSource.Factory} serves as a fallback if the item's {@link * MediaItem.PlaybackProperties#uri uri} doesn't match one of the above. It tries to infer the - * required extractor by using the {@link - * com.google.android.exoplayer2.extractor.DefaultExtractorsFactory} or the {@link + * required extractor by using the {@link DefaultExtractorsFactory} or the {@link * ExtractorsFactory} provided in the constructor. An {@link UnrecognizedInputFormatException} * is thrown if none of the available extractors can read the stream. *
      * - *

      Ad support for media items with ad tag URIs

      + *

      Ad support for media items with ad tag URIs

      * *

      To support media items with {@link MediaItem.PlaybackProperties#adsConfiguration ads * configuration}, {@link #setAdsLoaderProvider} and {@link #setAdViewProvider} need to be called to @@ -437,7 +436,6 @@ private MediaSource maybeWrapWithAdsMediaSource(MediaItem mediaItem, MediaSource private static SparseArray loadDelegates( DataSource.Factory dataSourceFactory, ExtractorsFactory extractorsFactory) { SparseArray factories = new SparseArray<>(); - // LINT.IfChange try { Class factoryClazz = Class.forName("com.google.android.exoplayer2.source.dash.DashMediaSource$Factory") @@ -477,7 +475,6 @@ private static SparseArray loadDelegates( } catch (Exception e) { // Expected if the app was built without the RTSP module. } - // LINT.ThenChange(../../../../../../../../proguard-rules.txt) factories.put( C.TYPE_OTHER, new ProgressiveMediaSource.Factory(dataSourceFactory, extractorsFactory)); return factories; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ForwardingTimeline.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ForwardingTimeline.java index fb732ad10d4..009c6466d19 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ForwardingTimeline.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ForwardingTimeline.java @@ -33,14 +33,14 @@ public int getWindowCount() { } @Override - public int getNextWindowIndex(int windowIndex, @Player.RepeatMode int repeatMode, - boolean shuffleModeEnabled) { + public int getNextWindowIndex( + int windowIndex, @Player.RepeatMode int repeatMode, boolean shuffleModeEnabled) { return timeline.getNextWindowIndex(windowIndex, repeatMode, shuffleModeEnabled); } @Override - public int getPreviousWindowIndex(int windowIndex, @Player.RepeatMode int repeatMode, - boolean shuffleModeEnabled) { + public int getPreviousWindowIndex( + int windowIndex, @Player.RepeatMode int repeatMode, boolean shuffleModeEnabled) { return timeline.getPreviousWindowIndex(windowIndex, repeatMode, shuffleModeEnabled); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/IcyDataSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/IcyDataSource.java index 285b9f3fef0..cab324fc136 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/IcyDataSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/IcyDataSource.java @@ -79,7 +79,7 @@ public long open(DataSpec dataSpec) { } @Override - public int read(byte[] buffer, int offset, int readLength) throws IOException { + public int read(byte[] buffer, int offset, int length) throws IOException { if (bytesUntilMetadata == 0) { if (readMetadata()) { bytesUntilMetadata = metadataIntervalBytes; @@ -87,7 +87,7 @@ public int read(byte[] buffer, int offset, int readLength) throws IOException { return C.RESULT_END_OF_INPUT; } } - int bytesRead = upstream.read(buffer, offset, min(bytesUntilMetadata, readLength)); + int bytesRead = upstream.read(buffer, offset, min(bytesUntilMetadata, length)); if (bytesRead != C.RESULT_END_OF_INPUT) { bytesUntilMetadata -= bytesRead; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/LoopingMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/LoopingMediaSource.java index d10651a575c..99e62728acc 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/LoopingMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/LoopingMediaSource.java @@ -49,8 +49,8 @@ public final class LoopingMediaSource extends CompositeMediaSource { private final Map mediaPeriodToChildMediaPeriodId; /** - * Loops the provided source indefinitely. Note that it is usually better to use - * {@link ExoPlayer#setRepeatMode(int)}. + * Loops the provided source indefinitely. Note that it is usually better to use {@link + * ExoPlayer#setRepeatMode(int)}. * * @param childSource The {@link MediaSource} to loop. */ @@ -72,17 +72,6 @@ public LoopingMediaSource(MediaSource childSource, int loopCount) { mediaPeriodToChildMediaPeriodId = new HashMap<>(); } - /** - * @deprecated Use {@link #getMediaItem()} and {@link MediaItem.PlaybackProperties#tag} instead. - */ - @SuppressWarnings("deprecation") - @Deprecated - @Override - @Nullable - public Object getTag() { - return maskingMediaSource.getTag(); - } - @Override public MediaItem getMediaItem() { return maskingMediaSource.getMediaItem(); @@ -163,7 +152,8 @@ public LoopingTimeline(Timeline childTimeline, int loopCount) { childWindowCount = childTimeline.getWindowCount(); this.loopCount = loopCount; if (childPeriodCount > 0) { - Assertions.checkState(loopCount <= Integer.MAX_VALUE / childPeriodCount, + Assertions.checkState( + loopCount <= Integer.MAX_VALUE / childPeriodCount, "LoopingMediaSource contains too many periods"); } } @@ -215,7 +205,6 @@ protected int getFirstWindowIndexByChildIndex(int childIndex) { protected Object getChildUidByChildIndex(int childIndex) { return childIndex; } - } private static final class InfinitelyLoopingTimeline extends ForwardingTimeline { @@ -225,23 +214,23 @@ public InfinitelyLoopingTimeline(Timeline timeline) { } @Override - public int getNextWindowIndex(int windowIndex, @Player.RepeatMode int repeatMode, - boolean shuffleModeEnabled) { - int childNextWindowIndex = timeline.getNextWindowIndex(windowIndex, repeatMode, - shuffleModeEnabled); - return childNextWindowIndex == C.INDEX_UNSET ? getFirstWindowIndex(shuffleModeEnabled) + public int getNextWindowIndex( + int windowIndex, @Player.RepeatMode int repeatMode, boolean shuffleModeEnabled) { + int childNextWindowIndex = + timeline.getNextWindowIndex(windowIndex, repeatMode, shuffleModeEnabled); + return childNextWindowIndex == C.INDEX_UNSET + ? getFirstWindowIndex(shuffleModeEnabled) : childNextWindowIndex; } @Override - public int getPreviousWindowIndex(int windowIndex, @Player.RepeatMode int repeatMode, - boolean shuffleModeEnabled) { - int childPreviousWindowIndex = timeline.getPreviousWindowIndex(windowIndex, repeatMode, - shuffleModeEnabled); - return childPreviousWindowIndex == C.INDEX_UNSET ? getLastWindowIndex(shuffleModeEnabled) + public int getPreviousWindowIndex( + int windowIndex, @Player.RepeatMode int repeatMode, boolean shuffleModeEnabled) { + int childPreviousWindowIndex = + timeline.getPreviousWindowIndex(windowIndex, repeatMode, shuffleModeEnabled); + return childPreviousWindowIndex == C.INDEX_UNSET + ? getLastWindowIndex(shuffleModeEnabled) : childPreviousWindowIndex; } - } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/MaskingMediaPeriod.java b/library/core/src/main/java/com/google/android/exoplayer2/source/MaskingMediaPeriod.java index 2151119abf5..7c60a379c7f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/MaskingMediaPeriod.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/MaskingMediaPeriod.java @@ -139,7 +139,7 @@ public void releasePeriod() { } @Override - public void prepare(Callback callback, long preparePositionUs) { + public void prepare(Callback callback, long positionUs) { this.callback = callback; if (mediaPeriod != null) { mediaPeriod.prepare( diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/MaskingMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/MaskingMediaSource.java index e7c27ba95ee..c1744ed57a6 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/MaskingMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/MaskingMediaSource.java @@ -86,17 +86,6 @@ public void prepareSourceInternal(@Nullable TransferListener mediaTransferListen } } - /** - * @deprecated Use {@link #getMediaItem()} and {@link MediaItem.PlaybackProperties#tag} instead. - */ - @SuppressWarnings("deprecation") - @Deprecated - @Override - @Nullable - public Object getTag() { - return mediaSource.getTag(); - } - @Override public MediaItem getMediaItem() { return mediaSource.getMediaItem(); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/MediaLoadData.java b/library/core/src/main/java/com/google/android/exoplayer2/source/MediaLoadData.java index 683912448d1..5f5eb38db7f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/MediaLoadData.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/MediaLoadData.java @@ -17,13 +17,14 @@ import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.C.DataType; import com.google.android.exoplayer2.Format; /** Descriptor for data being loaded or selected by a {@link MediaSource}. */ public final class MediaLoadData { - /** One of the {@link C} {@code DATA_TYPE_*} constants defining the type of data. */ - public final int dataType; + /** The {@link DataType data type}. */ + @DataType public final int dataType; /** * One of the {@link C} {@code TRACK_TYPE_*} constants if the data corresponds to media of a * specific type. {@link C#TRACK_TYPE_UNKNOWN} otherwise. @@ -56,7 +57,7 @@ public final class MediaLoadData { public final long mediaEndTimeMs; /** Creates an instance with the given {@link #dataType}. */ - public MediaLoadData(int dataType) { + public MediaLoadData(@DataType int dataType) { this( dataType, /* trackType= */ C.TRACK_TYPE_UNKNOWN, @@ -79,7 +80,7 @@ public MediaLoadData(int dataType) { * @param mediaEndTimeMs See {@link #mediaEndTimeMs}. */ public MediaLoadData( - int dataType, + @DataType int dataType, int trackType, @Nullable Format trackFormat, int trackSelectionReason, diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSource.java index 4b5229ba00e..2117883f4d2 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSource.java @@ -180,15 +180,6 @@ default boolean isSingleWindow() { return true; } - /** - * @deprecated Use {@link #getMediaItem()} and {@link MediaItem.PlaybackProperties#tag} instead. - */ - @Deprecated - @Nullable - default Object getTag() { - return null; - } - /** Returns the {@link MediaItem} whose media is provided by the source. */ MediaItem getMediaItem(); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSourceEventListener.java b/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSourceEventListener.java index c5859fecbc5..115bff2a99e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSourceEventListener.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSourceEventListener.java @@ -21,6 +21,7 @@ import androidx.annotation.CheckResult; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.C.DataType; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; @@ -212,7 +213,7 @@ public void removeEventListener(MediaSourceEventListener eventListener) { } /** Dispatches {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */ - public void loadStarted(LoadEventInfo loadEventInfo, int dataType) { + public void loadStarted(LoadEventInfo loadEventInfo, @DataType int dataType) { loadStarted( loadEventInfo, dataType, @@ -227,7 +228,7 @@ public void loadStarted(LoadEventInfo loadEventInfo, int dataType) { /** Dispatches {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */ public void loadStarted( LoadEventInfo loadEventInfo, - int dataType, + @DataType int dataType, int trackType, @Nullable Format trackFormat, int trackSelectionReason, @@ -257,7 +258,7 @@ public void loadStarted(LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData } /** Dispatches {@link #onLoadCompleted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */ - public void loadCompleted(LoadEventInfo loadEventInfo, int dataType) { + public void loadCompleted(LoadEventInfo loadEventInfo, @DataType int dataType) { loadCompleted( loadEventInfo, dataType, @@ -272,7 +273,7 @@ public void loadCompleted(LoadEventInfo loadEventInfo, int dataType) { /** Dispatches {@link #onLoadCompleted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */ public void loadCompleted( LoadEventInfo loadEventInfo, - int dataType, + @DataType int dataType, int trackType, @Nullable Format trackFormat, int trackSelectionReason, @@ -303,7 +304,7 @@ public void loadCompleted(LoadEventInfo loadEventInfo, MediaLoadData mediaLoadDa } /** Dispatches {@link #onLoadCanceled(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */ - public void loadCanceled(LoadEventInfo loadEventInfo, int dataType) { + public void loadCanceled(LoadEventInfo loadEventInfo, @DataType int dataType) { loadCanceled( loadEventInfo, dataType, @@ -318,7 +319,7 @@ public void loadCanceled(LoadEventInfo loadEventInfo, int dataType) { /** Dispatches {@link #onLoadCanceled(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */ public void loadCanceled( LoadEventInfo loadEventInfo, - int dataType, + @DataType int dataType, int trackType, @Nullable Format trackFormat, int trackSelectionReason, @@ -353,7 +354,10 @@ public void loadCanceled(LoadEventInfo loadEventInfo, MediaLoadData mediaLoadDat * boolean)}. */ public void loadError( - LoadEventInfo loadEventInfo, int dataType, IOException error, boolean wasCanceled) { + LoadEventInfo loadEventInfo, + @DataType int dataType, + IOException error, + boolean wasCanceled) { loadError( loadEventInfo, dataType, @@ -373,7 +377,7 @@ public void loadError( */ public void loadError( LoadEventInfo loadEventInfo, - int dataType, + @DataType int dataType, int trackType, @Nullable Format trackFormat, int trackSelectionReason, diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/MergingMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/MergingMediaSource.java index 3a9bfe4f918..f4d44b95404 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/MergingMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/MergingMediaSource.java @@ -44,9 +44,7 @@ */ public final class MergingMediaSource extends CompositeMediaSource { - /** - * Thrown when a {@link MergingMediaSource} cannot merge its sources. - */ + /** Thrown when a {@link MergingMediaSource} cannot merge its sources. */ public static final class IllegalMergeException extends IOException { /** The reason the merge failed. One of {@link #REASON_PERIOD_COUNT_MISMATCH}. */ @@ -54,23 +52,16 @@ public static final class IllegalMergeException extends IOException { @Retention(RetentionPolicy.SOURCE) @IntDef({REASON_PERIOD_COUNT_MISMATCH}) public @interface Reason {} - /** - * The sources have different period counts. - */ + /** The sources have different period counts. */ public static final int REASON_PERIOD_COUNT_MISMATCH = 0; - /** - * The reason the merge failed. - */ + /** The reason the merge failed. */ @Reason public final int reason; - /** - * @param reason The reason the merge failed. - */ + /** @param reason The reason the merge failed. */ public IllegalMergeException(@Reason int reason) { this.reason = reason; } - } private static final int PERIOD_COUNT_UNSET = -1; @@ -163,17 +154,6 @@ public MergingMediaSource( clippedMediaPeriods = MultimapBuilder.hashKeys().arrayListValues().build(); } - /** - * @deprecated Use {@link #getMediaItem()} and {@link MediaItem.PlaybackProperties#tag} instead. - */ - @SuppressWarnings("deprecation") - @Deprecated - @Override - @Nullable - public Object getTag() { - return mediaSources.length > 0 ? mediaSources[0].getTag() : null; - } - @Override public MediaItem getMediaItem() { return mediaSources.length > 0 ? mediaSources[0].getMediaItem() : EMPTY_MEDIA_ITEM; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriod.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriod.java index 791dd724796..2ffe134fa4e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriod.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriod.java @@ -22,6 +22,7 @@ import android.os.Handler; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.C.DataType; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.FormatHolder; import com.google.android.exoplayer2.ParserException; @@ -73,9 +74,7 @@ Loader.ReleaseCallback, UpstreamFormatChangedListener { - /** - * Listener for information about the period. - */ + /** Listener for information about the period. */ interface Listener { /** @@ -129,7 +128,7 @@ interface Listener { private @MonotonicNonNull SeekMap seekMap; private long durationUs; private boolean isLive; - private int dataType; + @DataType private int dataType; private boolean seenFirstTrackSelection; private boolean notifyDiscontinuity; @@ -162,10 +161,7 @@ interface Listener { * invocation of {@link Callback#onContinueLoadingRequested(SequenceableLoader)}. */ // maybeFinishPrepare is not posted to the handler until initialization completes. - @SuppressWarnings({ - "nullness:argument.type.incompatible", - "nullness:methodref.receiver.bound.invalid" - }) + @SuppressWarnings({"nullness:argument", "nullness:methodref.receiver.bound"}) public ProgressiveMediaPeriod( Uri uri, DataSource dataSource, @@ -241,7 +237,8 @@ public void prepare(Callback callback, long positionUs) { public void maybeThrowPrepareError() throws IOException { maybeThrowError(); if (loadingFinished && !prepared) { - throw new ParserException("Loading finished before preparation is complete."); + throw ParserException.createForMalformedContainer( + "Loading finished before preparation is complete.", /* cause= */ null); } } @@ -404,7 +401,8 @@ public long getBufferedPositionUs() { if (largestQueuedTimestampUs == Long.MAX_VALUE) { largestQueuedTimestampUs = getLargestQueuedTimestampUs(); } - return largestQueuedTimestampUs == Long.MIN_VALUE ? lastSeekPositionUs + return largestQueuedTimestampUs == Long.MIN_VALUE + ? lastSeekPositionUs : largestQueuedTimestampUs; } @@ -552,8 +550,10 @@ public void onLoadCompleted( if (durationUs == C.TIME_UNSET && seekMap != null) { boolean isSeekable = seekMap.isSeekable(); long largestQueuedTimestampUs = getLargestQueuedTimestampUs(); - durationUs = largestQueuedTimestampUs == Long.MIN_VALUE ? 0 - : largestQueuedTimestampUs + DEFAULT_LAST_SAMPLE_DURATION_US; + durationUs = + largestQueuedTimestampUs == Long.MIN_VALUE + ? 0 + : largestQueuedTimestampUs + DEFAULT_LAST_SAMPLE_DURATION_US; listener.onSourceInfoRefreshed(durationUs, isSeekable, isLive); } StatsDataSource dataSource = loadable.dataSource; @@ -844,8 +844,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 (length != C.LENGTH_UNSET || (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; @@ -957,7 +956,6 @@ public int readData( public int skipData(long positionUs) { return ProgressiveMediaPeriod.this.skipData(track, positionUs); } - } /** Loads the media stream and extracts sample data from it. */ @@ -980,7 +978,7 @@ public int skipData(long positionUs) { @Nullable private TrackOutput icyTrackOutput; private boolean seenIcyMetadata; - @SuppressWarnings("method.invocation.invalid") + @SuppressWarnings("nullness:method.invocation") public ExtractingLoadable( Uri uri, DataSource dataSource, diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaSource.java index 4c9ce824950..9243ed59751 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaSource.java @@ -283,17 +283,6 @@ private ProgressiveMediaSource( this.timelineDurationUs = C.TIME_UNSET; } - /** - * @deprecated Use {@link #getMediaItem()} and {@link MediaItem.PlaybackProperties#tag} instead. - */ - @SuppressWarnings("deprecation") - @Deprecated - @Override - @Nullable - public Object getTag() { - return playbackProperties.tag; - } - @Override public MediaItem getMediaItem() { return mediaItem; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java index def7cb16bbf..7b5c6a35f73 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java @@ -581,8 +581,8 @@ public final int sampleData( @Override public final void sampleData( - ParsableByteArray buffer, int length, @SampleDataPart int sampleDataPart) { - sampleDataQueue.sampleData(buffer, length); + ParsableByteArray data, int length, @SampleDataPart int sampleDataPart) { + sampleDataQueue.sampleData(data, length); } @Override diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SequenceableLoader.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SequenceableLoader.java index e500d0520ac..91f0e9b820a 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/SequenceableLoader.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SequenceableLoader.java @@ -21,9 +21,7 @@ /** A loader that can proceed in approximate synchronization with other loaders. */ public interface SequenceableLoader { - /** - * A callback to be notified of {@link SequenceableLoader} events. - */ + /** A callback to be notified of {@link SequenceableLoader} events. */ interface Callback { /** @@ -31,7 +29,6 @@ interface Callback { * to be called when it can continue to load data. Called on the playback thread. */ void onContinueLoadingRequested(T source); - } /** @@ -42,19 +39,17 @@ interface Callback { */ long getBufferedPositionUs(); - /** - * Returns the next load time, or {@link C#TIME_END_OF_SOURCE} if loading has finished. - */ + /** Returns the next load time, or {@link C#TIME_END_OF_SOURCE} if loading has finished. */ long getNextLoadPositionUs(); /** * Attempts to continue loading. * * @param positionUs The current playback position in microseconds. If playback of the period to - * which this loader belongs has not yet started, the value will be the starting position - * in the period minus the duration of any media in previous periods still to be played. - * @return True if progress was made, meaning that {@link #getNextLoadPositionUs()} will return - * a different value than prior to the call. False otherwise. + * which this loader belongs has not yet started, the value will be the starting position in + * the period minus the duration of any media in previous periods still to be played. + * @return True if progress was made, meaning that {@link #getNextLoadPositionUs()} will return a + * different value than prior to the call. False otherwise. */ boolean continueLoading(long positionUs); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ShuffleOrder.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ShuffleOrder.java index 5af9dbd20ac..e8f804fbe07 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ShuffleOrder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ShuffleOrder.java @@ -26,9 +26,7 @@ */ public interface ShuffleOrder { - /** - * The default {@link ShuffleOrder} implementation for random shuffle order. - */ + /** The default {@link ShuffleOrder} implementation for random shuffle order. */ class DefaultShuffleOrder implements ShuffleOrder { private final Random random; @@ -164,12 +162,9 @@ private static int[] createShuffledList(int length, Random random) { } return shuffled; } - } - /** - * A {@link ShuffleOrder} implementation which does not shuffle. - */ + /** A {@link ShuffleOrder} implementation which does not shuffle. */ final class UnshuffledShuffleOrder implements ShuffleOrder { private final int length; @@ -224,9 +219,7 @@ public ShuffleOrder cloneAndClear() { } } - /** - * Returns length of shuffle order. - */ + /** Returns length of shuffle order. */ int getLength(); /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SilenceMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SilenceMediaSource.java index 35e5e6f8c02..725100b583e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/SilenceMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SilenceMediaSource.java @@ -148,17 +148,6 @@ public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long star @Override public void releasePeriod(MediaPeriod mediaPeriod) {} - /** - * @deprecated Use {@link #getMediaItem()} and {@link MediaItem.PlaybackProperties#tag} instead. - */ - @SuppressWarnings("deprecation") - @Deprecated - @Nullable - @Override - public Object getTag() { - return Assertions.checkNotNull(mediaItem.playbackProperties).tag; - } - @Override public MediaItem getMediaItem() { return mediaItem; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java index 26438dbb77b..314946f90ae 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java @@ -351,6 +351,10 @@ public void maybeThrowError() throws IOException { public int readData( FormatHolder formatHolder, DecoderInputBuffer buffer, @ReadFlags int readFlags) { maybeNotifyDownstreamFormat(); + if (loadingFinished && sampleData == null) { + streamState = STREAM_STATE_END_OF_STREAM; + } + if (streamState == STREAM_STATE_END_OF_STREAM) { buffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM); return C.RESULT_BUFFER_READ; @@ -365,12 +369,7 @@ public int readData( if (!loadingFinished) { return C.RESULT_NOTHING_READ; } - - if (sampleData == null) { - buffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM); - streamState = STREAM_STATE_END_OF_STREAM; - return C.RESULT_BUFFER_READ; - } + Assertions.checkNotNull(sampleData); buffer.addFlag(C.BUFFER_FLAG_KEY_FRAME); buffer.timeUs = 0; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java index 3d557cf17d2..45f33c39c9b 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java @@ -16,7 +16,6 @@ package com.google.android.exoplayer2.source; import static com.google.android.exoplayer2.util.Assertions.checkNotNull; -import static com.google.android.exoplayer2.util.Util.castNonNull; import android.net.Uri; import androidx.annotation.Nullable; @@ -198,17 +197,6 @@ private SingleSampleMediaSource( // MediaSource implementation. - /** - * @deprecated Use {@link #getMediaItem()} and {@link MediaItem.PlaybackProperties#tag} instead. - */ - @SuppressWarnings("deprecation") - @Deprecated - @Override - @Nullable - public Object getTag() { - return castNonNull(mediaItem.playbackProperties).tag; - } - @Override public MediaItem getMediaItem() { return mediaItem; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/UnrecognizedInputFormatException.java b/library/core/src/main/java/com/google/android/exoplayer2/source/UnrecognizedInputFormatException.java index 324f89794a3..ec94e40777d 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/UnrecognizedInputFormatException.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/UnrecognizedInputFormatException.java @@ -16,14 +16,13 @@ package com.google.android.exoplayer2.source; import android.net.Uri; +import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ParserException; /** Thrown if the input format was not recognized. */ public class UnrecognizedInputFormatException extends ParserException { - /** - * The {@link Uri} from which the unrecognized data was read. - */ + /** The {@link Uri} from which the unrecognized data was read. */ public final Uri uri; /** @@ -31,8 +30,7 @@ public class UnrecognizedInputFormatException extends ParserException { * @param uri The {@link Uri} from which the unrecognized data was read. */ public UnrecognizedInputFormatException(String message, Uri uri) { - super(message); + super(message, /* cause= */ null, /* contentIsMalformed= */ false, C.DATA_TYPE_MEDIA); this.uri = uri; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsLoader.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsLoader.java index 906139cf76f..f937b0a07bb 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsLoader.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsLoader.java @@ -50,7 +50,7 @@ interface EventListener { /** * Called when the ad playback state has been updated. The number of {@link - * AdPlaybackState#adGroups ad groups} may not change after the first call. + * AdPlaybackState#adGroupCount ad groups} may not change after the first call. * * @param adPlaybackState The new ad playback state. */ diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java index f9a3daca869..182ead64d1f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java @@ -174,17 +174,6 @@ public AdsMediaSource( adsLoader.setSupportedContentTypes(adMediaSourceFactory.getSupportedTypes()); } - /** - * @deprecated Use {@link #getMediaItem()} and {@link MediaItem.PlaybackProperties#tag} instead. - */ - @SuppressWarnings("deprecation") - @Deprecated - @Override - @Nullable - public Object getTag() { - return contentMediaSource.getTag(); - } - @Override public MediaItem getMediaItem() { return contentMediaSource.getMediaItem(); @@ -316,11 +305,11 @@ private void maybeUpdateAdMediaSources() { @Nullable AdMediaSourceHolder adMediaSourceHolder = this.adMediaSourceHolders[adGroupIndex][adIndexInAdGroup]; + AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(adGroupIndex); if (adMediaSourceHolder != null && !adMediaSourceHolder.hasMediaSource() - && adPlaybackState.adGroups[adGroupIndex] != null - && adIndexInAdGroup < adPlaybackState.adGroups[adGroupIndex].uris.length) { - @Nullable Uri adUri = adPlaybackState.adGroups[adGroupIndex].uris[adIndexInAdGroup]; + && adIndexInAdGroup < adGroup.uris.length) { + @Nullable Uri adUri = adGroup.uris[adIndexInAdGroup]; if (adUri != null) { MediaItem.Builder adMediaItem = new MediaItem.Builder().setUri(adUri); // Propagate the content's DRM config into the ad media source. diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ads/ServerSideInsertedAdsMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/ServerSideInsertedAdsMediaSource.java new file mode 100644 index 00000000000..69588f504c9 --- /dev/null +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/ServerSideInsertedAdsMediaSource.java @@ -0,0 +1,1110 @@ +/* + * 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 com.google.android.exoplayer2.source.ads; + +import static com.google.android.exoplayer2.source.ads.ServerSideInsertedAdsUtil.getAdCountInGroup; +import static com.google.android.exoplayer2.source.ads.ServerSideInsertedAdsUtil.getMediaPeriodPositionUs; +import static com.google.android.exoplayer2.source.ads.ServerSideInsertedAdsUtil.getMediaPeriodPositionUsForAd; +import static com.google.android.exoplayer2.source.ads.ServerSideInsertedAdsUtil.getMediaPeriodPositionUsForContent; +import static com.google.android.exoplayer2.source.ads.ServerSideInsertedAdsUtil.getStreamPositionUs; +import static com.google.android.exoplayer2.util.Assertions.checkArgument; +import static com.google.android.exoplayer2.util.Assertions.checkNotNull; +import static com.google.android.exoplayer2.util.Util.castNonNull; + +import android.os.Handler; +import android.util.Pair; +import androidx.annotation.GuardedBy; +import androidx.annotation.Nullable; +import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.FormatHolder; +import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.SeekParameters; +import com.google.android.exoplayer2.Timeline; +import com.google.android.exoplayer2.decoder.DecoderInputBuffer; +import com.google.android.exoplayer2.drm.DrmSession; +import com.google.android.exoplayer2.drm.DrmSessionEventListener; +import com.google.android.exoplayer2.offline.StreamKey; +import com.google.android.exoplayer2.source.BaseMediaSource; +import com.google.android.exoplayer2.source.EmptySampleStream; +import com.google.android.exoplayer2.source.ForwardingTimeline; +import com.google.android.exoplayer2.source.LoadEventInfo; +import com.google.android.exoplayer2.source.MediaLoadData; +import com.google.android.exoplayer2.source.MediaPeriod; +import com.google.android.exoplayer2.source.MediaSource; +import com.google.android.exoplayer2.source.MediaSourceEventListener; +import com.google.android.exoplayer2.source.SampleStream; +import com.google.android.exoplayer2.source.TrackGroup; +import com.google.android.exoplayer2.source.TrackGroupArray; +import com.google.android.exoplayer2.trackselection.ExoTrackSelection; +import com.google.android.exoplayer2.upstream.Allocator; +import com.google.android.exoplayer2.upstream.TransferListener; +import com.google.android.exoplayer2.util.Assertions; +import com.google.android.exoplayer2.util.Util; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Iterables; +import com.google.common.collect.ListMultimap; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.checkerframework.checker.nullness.compatqual.NullableType; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; + +/** + * A {@link MediaSource} for server-side inserted ad breaks. + * + *

      The media source publishes a {@link Timeline} for the wrapped {@link MediaSource} with the + * server-side inserted ad breaks and ensures that playback continues seamlessly with the wrapped + * media across all transitions. + * + *

      The ad breaks need to be specified using {@link #setAdPlaybackState} and can be updated during + * playback. + */ +public final class ServerSideInsertedAdsMediaSource extends BaseMediaSource + implements MediaSource.MediaSourceCaller, MediaSourceEventListener, DrmSessionEventListener { + + private final MediaSource mediaSource; + private final ListMultimap mediaPeriods; + private final MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcherWithoutId; + private final DrmSessionEventListener.EventDispatcher drmEventDispatcherWithoutId; + + @GuardedBy("this") + @Nullable + private Handler playbackHandler; + + @Nullable private SharedMediaPeriod lastUsedMediaPeriod; + @Nullable private Timeline contentTimeline; + private AdPlaybackState adPlaybackState; + + /** + * Creates the media source. + * + * @param mediaSource The {@link MediaSource} to wrap. + */ + // Calling BaseMediaSource.createEventDispatcher from the constructor. + @SuppressWarnings("nullness:method.invocation") + public ServerSideInsertedAdsMediaSource(MediaSource mediaSource) { + this.mediaSource = mediaSource; + mediaPeriods = ArrayListMultimap.create(); + adPlaybackState = AdPlaybackState.NONE; + mediaSourceEventDispatcherWithoutId = createEventDispatcher(/* mediaPeriodId= */ null); + drmEventDispatcherWithoutId = createDrmEventDispatcher(/* mediaPeriodId= */ null); + } + + /** + * Sets the {@link AdPlaybackState} published by this source. + * + *

      May be called from any thread. + * + *

      Must only contain server-side inserted ad groups. The number of ad groups and the number of + * ads within an ad group may only increase. The durations of ads may change and the positions of + * future ad groups may change. Post-roll ad groups with {@link C#TIME_END_OF_SOURCE} must be + * empty and can be used as a placeholder for a future ad group. + * + * @param adPlaybackState The new {@link AdPlaybackState}. + */ + public void setAdPlaybackState(AdPlaybackState adPlaybackState) { + checkArgument(adPlaybackState.adGroupCount >= this.adPlaybackState.adGroupCount); + for (int i = adPlaybackState.removedAdGroupCount; i < adPlaybackState.adGroupCount; i++) { + AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(i); + checkArgument(adGroup.isServerSideInserted); + if (i < this.adPlaybackState.adGroupCount) { + checkArgument( + getAdCountInGroup(adPlaybackState, /* adGroupIndex= */ i) + >= getAdCountInGroup(this.adPlaybackState, /* adGroupIndex= */ i)); + } + if (adGroup.timeUs == C.TIME_END_OF_SOURCE) { + checkArgument(getAdCountInGroup(adPlaybackState, /* adGroupIndex= */ i) == 0); + } + } + synchronized (this) { + if (playbackHandler == null) { + this.adPlaybackState = adPlaybackState; + } else { + playbackHandler.post( + () -> { + for (SharedMediaPeriod mediaPeriod : mediaPeriods.values()) { + mediaPeriod.updateAdPlaybackState(adPlaybackState); + } + if (lastUsedMediaPeriod != null) { + lastUsedMediaPeriod.updateAdPlaybackState(adPlaybackState); + } + this.adPlaybackState = adPlaybackState; + if (contentTimeline != null) { + refreshSourceInfo( + new ServerSideInsertedAdsTimeline(contentTimeline, adPlaybackState)); + } + }); + } + } + } + + @Override + public MediaItem getMediaItem() { + return mediaSource.getMediaItem(); + } + + @Override + protected void prepareSourceInternal(@Nullable TransferListener mediaTransferListener) { + Handler handler = Util.createHandlerForCurrentLooper(); + synchronized (this) { + playbackHandler = handler; + } + mediaSource.addEventListener(handler, /* eventListener= */ this); + mediaSource.addDrmEventListener(handler, /* eventListener= */ this); + mediaSource.prepareSource(/* caller= */ this, mediaTransferListener); + } + + @Override + public void maybeThrowSourceInfoRefreshError() throws IOException { + mediaSource.maybeThrowSourceInfoRefreshError(); + } + + @Override + protected void enableInternal() { + mediaSource.enable(/* caller= */ this); + } + + @Override + protected void disableInternal() { + releaseLastUsedMediaPeriod(); + mediaSource.disable(/* caller= */ this); + } + + @Override + public void onSourceInfoRefreshed(MediaSource source, Timeline timeline) { + this.contentTimeline = timeline; + if (AdPlaybackState.NONE.equals(adPlaybackState)) { + return; + } + refreshSourceInfo(new ServerSideInsertedAdsTimeline(timeline, adPlaybackState)); + } + + @Override + protected void releaseSourceInternal() { + releaseLastUsedMediaPeriod(); + contentTimeline = null; + synchronized (this) { + playbackHandler = null; + } + mediaSource.releaseSource(/* caller= */ this); + mediaSource.removeEventListener(/* eventListener= */ this); + mediaSource.removeDrmEventListener(/* eventListener= */ this); + } + + @Override + public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) { + SharedMediaPeriod sharedPeriod; + if (lastUsedMediaPeriod != null) { + sharedPeriod = lastUsedMediaPeriod; + lastUsedMediaPeriod = null; + mediaPeriods.put(id.windowSequenceNumber, sharedPeriod); + } else { + @Nullable + SharedMediaPeriod lastExistingPeriod = + Iterables.getLast(mediaPeriods.get(id.windowSequenceNumber), /* defaultValue= */ null); + if (lastExistingPeriod != null + && lastExistingPeriod.canReuseMediaPeriod(id, startPositionUs)) { + sharedPeriod = lastExistingPeriod; + } else { + long streamPositionUs = getStreamPositionUs(startPositionUs, id, adPlaybackState); + sharedPeriod = + new SharedMediaPeriod( + mediaSource.createPeriod( + new MediaPeriodId(id.periodUid, id.windowSequenceNumber), + allocator, + streamPositionUs), + adPlaybackState); + mediaPeriods.put(id.windowSequenceNumber, sharedPeriod); + } + } + MediaPeriodImpl mediaPeriod = + new MediaPeriodImpl( + sharedPeriod, id, createEventDispatcher(id), createDrmEventDispatcher(id)); + sharedPeriod.add(mediaPeriod); + return mediaPeriod; + } + + @Override + public void releasePeriod(MediaPeriod mediaPeriod) { + MediaPeriodImpl mediaPeriodImpl = (MediaPeriodImpl) mediaPeriod; + mediaPeriodImpl.sharedPeriod.remove(mediaPeriodImpl); + if (mediaPeriodImpl.sharedPeriod.isUnused()) { + mediaPeriods.remove( + mediaPeriodImpl.mediaPeriodId.windowSequenceNumber, mediaPeriodImpl.sharedPeriod); + if (mediaPeriods.isEmpty()) { + // Keep until disabled. + lastUsedMediaPeriod = mediaPeriodImpl.sharedPeriod; + } else { + mediaPeriodImpl.sharedPeriod.release(mediaSource); + } + } + } + + @Override + public void onDrmSessionAcquired( + int windowIndex, @Nullable MediaPeriodId mediaPeriodId, @DrmSession.State int state) { + @Nullable + MediaPeriodImpl mediaPeriod = + getMediaPeriodForEvent( + mediaPeriodId, /* mediaLoadData= */ null, /* useLoadingPeriod= */ true); + if (mediaPeriod == null) { + drmEventDispatcherWithoutId.drmSessionAcquired(state); + } else { + mediaPeriod.drmEventDispatcher.drmSessionAcquired(state); + } + } + + @Override + public void onDrmKeysLoaded(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) { + @Nullable + MediaPeriodImpl mediaPeriod = + getMediaPeriodForEvent( + mediaPeriodId, /* mediaLoadData= */ null, /* useLoadingPeriod= */ false); + if (mediaPeriod == null) { + drmEventDispatcherWithoutId.drmKeysLoaded(); + } else { + mediaPeriod.drmEventDispatcher.drmKeysLoaded(); + } + } + + @Override + public void onDrmSessionManagerError( + int windowIndex, @Nullable MediaPeriodId mediaPeriodId, Exception error) { + @Nullable + MediaPeriodImpl mediaPeriod = + getMediaPeriodForEvent( + mediaPeriodId, /* mediaLoadData= */ null, /* useLoadingPeriod= */ false); + if (mediaPeriod == null) { + drmEventDispatcherWithoutId.drmSessionManagerError(error); + } else { + mediaPeriod.drmEventDispatcher.drmSessionManagerError(error); + } + } + + @Override + public void onDrmKeysRestored(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) { + @Nullable + MediaPeriodImpl mediaPeriod = + getMediaPeriodForEvent( + mediaPeriodId, /* mediaLoadData= */ null, /* useLoadingPeriod= */ false); + if (mediaPeriod == null) { + drmEventDispatcherWithoutId.drmKeysRestored(); + } else { + mediaPeriod.drmEventDispatcher.drmKeysRestored(); + } + } + + @Override + public void onDrmKeysRemoved(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) { + @Nullable + MediaPeriodImpl mediaPeriod = + getMediaPeriodForEvent( + mediaPeriodId, /* mediaLoadData= */ null, /* useLoadingPeriod= */ false); + if (mediaPeriod == null) { + drmEventDispatcherWithoutId.drmKeysRemoved(); + } else { + mediaPeriod.drmEventDispatcher.drmKeysRemoved(); + } + } + + @Override + public void onDrmSessionReleased(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) { + @Nullable + MediaPeriodImpl mediaPeriod = + getMediaPeriodForEvent( + mediaPeriodId, /* mediaLoadData= */ null, /* useLoadingPeriod= */ false); + if (mediaPeriod == null) { + drmEventDispatcherWithoutId.drmSessionReleased(); + } else { + mediaPeriod.drmEventDispatcher.drmSessionReleased(); + } + } + + @Override + public void onLoadStarted( + int windowIndex, + @Nullable MediaPeriodId mediaPeriodId, + LoadEventInfo loadEventInfo, + MediaLoadData mediaLoadData) { + @Nullable + MediaPeriodImpl mediaPeriod = + getMediaPeriodForEvent(mediaPeriodId, mediaLoadData, /* useLoadingPeriod= */ true); + if (mediaPeriod == null) { + mediaSourceEventDispatcherWithoutId.loadStarted(loadEventInfo, mediaLoadData); + } else { + mediaPeriod.sharedPeriod.onLoadStarted(loadEventInfo, mediaLoadData); + mediaPeriod.mediaSourceEventDispatcher.loadStarted( + loadEventInfo, correctMediaLoadData(mediaPeriod, mediaLoadData, adPlaybackState)); + } + } + + @Override + public void onLoadCompleted( + int windowIndex, + @Nullable MediaPeriodId mediaPeriodId, + LoadEventInfo loadEventInfo, + MediaLoadData mediaLoadData) { + @Nullable + MediaPeriodImpl mediaPeriod = + getMediaPeriodForEvent(mediaPeriodId, mediaLoadData, /* useLoadingPeriod= */ true); + if (mediaPeriod == null) { + mediaSourceEventDispatcherWithoutId.loadCompleted(loadEventInfo, mediaLoadData); + } else { + mediaPeriod.sharedPeriod.onLoadFinished(loadEventInfo); + mediaPeriod.mediaSourceEventDispatcher.loadCompleted( + loadEventInfo, correctMediaLoadData(mediaPeriod, mediaLoadData, adPlaybackState)); + } + } + + @Override + public void onLoadCanceled( + int windowIndex, + @Nullable MediaPeriodId mediaPeriodId, + LoadEventInfo loadEventInfo, + MediaLoadData mediaLoadData) { + @Nullable + MediaPeriodImpl mediaPeriod = + getMediaPeriodForEvent(mediaPeriodId, mediaLoadData, /* useLoadingPeriod= */ true); + if (mediaPeriod == null) { + mediaSourceEventDispatcherWithoutId.loadCanceled(loadEventInfo, mediaLoadData); + } else { + mediaPeriod.sharedPeriod.onLoadFinished(loadEventInfo); + mediaPeriod.mediaSourceEventDispatcher.loadCanceled( + loadEventInfo, correctMediaLoadData(mediaPeriod, mediaLoadData, adPlaybackState)); + } + } + + @Override + public void onLoadError( + int windowIndex, + @Nullable MediaPeriodId mediaPeriodId, + LoadEventInfo loadEventInfo, + MediaLoadData mediaLoadData, + IOException error, + boolean wasCanceled) { + @Nullable + MediaPeriodImpl mediaPeriod = + getMediaPeriodForEvent(mediaPeriodId, mediaLoadData, /* useLoadingPeriod= */ true); + if (mediaPeriod == null) { + mediaSourceEventDispatcherWithoutId.loadError( + loadEventInfo, mediaLoadData, error, wasCanceled); + } else { + if (wasCanceled) { + mediaPeriod.sharedPeriod.onLoadFinished(loadEventInfo); + } + mediaPeriod.mediaSourceEventDispatcher.loadError( + loadEventInfo, + correctMediaLoadData(mediaPeriod, mediaLoadData, adPlaybackState), + error, + wasCanceled); + } + } + + @Override + public void onUpstreamDiscarded( + int windowIndex, MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) { + @Nullable + MediaPeriodImpl mediaPeriod = + getMediaPeriodForEvent(mediaPeriodId, mediaLoadData, /* useLoadingPeriod= */ false); + if (mediaPeriod == null) { + mediaSourceEventDispatcherWithoutId.upstreamDiscarded(mediaLoadData); + } else { + mediaPeriod.mediaSourceEventDispatcher.upstreamDiscarded( + correctMediaLoadData(mediaPeriod, mediaLoadData, adPlaybackState)); + } + } + + @Override + public void onDownstreamFormatChanged( + int windowIndex, @Nullable MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) { + @Nullable + MediaPeriodImpl mediaPeriod = + getMediaPeriodForEvent(mediaPeriodId, mediaLoadData, /* useLoadingPeriod= */ false); + if (mediaPeriod == null) { + mediaSourceEventDispatcherWithoutId.downstreamFormatChanged(mediaLoadData); + } else { + mediaPeriod.sharedPeriod.onDownstreamFormatChanged(mediaPeriod, mediaLoadData); + mediaPeriod.mediaSourceEventDispatcher.downstreamFormatChanged( + correctMediaLoadData(mediaPeriod, mediaLoadData, adPlaybackState)); + } + } + + private void releaseLastUsedMediaPeriod() { + if (lastUsedMediaPeriod != null) { + lastUsedMediaPeriod.release(mediaSource); + lastUsedMediaPeriod = null; + } + } + + @Nullable + private MediaPeriodImpl getMediaPeriodForEvent( + @Nullable MediaPeriodId mediaPeriodId, + @Nullable MediaLoadData mediaLoadData, + boolean useLoadingPeriod) { + if (mediaPeriodId == null) { + return null; + } + List periods = mediaPeriods.get(mediaPeriodId.windowSequenceNumber); + if (periods.isEmpty()) { + return null; + } + if (useLoadingPeriod) { + SharedMediaPeriod loadingPeriod = Iterables.getLast(periods); + return loadingPeriod.loadingPeriod != null + ? loadingPeriod.loadingPeriod + : Iterables.getLast(loadingPeriod.mediaPeriods); + } + for (int i = 0; i < periods.size(); i++) { + @Nullable MediaPeriodImpl period = periods.get(i).getMediaPeriodForEvent(mediaLoadData); + if (period != null) { + return period; + } + } + return periods.get(0).mediaPeriods.get(0); + } + + private static long getMediaPeriodEndPositionUs( + MediaPeriodImpl mediaPeriod, AdPlaybackState adPlaybackState) { + MediaPeriodId id = mediaPeriod.mediaPeriodId; + if (id.isAd()) { + AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(id.adGroupIndex); + return adGroup.count == C.LENGTH_UNSET ? 0 : adGroup.durationsUs[id.adIndexInAdGroup]; + } + if (id.nextAdGroupIndex == C.INDEX_UNSET) { + return Long.MAX_VALUE; + } + AdPlaybackState.AdGroup nextAdGroup = adPlaybackState.getAdGroup(id.nextAdGroupIndex); + return nextAdGroup.timeUs == C.TIME_END_OF_SOURCE ? Long.MAX_VALUE : nextAdGroup.timeUs; + } + + private static MediaLoadData correctMediaLoadData( + MediaPeriodImpl mediaPeriod, MediaLoadData mediaLoadData, AdPlaybackState adPlaybackState) { + return new MediaLoadData( + mediaLoadData.dataType, + mediaLoadData.trackType, + mediaLoadData.trackFormat, + mediaLoadData.trackSelectionReason, + mediaLoadData.trackSelectionData, + correctMediaLoadDataPositionMs( + mediaLoadData.mediaStartTimeMs, mediaPeriod, adPlaybackState), + correctMediaLoadDataPositionMs(mediaLoadData.mediaEndTimeMs, mediaPeriod, adPlaybackState)); + } + + private static long correctMediaLoadDataPositionMs( + long mediaPositionMs, MediaPeriodImpl mediaPeriod, AdPlaybackState adPlaybackState) { + if (mediaPositionMs == C.TIME_UNSET) { + return C.TIME_UNSET; + } + long mediaPositionUs = C.msToUs(mediaPositionMs); + MediaPeriodId id = mediaPeriod.mediaPeriodId; + long correctedPositionUs = + id.isAd() + ? getMediaPeriodPositionUsForAd( + mediaPositionUs, id.adGroupIndex, id.adIndexInAdGroup, adPlaybackState) + // Ignore nextAdGroupIndex for content ids to correct timestamps that fall into future + // content pieces (beyond nextAdGroupIndex). + : getMediaPeriodPositionUsForContent( + mediaPositionUs, /* nextAdGroupIndex= */ C.INDEX_UNSET, adPlaybackState); + return C.usToMs(correctedPositionUs); + } + + private static final class SharedMediaPeriod implements MediaPeriod.Callback { + + private final MediaPeriod actualMediaPeriod; + private final List mediaPeriods; + private final Map> activeLoads; + + private AdPlaybackState adPlaybackState; + @Nullable private MediaPeriodImpl loadingPeriod; + private boolean hasStartedPreparing; + private boolean isPrepared; + public @NullableType ExoTrackSelection[] trackSelections; + public @NullableType SampleStream[] sampleStreams; + public @NullableType MediaLoadData[] lastDownstreamFormatChangeData; + + public SharedMediaPeriod(MediaPeriod actualMediaPeriod, AdPlaybackState adPlaybackState) { + this.actualMediaPeriod = actualMediaPeriod; + this.adPlaybackState = adPlaybackState; + mediaPeriods = new ArrayList<>(); + activeLoads = new HashMap<>(); + trackSelections = new ExoTrackSelection[0]; + sampleStreams = new SampleStream[0]; + lastDownstreamFormatChangeData = new MediaLoadData[0]; + } + + public void updateAdPlaybackState(AdPlaybackState adPlaybackState) { + this.adPlaybackState = adPlaybackState; + } + + public void add(MediaPeriodImpl mediaPeriod) { + mediaPeriods.add(mediaPeriod); + } + + public void remove(MediaPeriodImpl mediaPeriod) { + if (mediaPeriod.equals(loadingPeriod)) { + loadingPeriod = null; + activeLoads.clear(); + } + mediaPeriods.remove(mediaPeriod); + } + + public boolean isUnused() { + return mediaPeriods.isEmpty(); + } + + public void release(MediaSource mediaSource) { + mediaSource.releasePeriod(actualMediaPeriod); + } + + public boolean canReuseMediaPeriod(MediaPeriodId id, long positionUs) { + MediaPeriodImpl previousPeriod = Iterables.getLast(mediaPeriods); + long previousEndPositionUs = + getStreamPositionUs( + getMediaPeriodEndPositionUs(previousPeriod, adPlaybackState), + previousPeriod.mediaPeriodId, + adPlaybackState); + long startPositionUs = getStreamPositionUs(positionUs, id, adPlaybackState); + return startPositionUs == previousEndPositionUs; + } + + @Nullable + public MediaPeriodImpl getMediaPeriodForEvent(@Nullable MediaLoadData mediaLoadData) { + if (mediaLoadData != null && mediaLoadData.mediaStartTimeMs != C.TIME_UNSET) { + for (int i = 0; i < mediaPeriods.size(); i++) { + MediaPeriodImpl mediaPeriod = mediaPeriods.get(i); + long startTimeInPeriodUs = + getMediaPeriodPositionUs( + C.msToUs(mediaLoadData.mediaStartTimeMs), + mediaPeriod.mediaPeriodId, + adPlaybackState); + long mediaPeriodEndPositionUs = getMediaPeriodEndPositionUs(mediaPeriod, adPlaybackState); + if (startTimeInPeriodUs >= 0 && startTimeInPeriodUs < mediaPeriodEndPositionUs) { + return mediaPeriod; + } + } + } + return null; + } + + public void prepare(MediaPeriodImpl mediaPeriod, long positionUs) { + mediaPeriod.lastStartPositionUs = positionUs; + if (hasStartedPreparing) { + if (isPrepared) { + checkNotNull(mediaPeriod.callback).onPrepared(mediaPeriod); + } + return; + } + hasStartedPreparing = true; + long preparePositionUs = + getStreamPositionUs(positionUs, mediaPeriod.mediaPeriodId, adPlaybackState); + actualMediaPeriod.prepare(/* callback= */ this, preparePositionUs); + } + + public void maybeThrowPrepareError() throws IOException { + actualMediaPeriod.maybeThrowPrepareError(); + } + + public TrackGroupArray getTrackGroups() { + return actualMediaPeriod.getTrackGroups(); + } + + public List getStreamKeys(List trackSelections) { + return actualMediaPeriod.getStreamKeys(trackSelections); + } + + public boolean continueLoading(MediaPeriodImpl mediaPeriod, long positionUs) { + @Nullable MediaPeriodImpl loadingPeriod = this.loadingPeriod; + if (loadingPeriod != null && !mediaPeriod.equals(loadingPeriod)) { + for (Pair loadData : activeLoads.values()) { + loadingPeriod.mediaSourceEventDispatcher.loadCompleted( + loadData.first, + correctMediaLoadData(loadingPeriod, loadData.second, adPlaybackState)); + mediaPeriod.mediaSourceEventDispatcher.loadStarted( + loadData.first, correctMediaLoadData(mediaPeriod, loadData.second, adPlaybackState)); + } + } + this.loadingPeriod = mediaPeriod; + long actualPlaybackPositionUs = + getStreamPositionUsWithNotYetStartedHandling(mediaPeriod, positionUs); + return actualMediaPeriod.continueLoading(actualPlaybackPositionUs); + } + + public boolean isLoading(MediaPeriodImpl mediaPeriod) { + return mediaPeriod.equals(loadingPeriod) && actualMediaPeriod.isLoading(); + } + + public long getBufferedPositionUs(MediaPeriodImpl mediaPeriod) { + return getMediaPeriodPositionUsWithEndOfSourceHandling( + mediaPeriod, actualMediaPeriod.getBufferedPositionUs()); + } + + public long getNextLoadPositionUs(MediaPeriodImpl mediaPeriod) { + return getMediaPeriodPositionUsWithEndOfSourceHandling( + mediaPeriod, actualMediaPeriod.getNextLoadPositionUs()); + } + + public long seekToUs(MediaPeriodImpl mediaPeriod, long positionUs) { + long actualRequestedPositionUs = + getStreamPositionUs(positionUs, mediaPeriod.mediaPeriodId, adPlaybackState); + long newActualPositionUs = actualMediaPeriod.seekToUs(actualRequestedPositionUs); + return getMediaPeriodPositionUs( + newActualPositionUs, mediaPeriod.mediaPeriodId, adPlaybackState); + } + + public long getAdjustedSeekPositionUs( + MediaPeriodImpl mediaPeriod, long positionUs, SeekParameters seekParameters) { + long actualRequestedPositionUs = + getStreamPositionUs(positionUs, mediaPeriod.mediaPeriodId, adPlaybackState); + long adjustedActualPositionUs = + actualMediaPeriod.getAdjustedSeekPositionUs(actualRequestedPositionUs, seekParameters); + return getMediaPeriodPositionUs( + adjustedActualPositionUs, mediaPeriod.mediaPeriodId, adPlaybackState); + } + + public void discardBuffer(MediaPeriodImpl mediaPeriod, long positionUs, boolean toKeyframe) { + long actualPositionUs = + getStreamPositionUs(positionUs, mediaPeriod.mediaPeriodId, adPlaybackState); + actualMediaPeriod.discardBuffer(actualPositionUs, toKeyframe); + } + + public void reevaluateBuffer(MediaPeriodImpl mediaPeriod, long positionUs) { + actualMediaPeriod.reevaluateBuffer( + getStreamPositionUsWithNotYetStartedHandling(mediaPeriod, positionUs)); + } + + public long readDiscontinuity(MediaPeriodImpl mediaPeriod) { + if (!mediaPeriod.equals(mediaPeriods.get(0))) { + return C.TIME_UNSET; + } + long actualDiscontinuityPositionUs = actualMediaPeriod.readDiscontinuity(); + return actualDiscontinuityPositionUs == C.TIME_UNSET + ? C.TIME_UNSET + : getMediaPeriodPositionUs( + actualDiscontinuityPositionUs, mediaPeriod.mediaPeriodId, adPlaybackState); + } + + public long selectTracks( + MediaPeriodImpl mediaPeriod, + @NullableType ExoTrackSelection[] selections, + boolean[] mayRetainStreamFlags, + @NullableType SampleStream[] streams, + boolean[] streamResetFlags, + long positionUs) { + mediaPeriod.lastStartPositionUs = positionUs; + if (mediaPeriod.equals(mediaPeriods.get(0))) { + // Do the real selection for the current first period in the list. + trackSelections = Arrays.copyOf(selections, selections.length); + long requestedPositionUs = + getStreamPositionUs(positionUs, mediaPeriod.mediaPeriodId, adPlaybackState); + @NullableType + SampleStream[] realStreams = + sampleStreams.length == 0 + ? new SampleStream[selections.length] + : Arrays.copyOf(sampleStreams, sampleStreams.length); + long startPositionUs = + actualMediaPeriod.selectTracks( + selections, + mayRetainStreamFlags, + realStreams, + streamResetFlags, + requestedPositionUs); + this.sampleStreams = Arrays.copyOf(realStreams, realStreams.length); + lastDownstreamFormatChangeData = + Arrays.copyOf(lastDownstreamFormatChangeData, realStreams.length); + for (int i = 0; i < realStreams.length; i++) { + if (realStreams[i] == null) { + streams[i] = null; + lastDownstreamFormatChangeData[i] = null; + } else if (streams[i] == null || streamResetFlags[i]) { + streams[i] = new SampleStreamImpl(mediaPeriod, /* streamIndex= */ i); + lastDownstreamFormatChangeData[i] = null; + } + } + return getMediaPeriodPositionUs( + startPositionUs, mediaPeriod.mediaPeriodId, adPlaybackState); + } + // All subsequent periods need to have the same selection. Ignore tracks or add empty tracks + // if this isn't the case. + for (int i = 0; i < selections.length; i++) { + if (selections[i] != null) { + streamResetFlags[i] = !mayRetainStreamFlags[i] || streams[i] == null; + if (streamResetFlags[i]) { + streams[i] = + Util.areEqual(trackSelections[i], selections[i]) + ? new SampleStreamImpl(mediaPeriod, /* streamIndex= */ i) + : new EmptySampleStream(); + } + } else { + streams[i] = null; + streamResetFlags[i] = true; + } + } + return positionUs; + } + + @SampleStream.ReadDataResult + public int readData( + MediaPeriodImpl mediaPeriod, + int streamIndex, + FormatHolder formatHolder, + DecoderInputBuffer buffer, + @SampleStream.ReadFlags int readFlags) { + @SampleStream.ReadFlags + int peekingFlags = readFlags | SampleStream.FLAG_PEEK | SampleStream.FLAG_OMIT_SAMPLE_DATA; + @SampleStream.ReadDataResult + int result = + castNonNull(sampleStreams[streamIndex]).readData(formatHolder, buffer, peekingFlags); + long adjustedTimeUs = + getMediaPeriodPositionUsWithEndOfSourceHandling(mediaPeriod, buffer.timeUs); + if ((result == C.RESULT_BUFFER_READ && adjustedTimeUs == C.TIME_END_OF_SOURCE) + || (result == C.RESULT_NOTHING_READ + && getBufferedPositionUs(mediaPeriod) == C.TIME_END_OF_SOURCE + && !buffer.waitingForKeys)) { + maybeNotifyDownstreamFormatChanged(mediaPeriod, streamIndex); + buffer.clear(); + buffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM); + return C.RESULT_BUFFER_READ; + } + if (result == C.RESULT_BUFFER_READ) { + maybeNotifyDownstreamFormatChanged(mediaPeriod, streamIndex); + castNonNull(sampleStreams[streamIndex]).readData(formatHolder, buffer, readFlags); + buffer.timeUs = adjustedTimeUs; + } + return result; + } + + public int skipData(MediaPeriodImpl mediaPeriod, int streamIndex, long positionUs) { + long actualPositionUs = + getStreamPositionUs(positionUs, mediaPeriod.mediaPeriodId, adPlaybackState); + return castNonNull(sampleStreams[streamIndex]).skipData(actualPositionUs); + } + + public boolean isReady(int streamIndex) { + return castNonNull(sampleStreams[streamIndex]).isReady(); + } + + public void maybeThrowError(int streamIndex) throws IOException { + castNonNull(sampleStreams[streamIndex]).maybeThrowError(); + } + + public void onDownstreamFormatChanged( + MediaPeriodImpl mediaPeriod, MediaLoadData mediaLoadData) { + int streamIndex = findMatchingStreamIndex(mediaLoadData); + if (streamIndex != C.INDEX_UNSET) { + lastDownstreamFormatChangeData[streamIndex] = mediaLoadData; + mediaPeriod.hasNotifiedDownstreamFormatChange[streamIndex] = true; + } + } + + public void onLoadStarted(LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData) { + activeLoads.put(loadEventInfo.loadTaskId, Pair.create(loadEventInfo, mediaLoadData)); + } + + public void onLoadFinished(LoadEventInfo loadEventInfo) { + activeLoads.remove(loadEventInfo.loadTaskId); + } + + @Override + public void onPrepared(MediaPeriod actualMediaPeriod) { + isPrepared = true; + for (int i = 0; i < mediaPeriods.size(); i++) { + MediaPeriodImpl mediaPeriod = mediaPeriods.get(i); + if (mediaPeriod.callback != null) { + mediaPeriod.callback.onPrepared(mediaPeriod); + } + } + } + + @Override + public void onContinueLoadingRequested(MediaPeriod source) { + if (loadingPeriod == null) { + return; + } + checkNotNull(loadingPeriod.callback).onContinueLoadingRequested(loadingPeriod); + } + + private long getStreamPositionUsWithNotYetStartedHandling( + MediaPeriodImpl mediaPeriod, long positionUs) { + if (positionUs < mediaPeriod.lastStartPositionUs) { + long actualStartPositionUs = + getStreamPositionUs( + mediaPeriod.lastStartPositionUs, mediaPeriod.mediaPeriodId, adPlaybackState); + return actualStartPositionUs - (mediaPeriod.lastStartPositionUs - positionUs); + } + return getStreamPositionUs(positionUs, mediaPeriod.mediaPeriodId, adPlaybackState); + } + + private long getMediaPeriodPositionUsWithEndOfSourceHandling( + MediaPeriodImpl mediaPeriod, long positionUs) { + if (positionUs == C.TIME_END_OF_SOURCE) { + return C.TIME_END_OF_SOURCE; + } + long mediaPeriodPositionUs = + getMediaPeriodPositionUs(positionUs, mediaPeriod.mediaPeriodId, adPlaybackState); + long endPositionUs = getMediaPeriodEndPositionUs(mediaPeriod, adPlaybackState); + return mediaPeriodPositionUs >= endPositionUs ? C.TIME_END_OF_SOURCE : mediaPeriodPositionUs; + } + + private int findMatchingStreamIndex(MediaLoadData mediaLoadData) { + if (mediaLoadData.trackFormat == null) { + return C.INDEX_UNSET; + } + for (int i = 0; i < trackSelections.length; i++) { + if (trackSelections[i] != null) { + TrackGroup trackGroup = trackSelections[i].getTrackGroup(); + // Muxed primary track group should be the first in the list. We need to match Formats on + // their id only as the muxed format and the format in the track group won't match. + boolean isPrimaryTrackGroup = + mediaLoadData.trackType == C.TRACK_TYPE_DEFAULT + && trackGroup.equals(getTrackGroups().get(0)); + for (int j = 0; j < trackGroup.length; j++) { + Format format = trackGroup.getFormat(j); + if (format.equals(mediaLoadData.trackFormat) + || (isPrimaryTrackGroup + && format.id != null + && format.id.equals(mediaLoadData.trackFormat.id))) { + return i; + } + } + } + } + return C.INDEX_UNSET; + } + + private void maybeNotifyDownstreamFormatChanged(MediaPeriodImpl mediaPeriod, int streamIndex) { + if (!mediaPeriod.hasNotifiedDownstreamFormatChange[streamIndex] + && lastDownstreamFormatChangeData[streamIndex] != null) { + mediaPeriod.hasNotifiedDownstreamFormatChange[streamIndex] = true; + mediaPeriod.mediaSourceEventDispatcher.downstreamFormatChanged( + correctMediaLoadData( + mediaPeriod, lastDownstreamFormatChangeData[streamIndex], adPlaybackState)); + } + } + } + + private static final class ServerSideInsertedAdsTimeline extends ForwardingTimeline { + + private final AdPlaybackState adPlaybackState; + + public ServerSideInsertedAdsTimeline( + Timeline contentTimeline, AdPlaybackState adPlaybackState) { + super(contentTimeline); + Assertions.checkState(contentTimeline.getPeriodCount() == 1); + Assertions.checkState(contentTimeline.getWindowCount() == 1); + this.adPlaybackState = adPlaybackState; + } + + @Override + public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) { + super.getWindow(windowIndex, window, defaultPositionProjectionUs); + long positionInPeriodUs = + getMediaPeriodPositionUsForContent( + window.positionInFirstPeriodUs, + /* nextAdGroupIndex= */ C.INDEX_UNSET, + adPlaybackState); + if (window.durationUs == C.TIME_UNSET) { + if (adPlaybackState.contentDurationUs != C.TIME_UNSET) { + window.durationUs = adPlaybackState.contentDurationUs - positionInPeriodUs; + } + } else { + long actualWindowEndPositionInPeriodUs = window.positionInFirstPeriodUs + window.durationUs; + long windowEndPositionInPeriodUs = + getMediaPeriodPositionUsForContent( + actualWindowEndPositionInPeriodUs, + /* nextAdGroupIndex= */ C.INDEX_UNSET, + adPlaybackState); + window.durationUs = windowEndPositionInPeriodUs - positionInPeriodUs; + } + window.positionInFirstPeriodUs = positionInPeriodUs; + return window; + } + + @Override + public Period getPeriod(int periodIndex, Period period, boolean setIds) { + super.getPeriod(periodIndex, period, setIds); + long durationUs = period.durationUs; + if (durationUs == C.TIME_UNSET) { + durationUs = adPlaybackState.contentDurationUs; + } else { + durationUs = + getMediaPeriodPositionUsForContent( + durationUs, /* nextAdGroupIndex= */ C.INDEX_UNSET, adPlaybackState); + } + long positionInWindowUs = + -getMediaPeriodPositionUsForContent( + -period.getPositionInWindowUs(), + /* nextAdGroupIndex= */ C.INDEX_UNSET, + adPlaybackState); + period.set( + period.id, + period.uid, + period.windowIndex, + durationUs, + positionInWindowUs, + adPlaybackState, + period.isPlaceholder); + return period; + } + } + + private static final class MediaPeriodImpl implements MediaPeriod { + + public final SharedMediaPeriod sharedPeriod; + public final MediaPeriodId mediaPeriodId; + public final MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher; + public final DrmSessionEventListener.EventDispatcher drmEventDispatcher; + + public @MonotonicNonNull Callback callback; + public long lastStartPositionUs; + public boolean[] hasNotifiedDownstreamFormatChange; + + public MediaPeriodImpl( + SharedMediaPeriod sharedPeriod, + MediaPeriodId mediaPeriodId, + MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher, + DrmSessionEventListener.EventDispatcher drmEventDispatcher) { + this.sharedPeriod = sharedPeriod; + this.mediaPeriodId = mediaPeriodId; + this.mediaSourceEventDispatcher = mediaSourceEventDispatcher; + this.drmEventDispatcher = drmEventDispatcher; + hasNotifiedDownstreamFormatChange = new boolean[0]; + } + + @Override + public void prepare(Callback callback, long positionUs) { + this.callback = callback; + sharedPeriod.prepare(/* mediaPeriod= */ this, positionUs); + } + + @Override + public void maybeThrowPrepareError() throws IOException { + sharedPeriod.maybeThrowPrepareError(); + } + + @Override + public TrackGroupArray getTrackGroups() { + return sharedPeriod.getTrackGroups(); + } + + @Override + public List getStreamKeys(List trackSelections) { + return sharedPeriod.getStreamKeys(trackSelections); + } + + @Override + public long selectTracks( + @NullableType ExoTrackSelection[] selections, + boolean[] mayRetainStreamFlags, + @NullableType SampleStream[] streams, + boolean[] streamResetFlags, + long positionUs) { + if (hasNotifiedDownstreamFormatChange.length == 0) { + hasNotifiedDownstreamFormatChange = new boolean[streams.length]; + } + return sharedPeriod.selectTracks( + /* mediaPeriod= */ this, + selections, + mayRetainStreamFlags, + streams, + streamResetFlags, + positionUs); + } + + @Override + public void discardBuffer(long positionUs, boolean toKeyframe) { + sharedPeriod.discardBuffer(/* mediaPeriod= */ this, positionUs, toKeyframe); + } + + @Override + public long readDiscontinuity() { + return sharedPeriod.readDiscontinuity(/* mediaPeriod= */ this); + } + + @Override + public long seekToUs(long positionUs) { + return sharedPeriod.seekToUs(/* mediaPeriod= */ this, positionUs); + } + + @Override + public long getAdjustedSeekPositionUs(long positionUs, SeekParameters seekParameters) { + return sharedPeriod.getAdjustedSeekPositionUs( + /* mediaPeriod= */ this, positionUs, seekParameters); + } + + @Override + public long getBufferedPositionUs() { + return sharedPeriod.getBufferedPositionUs(/* mediaPeriod= */ this); + } + + @Override + public long getNextLoadPositionUs() { + return sharedPeriod.getNextLoadPositionUs(/* mediaPeriod= */ this); + } + + @Override + public boolean continueLoading(long positionUs) { + return sharedPeriod.continueLoading(/* mediaPeriod= */ this, positionUs); + } + + @Override + public boolean isLoading() { + return sharedPeriod.isLoading(/* mediaPeriod= */ this); + } + + @Override + public void reevaluateBuffer(long positionUs) { + sharedPeriod.reevaluateBuffer(/* mediaPeriod= */ this, positionUs); + } + } + + private static final class SampleStreamImpl implements SampleStream { + + private final MediaPeriodImpl mediaPeriod; + private final int streamIndex; + + public SampleStreamImpl(MediaPeriodImpl mediaPeriod, int streamIndex) { + this.mediaPeriod = mediaPeriod; + this.streamIndex = streamIndex; + } + + @Override + public boolean isReady() { + return mediaPeriod.sharedPeriod.isReady(streamIndex); + } + + @Override + public void maybeThrowError() throws IOException { + mediaPeriod.sharedPeriod.maybeThrowError(streamIndex); + } + + @Override + @ReadDataResult + public int readData( + FormatHolder formatHolder, DecoderInputBuffer buffer, @ReadFlags int readFlags) { + return mediaPeriod.sharedPeriod.readData( + mediaPeriod, streamIndex, formatHolder, buffer, readFlags); + } + + @Override + public int skipData(long positionUs) { + return mediaPeriod.sharedPeriod.skipData(mediaPeriod, streamIndex, positionUs); + } + } +} diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ads/ServerSideInsertedAdsUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/ServerSideInsertedAdsUtil.java new file mode 100644 index 00000000000..65567d005bc --- /dev/null +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/ServerSideInsertedAdsUtil.java @@ -0,0 +1,316 @@ +/* + * 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 com.google.android.exoplayer2.source.ads; + +import static java.lang.Math.max; + +import androidx.annotation.CheckResult; +import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.Timeline; +import com.google.android.exoplayer2.source.MediaPeriod; +import com.google.android.exoplayer2.source.MediaPeriodId; +import com.google.android.exoplayer2.util.Util; + +/** A static utility class with methods to work with server-side inserted ads. */ +public final class ServerSideInsertedAdsUtil { + + private ServerSideInsertedAdsUtil() {} + + /** + * Adds a new server-side inserted ad group to an {@link AdPlaybackState}. + * + * @param adPlaybackState The existing {@link AdPlaybackState}. + * @param fromPositionUs The position in the underlying server-side inserted ads stream at which + * the ad group starts, in microseconds. + * @param toPositionUs The position in the underlying server-side inserted ads stream at which the + * ad group ends, in microseconds. + * @param contentResumeOffsetUs The timestamp offset which should be added to the content stream + * when resuming playback after the ad group. An offset of 0 collapses the ad group to a + * single insertion point, an offset of {@code toPositionUs-fromPositionUs} keeps the original + * stream timestamps after the ad group. + * @return The updated {@link AdPlaybackState}. + */ + @CheckResult + public static AdPlaybackState addAdGroupToAdPlaybackState( + AdPlaybackState adPlaybackState, + long fromPositionUs, + long toPositionUs, + long contentResumeOffsetUs) { + long adGroupInsertionPositionUs = + getMediaPeriodPositionUsForContent( + fromPositionUs, /* nextAdGroupIndex= */ C.INDEX_UNSET, adPlaybackState); + int insertionIndex = adPlaybackState.removedAdGroupCount; + while (insertionIndex < adPlaybackState.adGroupCount + && adPlaybackState.getAdGroup(insertionIndex).timeUs != C.TIME_END_OF_SOURCE + && adPlaybackState.getAdGroup(insertionIndex).timeUs <= adGroupInsertionPositionUs) { + insertionIndex++; + } + long adDurationUs = toPositionUs - fromPositionUs; + adPlaybackState = + adPlaybackState + .withNewAdGroup(insertionIndex, adGroupInsertionPositionUs) + .withIsServerSideInserted(insertionIndex, /* isServerSideInserted= */ true) + .withAdCount(insertionIndex, /* adCount= */ 1) + .withAdDurationsUs(insertionIndex, adDurationUs) + .withContentResumeOffsetUs(insertionIndex, contentResumeOffsetUs); + long followingAdGroupTimeUsOffset = -adDurationUs + contentResumeOffsetUs; + for (int i = insertionIndex + 1; i < adPlaybackState.adGroupCount; i++) { + long adGroupTimeUs = adPlaybackState.getAdGroup(i).timeUs; + if (adGroupTimeUs != C.TIME_END_OF_SOURCE) { + adPlaybackState = + adPlaybackState.withAdGroupTimeUs( + /* adGroupIndex= */ i, adGroupTimeUs + followingAdGroupTimeUsOffset); + } + } + return adPlaybackState; + } + + /** + * Returns the duration of the underlying server-side inserted ads stream for the current {@link + * Timeline.Period} in the {@link Player}. + * + * @param player The {@link Player}. + * @param adPlaybackState The {@link AdPlaybackState} defining the ad groups. + * @return The duration of the underlying server-side inserted ads stream, in microseconds, or + * {@link C#TIME_UNSET} if it can't be determined. + */ + public static long getStreamDurationUs(Player player, AdPlaybackState adPlaybackState) { + Timeline timeline = player.getCurrentTimeline(); + if (timeline.isEmpty()) { + return C.TIME_UNSET; + } + Timeline.Period period = + timeline.getPeriod(player.getCurrentPeriodIndex(), new Timeline.Period()); + if (period.durationUs == C.TIME_UNSET) { + return C.TIME_UNSET; + } + return getStreamPositionUsForContent( + period.durationUs, /* nextAdGroupIndex= */ C.INDEX_UNSET, adPlaybackState); + } + + /** + * Returns the position in the underlying server-side inserted ads stream for the current playback + * position in the {@link Player}. + * + * @param player The {@link Player}. + * @param adPlaybackState The {@link AdPlaybackState} defining the ad groups. + * @return The position in the underlying server-side inserted ads stream, in microseconds, or + * {@link C#TIME_UNSET} if it can't be determined. + */ + public static long getStreamPositionUs(Player player, AdPlaybackState adPlaybackState) { + Timeline timeline = player.getCurrentTimeline(); + if (timeline.isEmpty()) { + return C.TIME_UNSET; + } + Timeline.Period period = + timeline.getPeriod(player.getCurrentPeriodIndex(), new Timeline.Period()); + if (!Util.areEqual(period.getAdsId(), adPlaybackState.adsId)) { + return C.TIME_UNSET; + } + if (player.isPlayingAd()) { + int adGroupIndex = player.getCurrentAdGroupIndex(); + int adIndexInAdGroup = player.getCurrentAdIndexInAdGroup(); + long adPositionUs = C.msToUs(player.getCurrentPosition()); + return getStreamPositionUsForAd( + adPositionUs, adGroupIndex, adIndexInAdGroup, adPlaybackState); + } + long periodPositionUs = C.msToUs(player.getCurrentPosition()) - period.getPositionInWindowUs(); + return getStreamPositionUsForContent( + periodPositionUs, /* nextAdGroupIndex= */ C.INDEX_UNSET, adPlaybackState); + } + + /** + * Returns the position in the underlying server-side inserted ads stream for a position in a + * {@link MediaPeriod}. + * + * @param positionUs The position in the {@link MediaPeriod}, in microseconds. + * @param mediaPeriodId The {@link MediaPeriodId} of the {@link MediaPeriod}. + * @param adPlaybackState The {@link AdPlaybackState} defining the ad groups. + * @return The position in the underlying server-side inserted ads stream, in microseconds. + */ + public static long getStreamPositionUs( + long positionUs, MediaPeriodId mediaPeriodId, AdPlaybackState adPlaybackState) { + return mediaPeriodId.isAd() + ? getStreamPositionUsForAd( + positionUs, mediaPeriodId.adGroupIndex, mediaPeriodId.adIndexInAdGroup, adPlaybackState) + : getStreamPositionUsForContent( + positionUs, mediaPeriodId.nextAdGroupIndex, adPlaybackState); + } + + /** + * Returns the position in a {@link MediaPeriod} for a position in the underlying server-side + * inserted ads stream. + * + * @param positionUs The position in the underlying server-side inserted ads stream, in + * microseconds. + * @param mediaPeriodId The {@link MediaPeriodId} of the {@link MediaPeriod}. + * @param adPlaybackState The {@link AdPlaybackState} defining the ad groups. + * @return The position in the {@link MediaPeriod}, in microseconds. + */ + public static long getMediaPeriodPositionUs( + long positionUs, MediaPeriodId mediaPeriodId, AdPlaybackState adPlaybackState) { + return mediaPeriodId.isAd() + ? getMediaPeriodPositionUsForAd( + positionUs, mediaPeriodId.adGroupIndex, mediaPeriodId.adIndexInAdGroup, adPlaybackState) + : getMediaPeriodPositionUsForContent( + positionUs, mediaPeriodId.nextAdGroupIndex, adPlaybackState); + } + + /** + * Returns the position in the underlying server-side inserted ads stream for a position in an ad + * {@link MediaPeriod}. + * + * @param positionUs The position in the ad {@link MediaPeriod}, in microseconds. + * @param adGroupIndex The ad group index of the ad. + * @param adIndexInAdGroup The index of the ad in the ad group. + * @param adPlaybackState The {@link AdPlaybackState} defining the ad groups. + * @return The position in the underlying server-side inserted ads stream, in microseconds. + */ + public static long getStreamPositionUsForAd( + long positionUs, int adGroupIndex, int adIndexInAdGroup, AdPlaybackState adPlaybackState) { + AdPlaybackState.AdGroup currentAdGroup = adPlaybackState.getAdGroup(adGroupIndex); + positionUs += currentAdGroup.timeUs; + for (int i = adPlaybackState.removedAdGroupCount; i < adGroupIndex; i++) { + AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(i); + for (int j = 0; j < getAdCountInGroup(adPlaybackState, /* adGroupIndex= */ i); j++) { + positionUs += adGroup.durationsUs[j]; + } + positionUs -= adGroup.contentResumeOffsetUs; + } + if (adIndexInAdGroup < getAdCountInGroup(adPlaybackState, adGroupIndex)) { + for (int i = 0; i < adIndexInAdGroup; i++) { + positionUs += currentAdGroup.durationsUs[i]; + } + } + return positionUs; + } + + /** + * Returns the position in an ad {@link MediaPeriod} for a position in the underlying server-side + * inserted ads stream. + * + * @param positionUs The position in the underlying server-side inserted ads stream, in + * microseconds. + * @param adGroupIndex The ad group index of the ad. + * @param adIndexInAdGroup The index of the ad in the ad group. + * @param adPlaybackState The {@link AdPlaybackState} defining the ad groups. + * @return The position in the ad {@link MediaPeriod}, in microseconds. + */ + public static long getMediaPeriodPositionUsForAd( + long positionUs, int adGroupIndex, int adIndexInAdGroup, AdPlaybackState adPlaybackState) { + AdPlaybackState.AdGroup currentAdGroup = adPlaybackState.getAdGroup(adGroupIndex); + positionUs -= currentAdGroup.timeUs; + for (int i = adPlaybackState.removedAdGroupCount; i < adGroupIndex; i++) { + AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(i); + for (int j = 0; j < getAdCountInGroup(adPlaybackState, /* adGroupIndex= */ i); j++) { + positionUs -= adGroup.durationsUs[j]; + } + positionUs += adGroup.contentResumeOffsetUs; + } + if (adIndexInAdGroup < getAdCountInGroup(adPlaybackState, adGroupIndex)) { + for (int i = 0; i < adIndexInAdGroup; i++) { + positionUs -= currentAdGroup.durationsUs[i]; + } + } + return positionUs; + } + + /** + * Returns the position in the underlying server-side inserted ads stream for a position in a + * content {@link MediaPeriod}. + * + * @param positionUs The position in the content {@link MediaPeriod}, in microseconds. + * @param nextAdGroupIndex The next ad group index after the content, or {@link C#INDEX_UNSET} if + * there is no following ad group. Ad groups from this index are not used to adjust the + * position. + * @param adPlaybackState The {@link AdPlaybackState} defining the ad groups. + * @return The position in the underlying server-side inserted ads stream, in microseconds. + */ + public static long getStreamPositionUsForContent( + long positionUs, int nextAdGroupIndex, AdPlaybackState adPlaybackState) { + long totalAdDurationBeforePositionUs = 0; + if (nextAdGroupIndex == C.INDEX_UNSET) { + nextAdGroupIndex = adPlaybackState.adGroupCount; + } + for (int i = adPlaybackState.removedAdGroupCount; i < nextAdGroupIndex; i++) { + AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(i); + if (adGroup.timeUs == C.TIME_END_OF_SOURCE || adGroup.timeUs > positionUs) { + break; + } + long adGroupStreamStartPositionUs = adGroup.timeUs + totalAdDurationBeforePositionUs; + for (int j = 0; j < getAdCountInGroup(adPlaybackState, /* adGroupIndex= */ i); j++) { + totalAdDurationBeforePositionUs += adGroup.durationsUs[j]; + } + totalAdDurationBeforePositionUs -= adGroup.contentResumeOffsetUs; + long adGroupResumePositionUs = adGroup.timeUs + adGroup.contentResumeOffsetUs; + if (adGroupResumePositionUs > positionUs) { + // The position is inside the ad group. + return max(adGroupStreamStartPositionUs, positionUs + totalAdDurationBeforePositionUs); + } + } + return positionUs + totalAdDurationBeforePositionUs; + } + + /** + * Returns the position in a content {@link MediaPeriod} for a position in the underlying + * server-side inserted ads stream. + * + * @param positionUs The position in the underlying server-side inserted ads stream, in + * microseconds. + * @param nextAdGroupIndex The next ad group index after the content, or {@link C#INDEX_UNSET} if + * there is no following ad group. Ad groups from this index are not used to adjust the + * position. + * @param adPlaybackState The {@link AdPlaybackState} defining the ad groups. + * @return The position in the content {@link MediaPeriod}, in microseconds. + */ + public static long getMediaPeriodPositionUsForContent( + long positionUs, int nextAdGroupIndex, AdPlaybackState adPlaybackState) { + long totalAdDurationBeforePositionUs = 0; + if (nextAdGroupIndex == C.INDEX_UNSET) { + nextAdGroupIndex = adPlaybackState.adGroupCount; + } + for (int i = adPlaybackState.removedAdGroupCount; i < nextAdGroupIndex; i++) { + AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(i); + if (adGroup.timeUs == C.TIME_END_OF_SOURCE + || adGroup.timeUs > positionUs - totalAdDurationBeforePositionUs) { + break; + } + for (int j = 0; j < getAdCountInGroup(adPlaybackState, /* adGroupIndex= */ i); j++) { + totalAdDurationBeforePositionUs += adGroup.durationsUs[j]; + } + totalAdDurationBeforePositionUs -= adGroup.contentResumeOffsetUs; + long adGroupResumePositionUs = adGroup.timeUs + adGroup.contentResumeOffsetUs; + if (adGroupResumePositionUs > positionUs - totalAdDurationBeforePositionUs) { + // The position is inside the ad group. + return max(adGroup.timeUs, positionUs - totalAdDurationBeforePositionUs); + } + } + return positionUs - totalAdDurationBeforePositionUs; + } + + /** + * Returns the number of ads in an ad group, treating an unknown number as zero ads. + * + * @param adPlaybackState The {@link AdPlaybackState}. + * @param adGroupIndex The index of the ad group. + * @return The number of ads in the ad group. + */ + public static int getAdCountInGroup(AdPlaybackState adPlaybackState, int adGroupIndex) { + AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(adGroupIndex); + return adGroup.count == C.LENGTH_UNSET ? 0 : adGroup.count; + } +} diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ads/SinglePeriodAdTimeline.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/SinglePeriodAdTimeline.java index c1a655e522f..a114bd92d98 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ads/SinglePeriodAdTimeline.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/SinglePeriodAdTimeline.java @@ -56,5 +56,4 @@ public Period getPeriod(int periodIndex, Period period, boolean setIds) { period.isPlaceholder); return period; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BaseMediaChunk.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BaseMediaChunk.java index 8693bb8912a..330bb494daa 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BaseMediaChunk.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BaseMediaChunk.java @@ -65,8 +65,15 @@ public BaseMediaChunk( long clippedStartTimeUs, long clippedEndTimeUs, long chunkIndex) { - super(dataSource, dataSpec, trackFormat, trackSelectionReason, trackSelectionData, startTimeUs, - endTimeUs, chunkIndex); + super( + dataSource, + dataSpec, + trackFormat, + trackSelectionReason, + trackSelectionData, + startTimeUs, + endTimeUs, + chunkIndex); this.clippedStartTimeUs = clippedStartTimeUs; this.clippedEndTimeUs = clippedEndTimeUs; } @@ -90,11 +97,8 @@ public final int getFirstSampleIndex(int trackIndex) { return Assertions.checkStateNotNull(firstSampleIndices)[trackIndex]; } - /** - * Returns the output most recently passed to {@link #init(BaseMediaChunkOutput)}. - */ + /** Returns the output most recently passed to {@link #init(BaseMediaChunkOutput)}. */ protected final BaseMediaChunkOutput getOutput() { return Assertions.checkStateNotNull(output); } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BaseMediaChunkIterator.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BaseMediaChunkIterator.java index 274be548890..a46fc106060 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BaseMediaChunkIterator.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BaseMediaChunkIterator.java @@ -34,7 +34,7 @@ public abstract class BaseMediaChunkIterator implements MediaChunkIterator { * @param fromIndex The first available index. * @param toIndex The last available index. */ - @SuppressWarnings("method.invocation.invalid") + @SuppressWarnings("nullness:method.invocation") public BaseMediaChunkIterator(long fromIndex, long toIndex) { this.fromIndex = fromIndex; this.toIndex = toIndex; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BaseMediaChunkOutput.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BaseMediaChunkOutput.java index 961d1f8db66..f7b2524e070 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BaseMediaChunkOutput.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BaseMediaChunkOutput.java @@ -52,9 +52,7 @@ public TrackOutput track(int id, int type) { return new DummyTrackOutput(); } - /** - * Returns the current absolute write indices of the individual sample queues. - */ + /** Returns the current absolute write indices of the individual sample queues. */ public int[] getWriteIndices() { int[] writeIndices = new int[sampleQueues.length]; for (int i = 0; i < sampleQueues.length; i++) { @@ -72,5 +70,4 @@ public void setSampleOffsetUs(long sampleOffsetUs) { sampleQueue.setSampleOffsetUs(sampleOffsetUs); } } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BundledChunkExtractor.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BundledChunkExtractor.java index ff19ee1d26f..322ee748fd4 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BundledChunkExtractor.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BundledChunkExtractor.java @@ -164,8 +164,9 @@ public TrackOutput track(int id, int type) { // Assert that if we're seeing a new track we have not seen endTracks. Assertions.checkState(sampleFormats == null); // TODO: Manifest formats for embedded tracks should also be passed here. - bindingTrackOutput = new BindingTrackOutput(id, type, - type == primaryTrackType ? primaryTrackManifestFormat : null); + bindingTrackOutput = + new BindingTrackOutput( + id, type, type == primaryTrackType ? primaryTrackManifestFormat : null); bindingTrackOutput.bind(trackOutputProvider, endTimeUs); bindingTrackOutputs.put(id, bindingTrackOutput); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/Chunk.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/Chunk.java index 1c729b3f350..c2d00123b73 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/Chunk.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/Chunk.java @@ -18,6 +18,7 @@ import android.net.Uri; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.C.DataType; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.source.LoadEventInfo; import com.google.android.exoplayer2.upstream.DataSource; @@ -38,11 +39,8 @@ public abstract class Chunk implements Loadable { public final long loadTaskId; /** The {@link DataSpec} that defines the data to be loaded. */ public final DataSpec dataSpec; - /** - * The type of the chunk. One of the {@code DATA_TYPE_*} constants defined in {@link C}. For - * reporting only. - */ - public final int type; + /** The {@link DataType data type} of the chunk. For reporting only. */ + @DataType public final int type; /** The format of the track to which this chunk belongs. */ public final Format trackFormat; /** @@ -57,8 +55,8 @@ public abstract class Chunk implements Loadable { */ @Nullable public final Object trackSelectionData; /** - * The start time of the media contained by the chunk, or {@link C#TIME_UNSET} if the data - * being loaded does not contain media samples. + * The start time of the media contained by the chunk, or {@link C#TIME_UNSET} if the data being + * loaded does not contain media samples. */ public final long startTimeUs; /** @@ -82,7 +80,7 @@ public abstract class Chunk implements Loadable { public Chunk( DataSource dataSource, DataSpec dataSpec, - int type, + @DataType int type, Format trackFormat, int trackSelectionReason, @Nullable Object trackSelectionData, @@ -99,9 +97,7 @@ public Chunk( loadTaskId = LoadEventInfo.getNewId(); } - /** - * Returns the duration of the chunk in microseconds. - */ + /** Returns the duration of the chunk in microseconds. */ public final long getDurationUs() { return endTimeUs - startTimeUs; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkHolder.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkHolder.java index da0a71e82d5..8d47ac7ad94 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkHolder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkHolder.java @@ -23,17 +23,12 @@ public final class ChunkHolder { /** The chunk. */ @Nullable public Chunk chunk; - /** - * Indicates that the end of the stream has been reached. - */ + /** Indicates that the end of the stream has been reached. */ public boolean endOfStream; - /** - * Clears the holder. - */ + /** Clears the holder. */ public void clear() { chunk = null; endOfStream = false; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java index 40c1b7f3577..b6cd400f223 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java @@ -211,9 +211,7 @@ public EmbeddedSampleStream selectEmbeddedTrack(long positionUs, int trackType) throw new IllegalStateException(); } - /** - * Returns the {@link ChunkSource} used by this stream. - */ + /** Returns the {@link ChunkSource} used by this stream. */ public T getChunkSource() { return chunkSource; } @@ -233,8 +231,10 @@ public long getBufferedPositionUs() { } else { long bufferedPositionUs = lastSeekPositionUs; BaseMediaChunk lastMediaChunk = getLastMediaChunk(); - BaseMediaChunk lastCompletedMediaChunk = lastMediaChunk.isLoadCompleted() ? lastMediaChunk - : mediaChunks.size() > 1 ? mediaChunks.get(mediaChunks.size() - 2) : null; + BaseMediaChunk lastCompletedMediaChunk = + lastMediaChunk.isLoadCompleted() + ? lastMediaChunk + : mediaChunks.size() > 1 ? mediaChunks.get(mediaChunks.size() - 2) : null; if (lastCompletedMediaChunk != null) { bufferedPositionUs = max(bufferedPositionUs, lastCompletedMediaChunk.endTimeUs); } @@ -516,12 +516,9 @@ public LoadErrorAction onLoadError( LoadErrorInfo loadErrorInfo = new LoadErrorInfo(loadEventInfo, mediaLoadData, error, errorCount); - long exclusionDurationMs = - cancelable - ? loadErrorHandlingPolicy.getBlacklistDurationMsFor(loadErrorInfo) - : C.TIME_UNSET; @Nullable LoadErrorAction loadErrorAction = null; - if (chunkSource.onChunkLoadError(loadable, cancelable, error, exclusionDurationMs)) { + if (chunkSource.onChunkLoadError( + loadable, cancelable, loadErrorInfo, loadErrorHandlingPolicy)) { if (cancelable) { loadErrorAction = Loader.DONT_RETRY; if (isMediaChunk) { @@ -812,9 +809,7 @@ private BaseMediaChunk discardUpstreamMediaChunksFromIndex(int chunkIndex) { return firstRemovedChunk; } - /** - * A {@link SampleStream} embedded in a {@link ChunkSampleStream}. - */ + /** A {@link SampleStream} embedded in a {@link ChunkSampleStream}. */ public final class EmbeddedSampleStream implements SampleStream { public final ChunkSampleStream parent; @@ -895,5 +890,4 @@ private void maybeNotifyDownstreamFormat() { } } } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSource.java index 81ce2d63def..b2a46a0cd48 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSource.java @@ -15,8 +15,8 @@ */ package com.google.android.exoplayer2.source.chunk; -import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.SeekParameters; +import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy; import java.io.IOException; import java.util.List; @@ -104,15 +104,19 @@ void getNextChunk( * * @param chunk The chunk whose load encountered the error. * @param cancelable Whether the load can be canceled. - * @param e The error. - * @param exclusionDurationMs The duration for which the associated track may be excluded, or - * {@link C#TIME_UNSET} if the track may not be excluded. + * @param loadErrorInfo The load error info. + * @param loadErrorHandlingPolicy The load error handling policy to customize the behaviour of + * handling the load error. * @return Whether the load should be canceled so that a replacement chunk can be loaded instead. * Must be {@code false} if {@code cancelable} is {@code false}. If {@code true}, {@link * #getNextChunk(long, long, List, ChunkHolder)} will be called to obtain the replacement * chunk. */ - boolean onChunkLoadError(Chunk chunk, boolean cancelable, Exception e, long exclusionDurationMs); + boolean onChunkLoadError( + Chunk chunk, + boolean cancelable, + LoadErrorHandlingPolicy.LoadErrorInfo loadErrorInfo, + LoadErrorHandlingPolicy loadErrorHandlingPolicy); /** Releases any held resources. */ void release(); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/DataChunk.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/DataChunk.java index cec6c0ee02d..aa705bc1012 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/DataChunk.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/DataChunk.java @@ -17,6 +17,7 @@ import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.C.DataType; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSpec; @@ -48,13 +49,20 @@ public abstract class DataChunk extends Chunk { public DataChunk( DataSource dataSource, DataSpec dataSpec, - int type, + @DataType int type, Format trackFormat, int trackSelectionReason, @Nullable Object trackSelectionData, @Nullable byte[] data) { - super(dataSource, dataSpec, type, trackFormat, trackSelectionReason, trackSelectionData, - C.TIME_UNSET, C.TIME_UNSET); + super( + dataSource, + dataSpec, + type, + trackFormat, + trackSelectionReason, + trackSelectionData, + C.TIME_UNSET, + C.TIME_UNSET); this.data = data == null ? Util.EMPTY_BYTE_ARRAY : data; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/InitializationChunk.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/InitializationChunk.java index 944b25395a2..b9717a3d46d 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/InitializationChunk.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/InitializationChunk.java @@ -54,8 +54,15 @@ public InitializationChunk( int trackSelectionReason, @Nullable Object trackSelectionData, ChunkExtractor chunkExtractor) { - super(dataSource, dataSpec, C.DATA_TYPE_MEDIA_INITIALIZATION, trackFormat, trackSelectionReason, - trackSelectionData, C.TIME_UNSET, C.TIME_UNSET); + super( + dataSource, + dataSpec, + C.DATA_TYPE_MEDIA_INITIALIZATION, + trackFormat, + trackSelectionReason, + trackSelectionData, + C.TIME_UNSET, + C.TIME_UNSET); this.chunkExtractor = chunkExtractor; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/MediaChunk.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/MediaChunk.java index 690b9db4d86..7e4913db150 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/MediaChunk.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/MediaChunk.java @@ -47,8 +47,15 @@ public MediaChunk( long startTimeUs, long endTimeUs, long chunkIndex) { - super(dataSource, dataSpec, C.DATA_TYPE_MEDIA, trackFormat, trackSelectionReason, - trackSelectionData, startTimeUs, endTimeUs); + super( + dataSource, + dataSpec, + C.DATA_TYPE_MEDIA, + trackFormat, + trackSelectionReason, + trackSelectionData, + startTimeUs, + endTimeUs); Assertions.checkNotNull(trackFormat); this.chunkIndex = chunkIndex; } @@ -58,9 +65,6 @@ public long getNextChunkIndex() { return chunkIndex != C.INDEX_UNSET ? chunkIndex + 1 : C.INDEX_UNSET; } - /** - * Returns whether the chunk has been fully loaded. - */ + /** Returns whether the chunk has been fully loaded. */ public abstract boolean isLoadCompleted(); - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/MediaParserChunkExtractor.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/MediaParserChunkExtractor.java index fadf7ad6f77..47467bc2ea1 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/MediaParserChunkExtractor.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/MediaParserChunkExtractor.java @@ -137,9 +137,9 @@ public void release() { } @Override - public boolean read(ExtractorInput extractorInput) throws IOException { + public boolean read(ExtractorInput input) throws IOException { maybeExecutePendingSeek(); - inputReaderAdapter.setDataReader(extractorInput, extractorInput.getLength()); + inputReaderAdapter.setDataReader(input, input.getLength()); return mediaParser.advance(inputReaderAdapter); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/SingleSampleMediaChunk.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/SingleSampleMediaChunk.java index 4c84a91be2b..1ded32b70c9 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/SingleSampleMediaChunk.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/SingleSampleMediaChunk.java @@ -74,7 +74,6 @@ public SingleSampleMediaChunk( this.sampleFormat = sampleFormat; } - @Override public boolean isLoadCompleted() { return loadCompleted; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/mediaparser/OutputConsumerAdapterV30.java b/library/core/src/main/java/com/google/android/exoplayer2/source/mediaparser/OutputConsumerAdapterV30.java index f3bed012ec2..648f1c7275c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/mediaparser/OutputConsumerAdapterV30.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/mediaparser/OutputConsumerAdapterV30.java @@ -684,8 +684,8 @@ private static final class DataReaderAdapter implements DataReader { @Nullable public MediaParser.InputReader input; @Override - public int read(byte[] target, int offset, int length) throws IOException { - return Util.castNonNull(input).read(target, offset, length); + public int read(byte[] buffer, int offset, int length) throws IOException { + return Util.castNonNull(input).read(buffer, offset, length); } } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/SimpleSubtitleDecoder.java b/library/core/src/main/java/com/google/android/exoplayer2/text/SimpleSubtitleDecoder.java index fb5e1f198a4..3325bdc7237 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/SimpleSubtitleDecoder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/SimpleSubtitleDecoder.java @@ -29,7 +29,7 @@ public abstract class SimpleSubtitleDecoder private final String name; /** @param name The name of the decoder. */ - @SuppressWarnings("nullness:method.invocation.invalid") + @SuppressWarnings("nullness:method.invocation") protected SimpleSubtitleDecoder(String name) { super(new SubtitleInputBuffer[2], new SubtitleOutputBuffer[2]); this.name = name; @@ -42,7 +42,7 @@ public final String getName() { } @Override - public void setPositionUs(long timeUs) { + public void setPositionUs(long positionUs) { // Do nothing } @@ -89,5 +89,4 @@ protected final SubtitleDecoderException decode( */ protected abstract Subtitle decode(byte[] data, int size, boolean reset) throws SubtitleDecoderException; - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/SimpleSubtitleOutputBuffer.java b/library/core/src/main/java/com/google/android/exoplayer2/text/SimpleSubtitleOutputBuffer.java index 6807661c84e..ab2736e6804 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/SimpleSubtitleOutputBuffer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/SimpleSubtitleOutputBuffer.java @@ -15,9 +15,7 @@ */ package com.google.android.exoplayer2.text; -/** - * A {@link SubtitleOutputBuffer} for decoders that extend {@link SimpleSubtitleDecoder}. - */ +/** A {@link SubtitleOutputBuffer} for decoders that extend {@link SimpleSubtitleDecoder}. */ /* package */ final class SimpleSubtitleOutputBuffer extends SubtitleOutputBuffer { private final Owner owner; @@ -32,5 +30,4 @@ public SimpleSubtitleOutputBuffer(Owner owner) { public final void release() { owner.releaseOutputBuffer(this); } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/Subtitle.java b/library/core/src/main/java/com/google/android/exoplayer2/text/Subtitle.java index 861faa73f93..6581939d074 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/Subtitle.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/Subtitle.java @@ -53,5 +53,4 @@ public interface Subtitle { * @return A list of cues that should be displayed, possibly empty. */ List getCues(long timeUs); - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/SubtitleDecoder.java b/library/core/src/main/java/com/google/android/exoplayer2/text/SubtitleDecoder.java index 7571b0ffeff..e02ac36e5c1 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/SubtitleDecoder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/SubtitleDecoder.java @@ -23,11 +23,10 @@ public interface SubtitleDecoder /** * Informs the decoder of the current playback position. - *

      - * Must be called prior to each attempt to dequeue output buffers from the decoder. + * + *

      Must be called prior to each attempt to dequeue output buffers from the decoder. * * @param positionUs The current playback position in microseconds. */ void setPositionUs(long positionUs); - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/SubtitleDecoderException.java b/library/core/src/main/java/com/google/android/exoplayer2/text/SubtitleDecoderException.java index 7de577f18cc..05d10c4786c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/SubtitleDecoderException.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/SubtitleDecoderException.java @@ -21,9 +21,7 @@ /** Thrown when an error occurs decoding subtitle data. */ public class SubtitleDecoderException extends DecoderException { - /** - * @param message The detail message for this exception. - */ + /** @param message The detail message for this exception. */ public SubtitleDecoderException(String message) { super(message); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/SubtitleInputBuffer.java b/library/core/src/main/java/com/google/android/exoplayer2/text/SubtitleInputBuffer.java index 9866517a58e..1e80a62e119 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/SubtitleInputBuffer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/SubtitleInputBuffer.java @@ -22,13 +22,12 @@ public class SubtitleInputBuffer extends DecoderInputBuffer { /** - * An offset that must be added to the subtitle's event times after it's been decoded, or - * {@link Format#OFFSET_SAMPLE_RELATIVE} if {@link #timeUs} should be added. + * An offset that must be added to the subtitle's event times after it's been decoded, or {@link + * Format#OFFSET_SAMPLE_RELATIVE} if {@link #timeUs} should be added. */ public long subsampleOffsetUs; public SubtitleInputBuffer() { super(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL); } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/SubtitleOutputBuffer.java b/library/core/src/main/java/com/google/android/exoplayer2/text/SubtitleOutputBuffer.java index 1dfa9ffb452..7d9c8d9c329 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/SubtitleOutputBuffer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/SubtitleOutputBuffer.java @@ -33,14 +33,14 @@ public abstract class SubtitleOutputBuffer extends OutputBuffer implements Subti * * @param timeUs The time of the start of the subtitle in microseconds. * @param subtitle The subtitle. - * @param subsampleOffsetUs An offset that must be added to the subtitle's event times, or - * {@link Format#OFFSET_SAMPLE_RELATIVE} if {@code timeUs} should be added. + * @param subsampleOffsetUs An offset that must be added to the subtitle's event times, or {@link + * Format#OFFSET_SAMPLE_RELATIVE} if {@code timeUs} should be added. */ public void setContent(long timeUs, Subtitle subtitle, long subsampleOffsetUs) { this.timeUs = timeUs; this.subtitle = subtitle; - this.subsampleOffsetUs = subsampleOffsetUs == Format.OFFSET_SAMPLE_RELATIVE ? this.timeUs - : subsampleOffsetUs; + this.subsampleOffsetUs = + subsampleOffsetUs == Format.OFFSET_SAMPLE_RELATIVE ? this.timeUs : subsampleOffsetUs; } @Override @@ -68,5 +68,4 @@ public void clear() { super.clear(); subtitle = null; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/TextRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/text/TextRenderer.java index c721fe8da08..5a27d5bb3a9 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/TextRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/TextRenderer.java @@ -58,9 +58,7 @@ public final class TextRenderer extends BaseRenderer implements Callback { REPLACEMENT_STATE_WAIT_END_OF_STREAM }) private @interface ReplacementState {} - /** - * The decoder does not need to be replaced. - */ + /** The decoder does not need to be replaced. */ private static final int REPLACEMENT_STATE_NONE = 0; /** * The decoder needs to be replaced, but we haven't yet signaled an end of stream to the existing diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/cea/Cea608Decoder.java b/library/core/src/main/java/com/google/android/exoplayer2/text/cea/Cea608Decoder.java index 97890d7ee52..b0e3f3f15ee 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/cea/Cea608Decoder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/cea/Cea608Decoder.java @@ -141,72 +141,148 @@ public final class Cea608Decoder extends CeaDecoder { private static final byte CTRL_END_OF_CAPTION = 0x2F; // Basic North American 608 CC char set, mostly ASCII. Indexed by (char-0x20). - private static final int[] BASIC_CHARACTER_SET = new int[] { - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, // ! " # $ % & ' - 0x28, 0x29, // ( ) - 0xE1, // 2A: 225 'á' "Latin small letter A with acute" - 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, // + , - . / - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, // 0 1 2 3 4 5 6 7 - 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, // 8 9 : ; < = > ? - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, // @ A B C D E F G - 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, // H I J K L M N O - 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, // P Q R S T U V W - 0x58, 0x59, 0x5A, 0x5B, // X Y Z [ - 0xE9, // 5C: 233 'é' "Latin small letter E with acute" - 0x5D, // ] - 0xED, // 5E: 237 'í' "Latin small letter I with acute" - 0xF3, // 5F: 243 'ó' "Latin small letter O with acute" - 0xFA, // 60: 250 'ú' "Latin small letter U with acute" - 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, // a b c d e f g - 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, // h i j k l m n o - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, // p q r s t u v w - 0x78, 0x79, 0x7A, // x y z - 0xE7, // 7B: 231 'ç' "Latin small letter C with cedilla" - 0xF7, // 7C: 247 '÷' "Division sign" - 0xD1, // 7D: 209 'Ñ' "Latin capital letter N with tilde" - 0xF1, // 7E: 241 'ñ' "Latin small letter N with tilde" - 0x25A0 // 7F: "Black Square" (NB: 2588 = Full Block) - }; + private static final int[] BASIC_CHARACTER_SET = + new int[] { + 0x20, + 0x21, + 0x22, + 0x23, + 0x24, + 0x25, + 0x26, + 0x27, // ! " # $ % & ' + 0x28, + 0x29, // ( ) + 0xE1, // 2A: 225 'á' "Latin small letter A with acute" + 0x2B, + 0x2C, + 0x2D, + 0x2E, + 0x2F, // + , - . / + 0x30, + 0x31, + 0x32, + 0x33, + 0x34, + 0x35, + 0x36, + 0x37, // 0 1 2 3 4 5 6 7 + 0x38, + 0x39, + 0x3A, + 0x3B, + 0x3C, + 0x3D, + 0x3E, + 0x3F, // 8 9 : ; < = > ? + 0x40, + 0x41, + 0x42, + 0x43, + 0x44, + 0x45, + 0x46, + 0x47, // @ A B C D E F G + 0x48, + 0x49, + 0x4A, + 0x4B, + 0x4C, + 0x4D, + 0x4E, + 0x4F, // H I J K L M N O + 0x50, + 0x51, + 0x52, + 0x53, + 0x54, + 0x55, + 0x56, + 0x57, // P Q R S T U V W + 0x58, + 0x59, + 0x5A, + 0x5B, // X Y Z [ + 0xE9, // 5C: 233 'é' "Latin small letter E with acute" + 0x5D, // ] + 0xED, // 5E: 237 'í' "Latin small letter I with acute" + 0xF3, // 5F: 243 'ó' "Latin small letter O with acute" + 0xFA, // 60: 250 'ú' "Latin small letter U with acute" + 0x61, + 0x62, + 0x63, + 0x64, + 0x65, + 0x66, + 0x67, // a b c d e f g + 0x68, + 0x69, + 0x6A, + 0x6B, + 0x6C, + 0x6D, + 0x6E, + 0x6F, // h i j k l m n o + 0x70, + 0x71, + 0x72, + 0x73, + 0x74, + 0x75, + 0x76, + 0x77, // p q r s t u v w + 0x78, + 0x79, + 0x7A, // x y z + 0xE7, // 7B: 231 'ç' "Latin small letter C with cedilla" + 0xF7, // 7C: 247 '÷' "Division sign" + 0xD1, // 7D: 209 'Ñ' "Latin capital letter N with tilde" + 0xF1, // 7E: 241 'ñ' "Latin small letter N with tilde" + 0x25A0 // 7F: "Black Square" (NB: 2588 = Full Block) + }; // Special North American 608 CC char set. - private static final int[] SPECIAL_CHARACTER_SET = new int[] { - 0xAE, // 30: 174 '®' "Registered Sign" - registered trademark symbol - 0xB0, // 31: 176 '°' "Degree Sign" - 0xBD, // 32: 189 '½' "Vulgar Fraction One Half" (1/2 symbol) - 0xBF, // 33: 191 '¿' "Inverted Question Mark" - 0x2122, // 34: "Trade Mark Sign" (tm superscript) - 0xA2, // 35: 162 '¢' "Cent Sign" - 0xA3, // 36: 163 '£' "Pound Sign" - pounds sterling - 0x266A, // 37: "Eighth Note" - music note - 0xE0, // 38: 224 'à' "Latin small letter A with grave" - 0x20, // 39: TRANSPARENT SPACE - for now use ordinary space - 0xE8, // 3A: 232 'è' "Latin small letter E with grave" - 0xE2, // 3B: 226 'â' "Latin small letter A with circumflex" - 0xEA, // 3C: 234 'ê' "Latin small letter E with circumflex" - 0xEE, // 3D: 238 'î' "Latin small letter I with circumflex" - 0xF4, // 3E: 244 'ô' "Latin small letter O with circumflex" - 0xFB // 3F: 251 'û' "Latin small letter U with circumflex" - }; + private static final int[] SPECIAL_CHARACTER_SET = + new int[] { + 0xAE, // 30: 174 '®' "Registered Sign" - registered trademark symbol + 0xB0, // 31: 176 '°' "Degree Sign" + 0xBD, // 32: 189 '½' "Vulgar Fraction One Half" (1/2 symbol) + 0xBF, // 33: 191 '¿' "Inverted Question Mark" + 0x2122, // 34: "Trade Mark Sign" (tm superscript) + 0xA2, // 35: 162 '¢' "Cent Sign" + 0xA3, // 36: 163 '£' "Pound Sign" - pounds sterling + 0x266A, // 37: "Eighth Note" - music note + 0xE0, // 38: 224 'à' "Latin small letter A with grave" + 0x20, // 39: TRANSPARENT SPACE - for now use ordinary space + 0xE8, // 3A: 232 'è' "Latin small letter E with grave" + 0xE2, // 3B: 226 'â' "Latin small letter A with circumflex" + 0xEA, // 3C: 234 'ê' "Latin small letter E with circumflex" + 0xEE, // 3D: 238 'î' "Latin small letter I with circumflex" + 0xF4, // 3E: 244 'ô' "Latin small letter O with circumflex" + 0xFB // 3F: 251 'û' "Latin small letter U with circumflex" + }; // Extended Spanish/Miscellaneous and French char set. - private static final int[] SPECIAL_ES_FR_CHARACTER_SET = new int[] { - // Spanish and misc. - 0xC1, 0xC9, 0xD3, 0xDA, 0xDC, 0xFC, 0x2018, 0xA1, - 0x2A, 0x27, 0x2014, 0xA9, 0x2120, 0x2022, 0x201C, 0x201D, - // French. - 0xC0, 0xC2, 0xC7, 0xC8, 0xCA, 0xCB, 0xEB, 0xCE, - 0xCF, 0xEF, 0xD4, 0xD9, 0xF9, 0xDB, 0xAB, 0xBB - }; + private static final int[] SPECIAL_ES_FR_CHARACTER_SET = + new int[] { + // Spanish and misc. + 0xC1, 0xC9, 0xD3, 0xDA, 0xDC, 0xFC, 0x2018, 0xA1, + 0x2A, 0x27, 0x2014, 0xA9, 0x2120, 0x2022, 0x201C, 0x201D, + // French. + 0xC0, 0xC2, 0xC7, 0xC8, 0xCA, 0xCB, 0xEB, 0xCE, + 0xCF, 0xEF, 0xD4, 0xD9, 0xF9, 0xDB, 0xAB, 0xBB + }; - //Extended Portuguese and German/Danish char set. - private static final int[] SPECIAL_PT_DE_CHARACTER_SET = new int[] { - // Portuguese. - 0xC3, 0xE3, 0xCD, 0xCC, 0xEC, 0xD2, 0xF2, 0xD5, - 0xF5, 0x7B, 0x7D, 0x5C, 0x5E, 0x5F, 0x7C, 0x7E, - // German/Danish. - 0xC4, 0xE4, 0xD6, 0xF6, 0xDF, 0xA5, 0xA4, 0x2502, - 0xC5, 0xE5, 0xD8, 0xF8, 0x250C, 0x2510, 0x2514, 0x2518 - }; + // Extended Portuguese and German/Danish char set. + private static final int[] SPECIAL_PT_DE_CHARACTER_SET = + new int[] { + // Portuguese. + 0xC3, 0xE3, 0xCD, 0xCC, 0xEC, 0xD2, 0xF2, 0xD5, + 0xF5, 0x7B, 0x7D, 0x5C, 0x5E, 0x5F, 0x7C, 0x7E, + // German/Danish. + 0xC4, 0xE4, 0xD6, 0xF6, 0xDF, 0xA5, 0xA4, 0x2502, + 0xC5, 0xE5, 0xD8, 0xF8, 0x250C, 0x2510, 0x2514, 0x2518 + }; private static final boolean[] ODD_PARITY_BYTE_TABLE = { false, true, true, false, true, false, false, true, // 0 @@ -383,8 +459,8 @@ protected void decode(SubtitleInputBuffer inputBuffer) { ccData.reset(subtitleData.array(), subtitleData.limit()); boolean captionDataProcessed = false; while (ccData.bytesLeft() >= packetLength) { - byte ccHeader = packetLength == 2 ? CC_IMPLICIT_DATA_HEADER - : (byte) ccData.readUnsignedByte(); + byte ccHeader = + packetLength == 2 ? CC_IMPLICIT_DATA_HEADER : (byte) ccData.readUnsignedByte(); int ccByte1 = ccData.readUnsignedByte(); int ccByte2 = ccData.readUnsignedByte(); @@ -669,7 +745,8 @@ private void setCaptionMode(int captionMode) { // Clear the working memory. resetCueBuilders(); - if (oldCaptionMode == CC_MODE_PAINT_ON || captionMode == CC_MODE_ROLL_UP + if (oldCaptionMode == CC_MODE_PAINT_ON + || captionMode == CC_MODE_ROLL_UP || captionMode == CC_MODE_UNKNOWN) { // When switching from paint-on or to roll-up or unknown, we also need to clear the caption. cues = Collections.emptyList(); @@ -1065,9 +1142,7 @@ public CueStyle(int style, boolean underline, int start) { this.underline = underline; this.start = start; } - } - } /** See ANSI/CTA-608-E R-2014 Annex C.9 for Caption Erase Logic. */ diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/cea/Cea708Decoder.java b/library/core/src/main/java/com/google/android/exoplayer2/text/cea/Cea708Decoder.java index e91edcd3077..d09be81f371 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/cea/Cea708Decoder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/cea/Cea708Decoder.java @@ -57,62 +57,62 @@ public final class Cea708Decoder extends CeaDecoder { private static final int CC_VALID_FLAG = 0x04; // Base Commands - private static final int GROUP_C0_END = 0x1F; // Miscellaneous Control Codes - private static final int GROUP_G0_END = 0x7F; // ASCII Printable Characters - private static final int GROUP_C1_END = 0x9F; // Captioning Command Control Codes - private static final int GROUP_G1_END = 0xFF; // ISO 8859-1 LATIN-1 Character Set + private static final int GROUP_C0_END = 0x1F; // Miscellaneous Control Codes + private static final int GROUP_G0_END = 0x7F; // ASCII Printable Characters + private static final int GROUP_C1_END = 0x9F; // Captioning Command Control Codes + private static final int GROUP_G1_END = 0xFF; // ISO 8859-1 LATIN-1 Character Set // Extended Commands - private static final int GROUP_C2_END = 0x1F; // Extended Control Code Set 1 - private static final int GROUP_G2_END = 0x7F; // Extended Miscellaneous Characters - private static final int GROUP_C3_END = 0x9F; // Extended Control Code Set 2 - private static final int GROUP_G3_END = 0xFF; // Future Expansion + private static final int GROUP_C2_END = 0x1F; // Extended Control Code Set 1 + private static final int GROUP_G2_END = 0x7F; // Extended Miscellaneous Characters + private static final int GROUP_C3_END = 0x9F; // Extended Control Code Set 2 + private static final int GROUP_G3_END = 0xFF; // Future Expansion // Group C0 Commands - private static final int COMMAND_NUL = 0x00; // Nul - private static final int COMMAND_ETX = 0x03; // EndOfText - private static final int COMMAND_BS = 0x08; // Backspace - private static final int COMMAND_FF = 0x0C; // FormFeed (Flush) - private static final int COMMAND_CR = 0x0D; // CarriageReturn - private static final int COMMAND_HCR = 0x0E; // ClearLine - private static final int COMMAND_EXT1 = 0x10; // Extended Control Code Flag + private static final int COMMAND_NUL = 0x00; // Nul + private static final int COMMAND_ETX = 0x03; // EndOfText + private static final int COMMAND_BS = 0x08; // Backspace + private static final int COMMAND_FF = 0x0C; // FormFeed (Flush) + private static final int COMMAND_CR = 0x0D; // CarriageReturn + private static final int COMMAND_HCR = 0x0E; // ClearLine + private static final int COMMAND_EXT1 = 0x10; // Extended Control Code Flag private static final int COMMAND_EXT1_START = 0x11; private static final int COMMAND_EXT1_END = 0x17; private static final int COMMAND_P16_START = 0x18; private static final int COMMAND_P16_END = 0x1F; // Group C1 Commands - private static final int COMMAND_CW0 = 0x80; // SetCurrentWindow to 0 - private static final int COMMAND_CW1 = 0x81; // SetCurrentWindow to 1 - private static final int COMMAND_CW2 = 0x82; // SetCurrentWindow to 2 - private static final int COMMAND_CW3 = 0x83; // SetCurrentWindow to 3 - private static final int COMMAND_CW4 = 0x84; // SetCurrentWindow to 4 - private static final int COMMAND_CW5 = 0x85; // SetCurrentWindow to 5 - private static final int COMMAND_CW6 = 0x86; // SetCurrentWindow to 6 - private static final int COMMAND_CW7 = 0x87; // SetCurrentWindow to 7 - private static final int COMMAND_CLW = 0x88; // ClearWindows (+1 byte) - private static final int COMMAND_DSW = 0x89; // DisplayWindows (+1 byte) - private static final int COMMAND_HDW = 0x8A; // HideWindows (+1 byte) - private static final int COMMAND_TGW = 0x8B; // ToggleWindows (+1 byte) - private static final int COMMAND_DLW = 0x8C; // DeleteWindows (+1 byte) - private static final int COMMAND_DLY = 0x8D; // Delay (+1 byte) - private static final int COMMAND_DLC = 0x8E; // DelayCancel - private static final int COMMAND_RST = 0x8F; // Reset - private static final int COMMAND_SPA = 0x90; // SetPenAttributes (+2 bytes) - private static final int COMMAND_SPC = 0x91; // SetPenColor (+3 bytes) - private static final int COMMAND_SPL = 0x92; // SetPenLocation (+2 bytes) - private static final int COMMAND_SWA = 0x97; // SetWindowAttributes (+4 bytes) - private static final int COMMAND_DF0 = 0x98; // DefineWindow 0 (+6 bytes) - private static final int COMMAND_DF1 = 0x99; // DefineWindow 1 (+6 bytes) - private static final int COMMAND_DF2 = 0x9A; // DefineWindow 2 (+6 bytes) - private static final int COMMAND_DF3 = 0x9B; // DefineWindow 3 (+6 bytes) + private static final int COMMAND_CW0 = 0x80; // SetCurrentWindow to 0 + private static final int COMMAND_CW1 = 0x81; // SetCurrentWindow to 1 + private static final int COMMAND_CW2 = 0x82; // SetCurrentWindow to 2 + private static final int COMMAND_CW3 = 0x83; // SetCurrentWindow to 3 + private static final int COMMAND_CW4 = 0x84; // SetCurrentWindow to 4 + private static final int COMMAND_CW5 = 0x85; // SetCurrentWindow to 5 + private static final int COMMAND_CW6 = 0x86; // SetCurrentWindow to 6 + private static final int COMMAND_CW7 = 0x87; // SetCurrentWindow to 7 + private static final int COMMAND_CLW = 0x88; // ClearWindows (+1 byte) + private static final int COMMAND_DSW = 0x89; // DisplayWindows (+1 byte) + private static final int COMMAND_HDW = 0x8A; // HideWindows (+1 byte) + private static final int COMMAND_TGW = 0x8B; // ToggleWindows (+1 byte) + private static final int COMMAND_DLW = 0x8C; // DeleteWindows (+1 byte) + private static final int COMMAND_DLY = 0x8D; // Delay (+1 byte) + private static final int COMMAND_DLC = 0x8E; // DelayCancel + private static final int COMMAND_RST = 0x8F; // Reset + private static final int COMMAND_SPA = 0x90; // SetPenAttributes (+2 bytes) + private static final int COMMAND_SPC = 0x91; // SetPenColor (+3 bytes) + private static final int COMMAND_SPL = 0x92; // SetPenLocation (+2 bytes) + private static final int COMMAND_SWA = 0x97; // SetWindowAttributes (+4 bytes) + private static final int COMMAND_DF0 = 0x98; // DefineWindow 0 (+6 bytes) + private static final int COMMAND_DF1 = 0x99; // DefineWindow 1 (+6 bytes) + private static final int COMMAND_DF2 = 0x9A; // DefineWindow 2 (+6 bytes) + private static final int COMMAND_DF3 = 0x9B; // DefineWindow 3 (+6 bytes) private static final int COMMAND_DF4 = 0x9C; // DefineWindow 4 (+6 bytes) - private static final int COMMAND_DF5 = 0x9D; // DefineWindow 5 (+6 bytes) - private static final int COMMAND_DF6 = 0x9E; // DefineWindow 6 (+6 bytes) - private static final int COMMAND_DF7 = 0x9F; // DefineWindow 7 (+6 bytes) + private static final int COMMAND_DF5 = 0x9D; // DefineWindow 5 (+6 bytes) + private static final int COMMAND_DF6 = 0x9E; // DefineWindow 6 (+6 bytes) + private static final int COMMAND_DF7 = 0x9F; // DefineWindow 7 (+6 bytes) // G0 Table Special Chars - private static final int CHARACTER_MN = 0x7F; // MusicNote + private static final int CHARACTER_MN = 0x7F; // MusicNote // G2 Table Special Chars private static final int CHARACTER_TSP = 0x20; @@ -825,7 +825,6 @@ public DtvCcPacket(int sequenceNumber, int packetSize) { packetData = new byte[2 * packetSize - 1]; currentIndex = 0; } - } // TODO: There is a lot of overlap between Cea708Decoder.CueInfoBuilder and @@ -872,45 +871,64 @@ private static final class CueInfoBuilder { private static final int PEN_OFFSET_NORMAL = 1; // The window style properties are specified in the CEA-708 specification. - private static final int[] WINDOW_STYLE_JUSTIFICATION = new int[] { - JUSTIFICATION_LEFT, JUSTIFICATION_LEFT, JUSTIFICATION_LEFT, - JUSTIFICATION_LEFT, JUSTIFICATION_LEFT, JUSTIFICATION_CENTER, - JUSTIFICATION_LEFT - }; - private static final int[] WINDOW_STYLE_PRINT_DIRECTION = new int[] { - DIRECTION_LEFT_TO_RIGHT, DIRECTION_LEFT_TO_RIGHT, DIRECTION_LEFT_TO_RIGHT, - DIRECTION_LEFT_TO_RIGHT, DIRECTION_LEFT_TO_RIGHT, DIRECTION_LEFT_TO_RIGHT, - DIRECTION_TOP_TO_BOTTOM - }; - private static final int[] WINDOW_STYLE_SCROLL_DIRECTION = new int[] { - DIRECTION_BOTTOM_TO_TOP, DIRECTION_BOTTOM_TO_TOP, DIRECTION_BOTTOM_TO_TOP, - DIRECTION_BOTTOM_TO_TOP, DIRECTION_BOTTOM_TO_TOP, DIRECTION_BOTTOM_TO_TOP, - DIRECTION_RIGHT_TO_LEFT - }; - private static final boolean[] WINDOW_STYLE_WORD_WRAP = new boolean[] { - false, false, false, true, true, true, false - }; - private static final int[] WINDOW_STYLE_FILL = new int[] { - COLOR_SOLID_BLACK, COLOR_TRANSPARENT, COLOR_SOLID_BLACK, COLOR_SOLID_BLACK, - COLOR_TRANSPARENT, COLOR_SOLID_BLACK, COLOR_SOLID_BLACK - }; + private static final int[] WINDOW_STYLE_JUSTIFICATION = + new int[] { + JUSTIFICATION_LEFT, JUSTIFICATION_LEFT, JUSTIFICATION_LEFT, + JUSTIFICATION_LEFT, JUSTIFICATION_LEFT, JUSTIFICATION_CENTER, + JUSTIFICATION_LEFT + }; + private static final int[] WINDOW_STYLE_PRINT_DIRECTION = + new int[] { + DIRECTION_LEFT_TO_RIGHT, DIRECTION_LEFT_TO_RIGHT, DIRECTION_LEFT_TO_RIGHT, + DIRECTION_LEFT_TO_RIGHT, DIRECTION_LEFT_TO_RIGHT, DIRECTION_LEFT_TO_RIGHT, + DIRECTION_TOP_TO_BOTTOM + }; + private static final int[] WINDOW_STYLE_SCROLL_DIRECTION = + new int[] { + DIRECTION_BOTTOM_TO_TOP, DIRECTION_BOTTOM_TO_TOP, DIRECTION_BOTTOM_TO_TOP, + DIRECTION_BOTTOM_TO_TOP, DIRECTION_BOTTOM_TO_TOP, DIRECTION_BOTTOM_TO_TOP, + DIRECTION_RIGHT_TO_LEFT + }; + private static final boolean[] WINDOW_STYLE_WORD_WRAP = + new boolean[] {false, false, false, true, true, true, false}; + private static final int[] WINDOW_STYLE_FILL = + new int[] { + COLOR_SOLID_BLACK, + COLOR_TRANSPARENT, + COLOR_SOLID_BLACK, + COLOR_SOLID_BLACK, + COLOR_TRANSPARENT, + COLOR_SOLID_BLACK, + COLOR_SOLID_BLACK + }; // The pen style properties are specified in the CEA-708 specification. - private static final int[] PEN_STYLE_FONT_STYLE = new int[] { - PEN_FONT_STYLE_DEFAULT, PEN_FONT_STYLE_MONOSPACED_WITH_SERIFS, - PEN_FONT_STYLE_PROPORTIONALLY_SPACED_WITH_SERIFS, PEN_FONT_STYLE_MONOSPACED_WITHOUT_SERIFS, - PEN_FONT_STYLE_PROPORTIONALLY_SPACED_WITHOUT_SERIFS, - PEN_FONT_STYLE_MONOSPACED_WITHOUT_SERIFS, - PEN_FONT_STYLE_PROPORTIONALLY_SPACED_WITHOUT_SERIFS - }; - private static final int[] PEN_STYLE_EDGE_TYPE = new int[] { - BORDER_AND_EDGE_TYPE_NONE, BORDER_AND_EDGE_TYPE_NONE, BORDER_AND_EDGE_TYPE_NONE, - BORDER_AND_EDGE_TYPE_NONE, BORDER_AND_EDGE_TYPE_NONE, BORDER_AND_EDGE_TYPE_UNIFORM, - BORDER_AND_EDGE_TYPE_UNIFORM - }; - private static final int[] PEN_STYLE_BACKGROUND = new int[] { - COLOR_SOLID_BLACK, COLOR_SOLID_BLACK, COLOR_SOLID_BLACK, COLOR_SOLID_BLACK, - COLOR_SOLID_BLACK, COLOR_TRANSPARENT, COLOR_TRANSPARENT}; + private static final int[] PEN_STYLE_FONT_STYLE = + new int[] { + PEN_FONT_STYLE_DEFAULT, + PEN_FONT_STYLE_MONOSPACED_WITH_SERIFS, + PEN_FONT_STYLE_PROPORTIONALLY_SPACED_WITH_SERIFS, + PEN_FONT_STYLE_MONOSPACED_WITHOUT_SERIFS, + PEN_FONT_STYLE_PROPORTIONALLY_SPACED_WITHOUT_SERIFS, + PEN_FONT_STYLE_MONOSPACED_WITHOUT_SERIFS, + PEN_FONT_STYLE_PROPORTIONALLY_SPACED_WITHOUT_SERIFS + }; + private static final int[] PEN_STYLE_EDGE_TYPE = + new int[] { + BORDER_AND_EDGE_TYPE_NONE, BORDER_AND_EDGE_TYPE_NONE, BORDER_AND_EDGE_TYPE_NONE, + BORDER_AND_EDGE_TYPE_NONE, BORDER_AND_EDGE_TYPE_NONE, BORDER_AND_EDGE_TYPE_UNIFORM, + BORDER_AND_EDGE_TYPE_UNIFORM + }; + private static final int[] PEN_STYLE_BACKGROUND = + new int[] { + COLOR_SOLID_BLACK, + COLOR_SOLID_BLACK, + COLOR_SOLID_BLACK, + COLOR_SOLID_BLACK, + COLOR_SOLID_BLACK, + COLOR_TRANSPARENT, + COLOR_TRANSPARENT + }; private final List rolledUpCaptions; private final SpannableStringBuilder captionStringBuilder; @@ -992,9 +1010,19 @@ public boolean isVisible() { return visible; } - public void defineWindow(boolean visible, boolean rowLock, boolean columnLock, int priority, - boolean relativePositioning, int verticalAnchor, int horizontalAnchor, int rowCount, - int columnCount, int anchorId, int windowStyleId, int penStyleId) { + public void defineWindow( + boolean visible, + boolean rowLock, + boolean columnLock, + int priority, + boolean relativePositioning, + int verticalAnchor, + int horizontalAnchor, + int rowCount, + int columnCount, + int anchorId, + int windowStyleId, + int penStyleId) { this.defined = true; this.visible = visible; this.rowLock = rowLock; @@ -1022,8 +1050,11 @@ public void defineWindow(boolean visible, boolean rowLock, boolean columnLock, i // windowStyleId is 1-based. int windowStyleIdIndex = windowStyleId - 1; // Note that Border type and border color are the same for all window styles. - setWindowAttributes(WINDOW_STYLE_FILL[windowStyleIdIndex], COLOR_TRANSPARENT, - WINDOW_STYLE_WORD_WRAP[windowStyleIdIndex], BORDER_AND_EDGE_TYPE_NONE, + setWindowAttributes( + WINDOW_STYLE_FILL[windowStyleIdIndex], + COLOR_TRANSPARENT, + WINDOW_STYLE_WORD_WRAP[windowStyleIdIndex], + BORDER_AND_EDGE_TYPE_NONE, WINDOW_STYLE_PRINT_DIRECTION[windowStyleIdIndex], WINDOW_STYLE_SCROLL_DIRECTION[windowStyleIdIndex], WINDOW_STYLE_JUSTIFICATION[windowStyleIdIndex]); @@ -1035,34 +1066,53 @@ public void defineWindow(boolean visible, boolean rowLock, boolean columnLock, i int penStyleIdIndex = penStyleId - 1; // Note that pen size, offset, italics, underline, foreground color, and foreground // opacity are the same for all pen styles. - setPenAttributes(0, PEN_OFFSET_NORMAL, PEN_SIZE_STANDARD, false, false, - PEN_STYLE_EDGE_TYPE[penStyleIdIndex], PEN_STYLE_FONT_STYLE[penStyleIdIndex]); + setPenAttributes( + 0, + PEN_OFFSET_NORMAL, + PEN_SIZE_STANDARD, + false, + false, + PEN_STYLE_EDGE_TYPE[penStyleIdIndex], + PEN_STYLE_FONT_STYLE[penStyleIdIndex]); setPenColor(COLOR_SOLID_WHITE, PEN_STYLE_BACKGROUND[penStyleIdIndex], COLOR_SOLID_BLACK); } } - - public void setWindowAttributes(int fillColor, int borderColor, boolean wordWrapToggle, - int borderType, int printDirection, int scrollDirection, int justification) { + public void setWindowAttributes( + int fillColor, + int borderColor, + boolean wordWrapToggle, + int borderType, + int printDirection, + int scrollDirection, + int justification) { this.windowFillColor = fillColor; // TODO: Add support for border color and types. // TODO: Add support for word wrap. // TODO: Add support for other scroll directions. // TODO: Add support for other print directions. this.justification = justification; - } - public void setPenAttributes(int textTag, int offset, int penSize, boolean italicsToggle, - boolean underlineToggle, int edgeType, int fontStyle) { + public void setPenAttributes( + int textTag, + int offset, + int penSize, + boolean italicsToggle, + boolean underlineToggle, + int edgeType, + int fontStyle) { // TODO: Add support for text tags. // TODO: Add support for other offsets. // TODO: Add support for other pen sizes. if (italicsStartPosition != C.POSITION_UNSET) { if (!italicsToggle) { - captionStringBuilder.setSpan(new StyleSpan(Typeface.ITALIC), italicsStartPosition, - captionStringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + captionStringBuilder.setSpan( + new StyleSpan(Typeface.ITALIC), + italicsStartPosition, + captionStringBuilder.length(), + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); italicsStartPosition = C.POSITION_UNSET; } } else if (italicsToggle) { @@ -1071,8 +1121,11 @@ public void setPenAttributes(int textTag, int offset, int penSize, boolean itali if (underlineStartPosition != C.POSITION_UNSET) { if (!underlineToggle) { - captionStringBuilder.setSpan(new UnderlineSpan(), underlineStartPosition, - captionStringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + captionStringBuilder.setSpan( + new UnderlineSpan(), + underlineStartPosition, + captionStringBuilder.length(), + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); underlineStartPosition = C.POSITION_UNSET; } } else if (underlineToggle) { @@ -1086,8 +1139,10 @@ public void setPenAttributes(int textTag, int offset, int penSize, boolean itali public void setPenColor(int foregroundColor, int backgroundColor, int edgeColor) { if (foregroundColorStartPosition != C.POSITION_UNSET) { if (this.foregroundColor != foregroundColor) { - captionStringBuilder.setSpan(new ForegroundColorSpan(this.foregroundColor), - foregroundColorStartPosition, captionStringBuilder.length(), + captionStringBuilder.setSpan( + new ForegroundColorSpan(this.foregroundColor), + foregroundColorStartPosition, + captionStringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } } @@ -1098,8 +1153,10 @@ public void setPenColor(int foregroundColor, int backgroundColor, int edgeColor) if (backgroundColorStartPosition != C.POSITION_UNSET) { if (this.backgroundColor != backgroundColor) { - captionStringBuilder.setSpan(new BackgroundColorSpan(this.backgroundColor), - backgroundColorStartPosition, captionStringBuilder.length(), + captionStringBuilder.setSpan( + new BackgroundColorSpan(this.backgroundColor), + backgroundColorStartPosition, + captionStringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } } @@ -1165,23 +1222,35 @@ public SpannableString buildSpannableString() { if (length > 0) { if (italicsStartPosition != C.POSITION_UNSET) { - spannableStringBuilder.setSpan(new StyleSpan(Typeface.ITALIC), italicsStartPosition, - length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + spannableStringBuilder.setSpan( + new StyleSpan(Typeface.ITALIC), + italicsStartPosition, + length, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } if (underlineStartPosition != C.POSITION_UNSET) { - spannableStringBuilder.setSpan(new UnderlineSpan(), underlineStartPosition, - length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + spannableStringBuilder.setSpan( + new UnderlineSpan(), + underlineStartPosition, + length, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } if (foregroundColorStartPosition != C.POSITION_UNSET) { - spannableStringBuilder.setSpan(new ForegroundColorSpan(foregroundColor), - foregroundColorStartPosition, length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + spannableStringBuilder.setSpan( + new ForegroundColorSpan(foregroundColor), + foregroundColorStartPosition, + length, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } if (backgroundColorStartPosition != C.POSITION_UNSET) { - spannableStringBuilder.setSpan(new BackgroundColorSpan(backgroundColor), - backgroundColorStartPosition, length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + spannableStringBuilder.setSpan( + new BackgroundColorSpan(backgroundColor), + backgroundColorStartPosition, + length, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } } @@ -1308,10 +1377,7 @@ public static int getArgbColorFromCeaColor(int red, int green, int blue, int opa // TODO: Add support for the Alternative Minimum Color List or the full 64 RGB combinations. // Return values based on the Minimum Color List - return Color.argb(alpha, - (red > 1 ? 255 : 0), - (green > 1 ? 255 : 0), - (blue > 1 ? 255 : 0)); + return Color.argb(alpha, (red > 1 ? 255 : 0), (green > 1 ? 255 : 0), (blue > 1 ? 255 : 0)); } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/cea/CeaDecoder.java b/library/core/src/main/java/com/google/android/exoplayer2/text/cea/CeaDecoder.java index 81ef58a7129..4db023cc9c9 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/cea/CeaDecoder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/cea/CeaDecoder.java @@ -28,9 +28,7 @@ import java.util.ArrayDeque; import java.util.PriorityQueue; -/** - * Base class for subtitle parsers for CEA captions. - */ +/** Base class for subtitle parsers for CEA captions. */ /* package */ abstract class CeaDecoder implements SubtitleDecoder { private static final int NUM_INPUT_BUFFERS = 10; @@ -44,7 +42,7 @@ private long playbackPositionUs; private long queuedInputBufferCount; - @SuppressWarnings("nullness:methodref.receiver.bound.invalid") + @SuppressWarnings("nullness:methodref.receiver.bound") public CeaDecoder() { availableInputBuffers = new ArrayDeque<>(); for (int i = 0; i < NUM_INPUT_BUFFERS; i++) { @@ -154,14 +152,10 @@ public void release() { // Do nothing. } - /** - * Returns whether there is data available to create a new {@link Subtitle}. - */ + /** Returns whether there is data available to create a new {@link Subtitle}. */ protected abstract boolean isNewSubtitleDataAvailable(); - /** - * Creates a {@link Subtitle} from the available data. - */ + /** Creates a {@link Subtitle} from the available data. */ protected abstract Subtitle createSubtitle(); /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/cea/CeaSubtitle.java b/library/core/src/main/java/com/google/android/exoplayer2/text/cea/CeaSubtitle.java index 738f251e279..bc02caf5c08 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/cea/CeaSubtitle.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/cea/CeaSubtitle.java @@ -22,16 +22,12 @@ import java.util.Collections; import java.util.List; -/** - * A representation of a CEA subtitle. - */ +/** A representation of a CEA subtitle. */ /* package */ final class CeaSubtitle implements Subtitle { private final List cues; - /** - * @param cues The subtitle cues. - */ + /** @param cues The subtitle cues. */ public CeaSubtitle(List cues) { this.cues = cues; } @@ -56,5 +52,4 @@ public long getEventTime(int index) { public List getCues(long timeUs) { return timeUs >= 0 ? cues : Collections.emptyList(); } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/dvb/DvbDecoder.java b/library/core/src/main/java/com/google/android/exoplayer2/text/dvb/DvbDecoder.java index 22ce893fce9..0e98a2e7ebf 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/dvb/DvbDecoder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/dvb/DvbDecoder.java @@ -26,9 +26,9 @@ public final class DvbDecoder extends SimpleSubtitleDecoder { private final DvbParser parser; /** - * @param initializationData The initialization data for the decoder. The initialization data - * must consist of a single byte array containing 5 bytes: flag_pes_stripped (1), - * composition_page (2), ancillary_page (2). + * @param initializationData The initialization data for the decoder. The initialization data must + * consist of a single byte array containing 5 bytes: flag_pes_stripped (1), composition_page + * (2), ancillary_page (2). */ public DvbDecoder(List initializationData) { super("DvbDecoder"); @@ -45,5 +45,4 @@ protected Subtitle decode(byte[] data, int length, boolean reset) { } return new DvbSubtitle(parser.decode(data, length)); } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/dvb/DvbParser.java b/library/core/src/main/java/com/google/android/exoplayer2/text/dvb/DvbParser.java index 5cdbfdf72ec..1d5ec8454c4 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/dvb/DvbParser.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/dvb/DvbParser.java @@ -34,9 +34,7 @@ import java.util.List; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; -/** - * Parses {@link Cue}s from a DVB subtitle bitstream. - */ +/** Parses {@link Cue}s from a DVB subtitle bitstream. */ /* package */ final class DvbParser { private static final String TAG = "DvbParser"; @@ -72,15 +70,14 @@ private static final int DATA_TYPE_END_LINE = 0xF0; // Clut mapping tables, as defined by ETSI EN 300 743 10.4, 10.5, 10.6 - private static final byte[] defaultMap2To4 = { - (byte) 0x00, (byte) 0x07, (byte) 0x08, (byte) 0x0F}; - private static final byte[] defaultMap2To8 = { - (byte) 0x00, (byte) 0x77, (byte) 0x88, (byte) 0xFF}; + private static final byte[] defaultMap2To4 = {(byte) 0x00, (byte) 0x07, (byte) 0x08, (byte) 0x0F}; + private static final byte[] defaultMap2To8 = {(byte) 0x00, (byte) 0x77, (byte) 0x88, (byte) 0xFF}; private static final byte[] defaultMap4To8 = { - (byte) 0x00, (byte) 0x11, (byte) 0x22, (byte) 0x33, - (byte) 0x44, (byte) 0x55, (byte) 0x66, (byte) 0x77, - (byte) 0x88, (byte) 0x99, (byte) 0xAA, (byte) 0xBB, - (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, (byte) 0xFF}; + (byte) 0x00, (byte) 0x11, (byte) 0x22, (byte) 0x33, + (byte) 0x44, (byte) 0x55, (byte) 0x66, (byte) 0x77, + (byte) 0x88, (byte) 0x99, (byte) 0xAA, (byte) 0xBB, + (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, (byte) 0xFF + }; private final Paint defaultPaint; private final Paint fillRegionPaint; @@ -108,14 +105,16 @@ public DvbParser(int subtitlePageId, int ancillaryPageId) { fillRegionPaint.setPathEffect(null); canvas = new Canvas(); defaultDisplayDefinition = new DisplayDefinition(719, 575, 0, 719, 0, 575); - defaultClutDefinition = new ClutDefinition(0, generateDefault2BitClutEntries(), - generateDefault4BitClutEntries(), generateDefault8BitClutEntries()); + defaultClutDefinition = + new ClutDefinition( + 0, + generateDefault2BitClutEntries(), + generateDefault4BitClutEntries(), + generateDefault8BitClutEntries()); subtitleService = new SubtitleService(subtitlePageId, ancillaryPageId); } - /** - * Resets the parser. - */ + /** Resets the parser. */ public void reset() { subtitleService.reset(); } @@ -141,12 +140,16 @@ public List decode(byte[] data, int limit) { } // Update the canvas bitmap if necessary. - DisplayDefinition displayDefinition = subtitleService.displayDefinition != null - ? subtitleService.displayDefinition : defaultDisplayDefinition; - if (bitmap == null || displayDefinition.width + 1 != bitmap.getWidth() + DisplayDefinition displayDefinition = + subtitleService.displayDefinition != null + ? subtitleService.displayDefinition + : defaultDisplayDefinition; + if (bitmap == null + || displayDefinition.width + 1 != bitmap.getWidth() || displayDefinition.height + 1 != bitmap.getHeight()) { - bitmap = Bitmap.createBitmap(displayDefinition.width + 1, displayDefinition.height + 1, - Bitmap.Config.ARGB_8888); + bitmap = + Bitmap.createBitmap( + displayDefinition.width + 1, displayDefinition.height + 1, Bitmap.Config.ARGB_8888); canvas.setBitmap(bitmap); } @@ -161,10 +164,10 @@ public List decode(byte[] data, int limit) { RegionComposition regionComposition = subtitleService.regions.get(regionId); // Clip drawing to the current region and display definition window. - int baseHorizontalAddress = pageRegion.horizontalAddress - + displayDefinition.horizontalPositionMinimum; - int baseVerticalAddress = pageRegion.verticalAddress - + displayDefinition.verticalPositionMinimum; + int baseHorizontalAddress = + pageRegion.horizontalAddress + displayDefinition.horizontalPositionMinimum; + int baseVerticalAddress = + pageRegion.verticalAddress + displayDefinition.verticalPositionMinimum; int clipRight = min( baseHorizontalAddress + regionComposition.width, @@ -192,9 +195,14 @@ public List decode(byte[] data, int limit) { } if (objectData != null) { @Nullable Paint paint = objectData.nonModifyingColorFlag ? null : defaultPaint; - paintPixelDataSubBlocks(objectData, clutDefinition, regionComposition.depth, + paintPixelDataSubBlocks( + objectData, + clutDefinition, + regionComposition.depth, baseHorizontalAddress + regionObject.horizontalPosition, - baseVerticalAddress + regionObject.verticalPosition, paint, canvas); + baseVerticalAddress + regionObject.verticalPosition, + paint, + canvas); } } @@ -208,7 +216,9 @@ public List decode(byte[] data, int limit) { color = clutDefinition.clutEntries2Bit[regionComposition.pixelCode2Bit]; } fillRegionPaint.setColor(color); - canvas.drawRect(baseHorizontalAddress, baseVerticalAddress, + canvas.drawRect( + baseHorizontalAddress, + baseVerticalAddress, baseHorizontalAddress + regionComposition.width, baseVerticalAddress + regionComposition.height, fillRegionPaint); @@ -244,8 +254,8 @@ public List decode(byte[] data, int limit) { /** * Parses a subtitling segment, as defined by ETSI EN 300 743 7.2 - *

      - * The {@link SubtitleService} is updated with the parsed segment data. + * + *

      The {@link SubtitleService} is updated with the parsed segment data. */ private static void parseSubtitlingSegment(ParsableBitArray data, SubtitleService service) { int segmentType = data.readBits(8); @@ -321,9 +331,7 @@ private static void parseSubtitlingSegment(ParsableBitArray data, SubtitleServic data.skipBytes(dataFieldLimit - data.getBytePosition()); } - /** - * Parses a display definition segment, as defined by ETSI EN 300 743 7.2.1. - */ + /** Parses a display definition segment, as defined by ETSI EN 300 743 7.2.1. */ private static DisplayDefinition parseDisplayDefinition(ParsableBitArray data) { data.skipBits(4); // dds_version_number (4). boolean displayWindowFlag = data.readBit(); @@ -347,13 +355,16 @@ private static DisplayDefinition parseDisplayDefinition(ParsableBitArray data) { verticalPositionMaximum = height; } - return new DisplayDefinition(width, height, horizontalPositionMinimum, - horizontalPositionMaximum, verticalPositionMinimum, verticalPositionMaximum); + return new DisplayDefinition( + width, + height, + horizontalPositionMinimum, + horizontalPositionMaximum, + verticalPositionMinimum, + verticalPositionMaximum); } - /** - * Parses a page composition segment, as defined by ETSI EN 300 743 7.2.2. - */ + /** Parses a page composition segment, as defined by ETSI EN 300 743 7.2.2. */ private static PageComposition parsePageComposition(ParsableBitArray data, int length) { int timeoutSecs = data.readBits(8); int version = data.readBits(4); @@ -374,9 +385,7 @@ private static PageComposition parsePageComposition(ParsableBitArray data, int l return new PageComposition(timeoutSecs, version, state, regions); } - /** - * Parses a region composition segment, as defined by ETSI EN 300 743 7.2.3. - */ + /** Parses a region composition segment, as defined by ETSI EN 300 743 7.2.3. */ private static RegionComposition parseRegionComposition(ParsableBitArray data, int length) { int id = data.readBits(8); data.skipBits(4); // Skip region_version_number @@ -412,18 +421,32 @@ private static RegionComposition parseRegionComposition(ParsableBitArray data, i remainingLength -= 2; } - regionObjects.put(objectId, new RegionObject(objectType, objectProvider, - objectHorizontalPosition, objectVerticalPosition, foregroundPixelCode, - backgroundPixelCode)); + regionObjects.put( + objectId, + new RegionObject( + objectType, + objectProvider, + objectHorizontalPosition, + objectVerticalPosition, + foregroundPixelCode, + backgroundPixelCode)); } - return new RegionComposition(id, fillFlag, width, height, levelOfCompatibility, depth, clutId, - pixelCode8Bit, pixelCode4Bit, pixelCode2Bit, regionObjects); + return new RegionComposition( + id, + fillFlag, + width, + height, + levelOfCompatibility, + depth, + clutId, + pixelCode8Bit, + pixelCode4Bit, + pixelCode2Bit, + regionObjects); } - /** - * Parses a CLUT definition segment, as defined by ETSI EN 300 743 7.2.4. - */ + /** Parses a CLUT definition segment, as defined by ETSI EN 300 743 7.2.4. */ private static ClutDefinition parseClutDefinition(ParsableBitArray data, int length) { int clutId = data.readBits(8); data.skipBits(8); // Skip clut_version_number (4), reserved (4) @@ -475,8 +498,12 @@ private static ClutDefinition parseClutDefinition(ParsableBitArray data, int len int r = (int) (y + (1.40200 * (cr - 128))); int g = (int) (y - (0.34414 * (cb - 128)) - (0.71414 * (cr - 128))); int b = (int) (y + (1.77200 * (cb - 128))); - clutEntries[entryId] = getColor(a, Util.constrainValue(r, 0, 255), - Util.constrainValue(g, 0, 255), Util.constrainValue(b, 0, 255)); + clutEntries[entryId] = + getColor( + a, + Util.constrainValue(r, 0, 255), + Util.constrainValue(g, 0, 255), + Util.constrainValue(b, 0, 255)); } return new ClutDefinition(clutId, clutEntries2Bit, clutEntries4Bit, clutEntries8Bit); @@ -533,17 +560,19 @@ private static int[] generateDefault4BitClutEntries() { entries[0] = 0x00000000; for (int i = 1; i < entries.length; i++) { if (i < 8) { - entries[i] = getColor( - 0xFF, - ((i & 0x01) != 0 ? 0xFF : 0x00), - ((i & 0x02) != 0 ? 0xFF : 0x00), - ((i & 0x04) != 0 ? 0xFF : 0x00)); + entries[i] = + getColor( + 0xFF, + ((i & 0x01) != 0 ? 0xFF : 0x00), + ((i & 0x02) != 0 ? 0xFF : 0x00), + ((i & 0x04) != 0 ? 0xFF : 0x00)); } else { - entries[i] = getColor( - 0xFF, - ((i & 0x01) != 0 ? 0x7F : 0x00), - ((i & 0x02) != 0 ? 0x7F : 0x00), - ((i & 0x04) != 0 ? 0x7F : 0x00)); + entries[i] = + getColor( + 0xFF, + ((i & 0x01) != 0 ? 0x7F : 0x00), + ((i & 0x02) != 0 ? 0x7F : 0x00), + ((i & 0x04) != 0 ? 0x7F : 0x00)); } } return entries; @@ -554,40 +583,45 @@ private static int[] generateDefault8BitClutEntries() { entries[0] = 0x00000000; for (int i = 0; i < entries.length; i++) { if (i < 8) { - entries[i] = getColor( - 0x3F, - ((i & 0x01) != 0 ? 0xFF : 0x00), - ((i & 0x02) != 0 ? 0xFF : 0x00), - ((i & 0x04) != 0 ? 0xFF : 0x00)); + entries[i] = + getColor( + 0x3F, + ((i & 0x01) != 0 ? 0xFF : 0x00), + ((i & 0x02) != 0 ? 0xFF : 0x00), + ((i & 0x04) != 0 ? 0xFF : 0x00)); } else { switch (i & 0x88) { case 0x00: - entries[i] = getColor( - 0xFF, - (((i & 0x01) != 0 ? 0x55 : 0x00) + ((i & 0x10) != 0 ? 0xAA : 0x00)), - (((i & 0x02) != 0 ? 0x55 : 0x00) + ((i & 0x20) != 0 ? 0xAA : 0x00)), - (((i & 0x04) != 0 ? 0x55 : 0x00) + ((i & 0x40) != 0 ? 0xAA : 0x00))); + entries[i] = + getColor( + 0xFF, + (((i & 0x01) != 0 ? 0x55 : 0x00) + ((i & 0x10) != 0 ? 0xAA : 0x00)), + (((i & 0x02) != 0 ? 0x55 : 0x00) + ((i & 0x20) != 0 ? 0xAA : 0x00)), + (((i & 0x04) != 0 ? 0x55 : 0x00) + ((i & 0x40) != 0 ? 0xAA : 0x00))); break; case 0x08: - entries[i] = getColor( - 0x7F, - (((i & 0x01) != 0 ? 0x55 : 0x00) + ((i & 0x10) != 0 ? 0xAA : 0x00)), - (((i & 0x02) != 0 ? 0x55 : 0x00) + ((i & 0x20) != 0 ? 0xAA : 0x00)), - (((i & 0x04) != 0 ? 0x55 : 0x00) + ((i & 0x40) != 0 ? 0xAA : 0x00))); + entries[i] = + getColor( + 0x7F, + (((i & 0x01) != 0 ? 0x55 : 0x00) + ((i & 0x10) != 0 ? 0xAA : 0x00)), + (((i & 0x02) != 0 ? 0x55 : 0x00) + ((i & 0x20) != 0 ? 0xAA : 0x00)), + (((i & 0x04) != 0 ? 0x55 : 0x00) + ((i & 0x40) != 0 ? 0xAA : 0x00))); break; case 0x80: - entries[i] = getColor( - 0xFF, - (127 + ((i & 0x01) != 0 ? 0x2B : 0x00) + ((i & 0x10) != 0 ? 0x55 : 0x00)), - (127 + ((i & 0x02) != 0 ? 0x2B : 0x00) + ((i & 0x20) != 0 ? 0x55 : 0x00)), - (127 + ((i & 0x04) != 0 ? 0x2B : 0x00) + ((i & 0x40) != 0 ? 0x55 : 0x00))); + entries[i] = + getColor( + 0xFF, + (127 + ((i & 0x01) != 0 ? 0x2B : 0x00) + ((i & 0x10) != 0 ? 0x55 : 0x00)), + (127 + ((i & 0x02) != 0 ? 0x2B : 0x00) + ((i & 0x20) != 0 ? 0x55 : 0x00)), + (127 + ((i & 0x04) != 0 ? 0x2B : 0x00) + ((i & 0x40) != 0 ? 0x55 : 0x00))); break; case 0x88: - entries[i] = getColor( - 0xFF, - (((i & 0x01) != 0 ? 0x2B : 0x00) + ((i & 0x10) != 0 ? 0x55 : 0x00)), - (((i & 0x02) != 0 ? 0x2B : 0x00) + ((i & 0x20) != 0 ? 0x55 : 0x00)), - (((i & 0x04) != 0 ? 0x2B : 0x00) + ((i & 0x40) != 0 ? 0x55 : 0x00))); + entries[i] = + getColor( + 0xFF, + (((i & 0x01) != 0 ? 0x2B : 0x00) + ((i & 0x10) != 0 ? 0x55 : 0x00)), + (((i & 0x02) != 0 ? 0x2B : 0x00) + ((i & 0x20) != 0 ? 0x55 : 0x00)), + (((i & 0x04) != 0 ? 0x2B : 0x00) + ((i & 0x40) != 0 ? 0x55 : 0x00))); break; } } @@ -618,10 +652,22 @@ private static void paintPixelDataSubBlocks( } else { clutEntries = clutDefinition.clutEntries2Bit; } - paintPixelDataSubBlock(objectData.topFieldData, clutEntries, regionDepth, horizontalAddress, - verticalAddress, paint, canvas); - paintPixelDataSubBlock(objectData.bottomFieldData, clutEntries, regionDepth, horizontalAddress, - verticalAddress + 1, paint, canvas); + paintPixelDataSubBlock( + objectData.topFieldData, + clutEntries, + regionDepth, + horizontalAddress, + verticalAddress, + paint, + canvas); + paintPixelDataSubBlock( + objectData.bottomFieldData, + clutEntries, + regionDepth, + horizontalAddress, + verticalAddress + 1, + paint, + canvas); } /** Draws a pixel data sub-block, as defined by ETSI EN 300 743 7.2.5.1, into a canvas. */ @@ -652,8 +698,9 @@ private static void paintPixelDataSubBlock( } else { clutMapTable2ToX = null; } - column = paint2BitPixelCodeString(data, clutEntries, clutMapTable2ToX, column, line, - paint, canvas); + column = + paint2BitPixelCodeString( + data, clutEntries, clutMapTable2ToX, column, line, paint, canvas); data.byteAlign(); break; case DATA_TYPE_4BP_CODE_STRING: @@ -663,8 +710,9 @@ private static void paintPixelDataSubBlock( } else { clutMapTable4ToX = null; } - column = paint4BitPixelCodeString(data, clutEntries, clutMapTable4ToX, column, line, - paint, canvas); + column = + paint4BitPixelCodeString( + data, clutEntries, clutMapTable4ToX, column, line, paint, canvas); data.byteAlign(); break; case DATA_TYPE_8BP_CODE_STRING: @@ -854,9 +902,7 @@ private static byte[] buildClutMapTable(int length, int bitsPerEntry, ParsableBi // Private inner classes. - /** - * The subtitle service definition. - */ + /** The subtitle service definition. */ private static final class SubtitleService { public final int subtitlePageId; @@ -890,13 +936,12 @@ public void reset() { displayDefinition = null; pageComposition = null; } - } /** * Contains the geometry and active area of the subtitle service. - *

      - * See ETSI EN 300 743 7.2.1 + * + *

      See ETSI EN 300 743 7.2.1 */ private static final class DisplayDefinition { @@ -908,8 +953,13 @@ private static final class DisplayDefinition { public final int verticalPositionMinimum; public final int verticalPositionMaximum; - public DisplayDefinition(int width, int height, int horizontalPositionMinimum, - int horizontalPositionMaximum, int verticalPositionMinimum, int verticalPositionMaximum) { + public DisplayDefinition( + int width, + int height, + int horizontalPositionMinimum, + int horizontalPositionMaximum, + int verticalPositionMinimum, + int verticalPositionMaximum) { this.width = width; this.height = height; this.horizontalPositionMinimum = horizontalPositionMinimum; @@ -917,13 +967,12 @@ public DisplayDefinition(int width, int height, int horizontalPositionMinimum, this.verticalPositionMinimum = verticalPositionMinimum; this.verticalPositionMaximum = verticalPositionMaximum; } - } /** - * The page is the definition and arrangement of regions in the screen. - *

      - * See ETSI EN 300 743 7.2.2 + * The page is the definition and arrangement of regions in the screen. + * + *

      See ETSI EN 300 743 7.2.2 */ private static final class PageComposition { @@ -932,20 +981,19 @@ private static final class PageComposition { public final int state; public final SparseArray regions; - public PageComposition(int timeoutSecs, int version, int state, - SparseArray regions) { + public PageComposition( + int timeoutSecs, int version, int state, SparseArray regions) { this.timeOutSecs = timeoutSecs; this.version = version; this.state = state; this.regions = regions; } - } /** * A region within a {@link PageComposition}. - *

      - * See ETSI EN 300 743 7.2.2 + * + *

      See ETSI EN 300 743 7.2.2 */ private static final class PageRegion { @@ -956,13 +1004,12 @@ public PageRegion(int horizontalAddress, int verticalAddress) { this.horizontalAddress = horizontalAddress; this.verticalAddress = verticalAddress; } - } /** * An area of the page composed of a list of objects and a CLUT. - *

      - * See ETSI EN 300 743 7.2.3 + * + *

      See ETSI EN 300 743 7.2.3 */ private static final class RegionComposition { @@ -978,9 +1025,18 @@ private static final class RegionComposition { public final int pixelCode2Bit; public final SparseArray regionObjects; - public RegionComposition(int id, boolean fillFlag, int width, int height, - int levelOfCompatibility, int depth, int clutId, int pixelCode8Bit, int pixelCode4Bit, - int pixelCode2Bit, SparseArray regionObjects) { + public RegionComposition( + int id, + boolean fillFlag, + int width, + int height, + int levelOfCompatibility, + int depth, + int clutId, + int pixelCode8Bit, + int pixelCode4Bit, + int pixelCode2Bit, + SparseArray regionObjects) { this.id = id; this.fillFlag = fillFlag; this.width = width; @@ -1000,13 +1056,12 @@ public void mergeFrom(RegionComposition otherRegionComposition) { regionObjects.put(otherRegionObjects.keyAt(i), otherRegionObjects.valueAt(i)); } } - } /** * An object within a {@link RegionComposition}. - *

      - * See ETSI EN 300 743 7.2.3 + * + *

      See ETSI EN 300 743 7.2.3 */ private static final class RegionObject { @@ -1017,8 +1072,13 @@ private static final class RegionObject { public final int foregroundPixelCode; // TODO: Use this or remove it. public final int backgroundPixelCode; // TODO: Use this or remove it. - public RegionObject(int type, int provider, int horizontalPosition, - int verticalPosition, int foregroundPixelCode, int backgroundPixelCode) { + public RegionObject( + int type, + int provider, + int horizontalPosition, + int verticalPosition, + int foregroundPixelCode, + int backgroundPixelCode) { this.type = type; this.provider = provider; this.horizontalPosition = horizontalPosition; @@ -1026,13 +1086,12 @@ public RegionObject(int type, int provider, int horizontalPosition, this.foregroundPixelCode = foregroundPixelCode; this.backgroundPixelCode = backgroundPixelCode; } - } /** * CLUT family definition containing the color tables for the three bit depths defined - *

      - * See ETSI EN 300 743 7.2.4 + * + *

      See ETSI EN 300 743 7.2.4 */ private static final class ClutDefinition { @@ -1041,20 +1100,19 @@ private static final class ClutDefinition { public final int[] clutEntries4Bit; public final int[] clutEntries8Bit; - public ClutDefinition(int id, int[] clutEntries2Bit, int[] clutEntries4Bit, - int[] clutEntries8bit) { + public ClutDefinition( + int id, int[] clutEntries2Bit, int[] clutEntries4Bit, int[] clutEntries8bit) { this.id = id; this.clutEntries2Bit = clutEntries2Bit; this.clutEntries4Bit = clutEntries4Bit; this.clutEntries8Bit = clutEntries8bit; } - } /** * The textual or graphical representation of an object. - *

      - * See ETSI EN 300 743 7.2.5 + * + *

      See ETSI EN 300 743 7.2.5 */ private static final class ObjectData { @@ -1063,14 +1121,12 @@ private static final class ObjectData { public final byte[] topFieldData; public final byte[] bottomFieldData; - public ObjectData(int id, boolean nonModifyingColorFlag, byte[] topFieldData, - byte[] bottomFieldData) { + public ObjectData( + int id, boolean nonModifyingColorFlag, byte[] topFieldData, byte[] bottomFieldData) { this.id = id; this.nonModifyingColorFlag = nonModifyingColorFlag; this.topFieldData = topFieldData; this.bottomFieldData = bottomFieldData; } - } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/dvb/DvbSubtitle.java b/library/core/src/main/java/com/google/android/exoplayer2/text/dvb/DvbSubtitle.java index 75728359c7f..de9cf453695 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/dvb/DvbSubtitle.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/dvb/DvbSubtitle.java @@ -20,9 +20,7 @@ import com.google.android.exoplayer2.text.Subtitle; import java.util.List; -/** - * A representation of a DVB subtitle. - */ +/** A representation of a DVB subtitle. */ /* package */ final class DvbSubtitle implements Subtitle { private final List cues; @@ -50,5 +48,4 @@ public long getEventTime(int index) { public List getCues(long timeUs) { return cues; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/ssa/SsaStyle.java b/library/core/src/main/java/com/google/android/exoplayer2/text/ssa/SsaStyle.java index 3ae6bd133d2..cf1ae43a36f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/ssa/SsaStyle.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/ssa/SsaStyle.java @@ -142,17 +142,13 @@ public static SsaStyle fromStyleLine(String styleLine, Format format) { ? parseFontSize(styleValues[format.fontSizeIndex].trim()) : Cue.DIMEN_UNSET, format.boldIndex != C.INDEX_UNSET - ? parseBooleanValue(styleValues[format.boldIndex].trim()) - : false, + && parseBooleanValue(styleValues[format.boldIndex].trim()), format.italicIndex != C.INDEX_UNSET - ? parseBooleanValue(styleValues[format.italicIndex].trim()) - : false, + && parseBooleanValue(styleValues[format.italicIndex].trim()), format.underlineIndex != C.INDEX_UNSET - ? parseBooleanValue(styleValues[format.underlineIndex].trim()) - : false, + && parseBooleanValue(styleValues[format.underlineIndex].trim()), format.strikeoutIndex != C.INDEX_UNSET - ? parseBooleanValue(styleValues[format.strikeoutIndex].trim()) - : false); + && parseBooleanValue(styleValues[format.strikeoutIndex].trim())); } catch (RuntimeException e) { Log.w(TAG, "Skipping malformed 'Style:' line: '" + styleLine + "'", e); return null; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/ssa/SsaSubtitle.java b/library/core/src/main/java/com/google/android/exoplayer2/text/ssa/SsaSubtitle.java index 4093f7974dd..79da60c34e8 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/ssa/SsaSubtitle.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/ssa/SsaSubtitle.java @@ -23,9 +23,7 @@ import java.util.Collections; import java.util.List; -/** - * A representation of an SSA/ASS subtitle. - */ +/** A representation of an SSA/ASS subtitle. */ /* package */ final class SsaSubtitle implements Subtitle { private final List> cues; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/subrip/SubripSubtitle.java b/library/core/src/main/java/com/google/android/exoplayer2/text/subrip/SubripSubtitle.java index 01ed1711a9e..631a6384087 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/subrip/SubripSubtitle.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/subrip/SubripSubtitle.java @@ -23,9 +23,7 @@ import java.util.Collections; import java.util.List; -/** - * A representation of a SubRip subtitle. - */ +/** A representation of a SubRip subtitle. */ /* package */ final class SubripSubtitle implements Subtitle { private final Cue[] cues; @@ -68,5 +66,4 @@ public List getCues(long timeUs) { return Collections.singletonList(cues[index]); } } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlDecoder.java b/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlDecoder.java index 1d84b7a6b31..6a57e149700 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlDecoder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlDecoder.java @@ -80,8 +80,9 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder { private static final String ATTR_IMAGE = "backgroundImage"; private static final Pattern CLOCK_TIME = - Pattern.compile("^([0-9][0-9]+):([0-9][0-9]):([0-9][0-9])" - + "(?:(\\.[0-9]+)|:([0-9][0-9])(?:\\.([0-9]+))?)?$"); + Pattern.compile( + "^([0-9][0-9]+):([0-9][0-9]):([0-9][0-9])" + + "(?:(\\.[0-9]+)|:([0-9][0-9])(?:\\.([0-9]+))?)?$"); private static final Pattern OFFSET_TIME = Pattern.compile("^([0-9]+(?:\\.[0-9]+)?)(h|m|s|ms|f|t)$"); private static final Pattern FONT_SIZE = Pattern.compile("^(([0-9]*.)?[0-9]+)(px|em|%)$"); @@ -526,12 +527,10 @@ private static String[] parseStyleIds(String parentStyleIds) { } break; case TtmlNode.ATTR_TTS_FONT_WEIGHT: - style = createIfNull(style).setBold( - TtmlNode.BOLD.equalsIgnoreCase(attributeValue)); + style = createIfNull(style).setBold(TtmlNode.BOLD.equalsIgnoreCase(attributeValue)); break; case TtmlNode.ATTR_TTS_FONT_STYLE: - style = createIfNull(style).setItalic( - TtmlNode.ITALIC.equalsIgnoreCase(attributeValue)); + style = createIfNull(style).setItalic(TtmlNode.ITALIC.equalsIgnoreCase(attributeValue)); break; case TtmlNode.ATTR_TTS_TEXT_ALIGN: style = createIfNull(style).setTextAlign(parseAlignment(attributeValue)); @@ -729,19 +728,21 @@ private static boolean isSupportedTag(String tag) { || tag.equals(TtmlNode.TAG_INFORMATION); } - private static void parseFontSize(String expression, TtmlStyle out) throws - SubtitleDecoderException { + private static void parseFontSize(String expression, TtmlStyle out) + throws SubtitleDecoderException { String[] expressions = Util.split(expression, "\\s+"); Matcher matcher; if (expressions.length == 1) { matcher = FONT_SIZE.matcher(expression); - } else if (expressions.length == 2){ + } else if (expressions.length == 2) { matcher = FONT_SIZE.matcher(expressions[1]); - Log.w(TAG, "Multiple values in fontSize attribute. Picking the second value for vertical font" - + " size and ignoring the first."); + Log.w( + TAG, + "Multiple values in fontSize attribute. Picking the second value for vertical font" + + " size and ignoring the first."); } else { - throw new SubtitleDecoderException("Invalid number of entries for fontSize: " - + expressions.length + "."); + throw new SubtitleDecoderException( + "Invalid number of entries for fontSize: " + expressions.length + "."); } if (matcher.matches()) { @@ -814,13 +815,15 @@ private static long parseTimeExpression(String time, FrameAndTickRate frameAndTi @Nullable String fraction = matcher.group(4); durationSeconds += (fraction != null) ? Double.parseDouble(fraction) : 0; @Nullable String frames = matcher.group(5); - durationSeconds += (frames != null) - ? Long.parseLong(frames) / frameAndTickRate.effectiveFrameRate : 0; + durationSeconds += + (frames != null) ? Long.parseLong(frames) / frameAndTickRate.effectiveFrameRate : 0; @Nullable String subframes = matcher.group(6); - durationSeconds += (subframes != null) - ? ((double) Long.parseLong(subframes)) / frameAndTickRate.subFrameRate - / frameAndTickRate.effectiveFrameRate - : 0; + durationSeconds += + (subframes != null) + ? ((double) Long.parseLong(subframes)) + / frameAndTickRate.subFrameRate + / frameAndTickRate.effectiveFrameRate + : 0; return (long) (durationSeconds * C.MICROS_PER_SECOND); } matcher = OFFSET_TIME.matcher(time); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlNode.java b/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlNode.java index 7e39d1e9f81..0677ef1e277 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlNode.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlNode.java @@ -32,9 +32,7 @@ import java.util.TreeSet; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; -/** - * A package internal representation of TTML node. - */ +/** A package internal representation of TTML node. */ /* package */ final class TtmlNode { public static final String TAG_TT = "tt"; @@ -342,8 +340,8 @@ private void traverseForText( boolean isPNode = TAG_P.equals(tag); for (int i = 0; i < getChildCount(); i++) { - getChild(i).traverseForText(timeUs, descendsPNode || isPNode, resolvedRegionId, - regionOutputs); + getChild(i) + .traverseForText(timeUs, descendsPNode || isPNode, resolvedRegionId, regionOutputs); } if (isPNode) { TtmlRenderUtil.endParagraph(getRegionOutputText(resolvedRegionId, regionOutputs)); @@ -473,5 +471,4 @@ private static void cleanUpText(SpannableStringBuilder builder) { builder.delete(builder.length() - 1, builder.length()); } } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlRegion.java b/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlRegion.java index 36c862568f3..593bfd7761a 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlRegion.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlRegion.java @@ -17,9 +17,7 @@ import com.google.android.exoplayer2.text.Cue; -/** - * Represents a TTML Region. - */ +/** Represents a TTML Region. */ /* package */ final class TtmlRegion { public final String id; @@ -69,5 +67,4 @@ public TtmlRegion( this.textSize = textSize; this.verticalType = verticalType; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlRenderUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlRenderUtil.java index e578a04072d..8d2724622e0 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlRenderUtil.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlRenderUtil.java @@ -41,9 +41,7 @@ import java.util.Deque; import java.util.Map; -/** - * Package internal utility class to render styled TtmlNodes. - */ +/** Package internal utility class to render styled TtmlNodes. */ /* package */ final class TtmlRenderUtil { private static final String TAG = "TtmlRenderUtil"; @@ -92,8 +90,8 @@ public static void applyStylesToSpan( @Cue.VerticalType int verticalType) { if (style.getStyle() != TtmlStyle.UNSPECIFIED) { - builder.setSpan(new StyleSpan(style.getStyle()), start, end, - Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + builder.setSpan( + new StyleSpan(style.getStyle()), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } if (style.isLinethrough()) { builder.setSpan(new StrikethroughSpan(), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); @@ -180,12 +178,22 @@ public static void applyStylesToSpan( break; } - // TODO: Get rubyPosition from `textNode` when TTML inheritance is implemented. + @Nullable + TtmlStyle textStyle = resolveStyle(textNode.style, textNode.getStyleIds(), globalStyles); + + // Use position from ruby text node if defined. @TextAnnotation.Position int rubyPosition = - containerNode.style != null - ? containerNode.style.getRubyPosition() - : TextAnnotation.POSITION_UNKNOWN; + textStyle != null ? textStyle.getRubyPosition() : TextAnnotation.POSITION_UNKNOWN; + + if (rubyPosition == TextAnnotation.POSITION_UNKNOWN) { + // If ruby position is not defined, use position info from container node. + @Nullable + TtmlStyle containerStyle = + resolveStyle(containerNode.style, containerNode.getStyleIds(), globalStyles); + rubyPosition = containerStyle != null ? containerStyle.getRubyPosition() : rubyPosition; + } + builder.setSpan( new RubySpan(rubyText, rubyPosition), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); break; @@ -313,5 +321,4 @@ private static TtmlNode findRubyContainerNode( } private TtmlRenderUtil() {} - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlStyle.java b/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlStyle.java index d1c7291652e..82ce86df2a9 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlStyle.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlStyle.java @@ -24,9 +24,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -/** - * Style object of a TtmlNode - */ +/** Style object of a TtmlNode */ /* package */ final class TtmlStyle { public static final int UNSPECIFIED = -1; @@ -109,12 +107,12 @@ public TtmlStyle() { * @return {@link #UNSPECIFIED}, {@link #STYLE_NORMAL}, {@link #STYLE_BOLD}, {@link #STYLE_BOLD} * or {@link #STYLE_BOLD_ITALIC}. */ - @StyleFlags public int getStyle() { + @StyleFlags + public int getStyle() { if (bold == UNSPECIFIED && italic == UNSPECIFIED) { return UNSPECIFIED; } - return (bold == ON ? STYLE_BOLD : STYLE_NORMAL) - | (italic == ON ? STYLE_ITALIC : STYLE_NORMAL); + return (bold == ON ? STYLE_BOLD : STYLE_NORMAL) | (italic == ON ? STYLE_ITALIC : STYLE_NORMAL); } public boolean isLinethrough() { @@ -352,7 +350,8 @@ public TtmlStyle setFontSizeUnit(int fontSizeUnit) { return this; } - @FontSizeUnit public int getFontSizeUnit() { + @FontSizeUnit + public int getFontSizeUnit() { return fontSizeUnit; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlSubtitle.java b/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlSubtitle.java index 6a52338a945..68c11a9a252 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlSubtitle.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlSubtitle.java @@ -24,9 +24,7 @@ import java.util.List; import java.util.Map; -/** - * A representation of a TTML subtitle. - */ +/** A representation of a TTML subtitle. */ /* package */ final class TtmlSubtitle implements Subtitle { private final TtmlNode root; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/tx3g/Tx3gDecoder.java b/library/core/src/main/java/com/google/android/exoplayer2/text/tx3g/Tx3gDecoder.java index ea08c375ef7..4b8f539f42f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/tx3g/Tx3gDecoder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/tx3g/Tx3gDecoder.java @@ -92,19 +92,20 @@ public Tx3gDecoder(List initializationData) { && (initializationData.get(0).length == 48 || initializationData.get(0).length == 53)) { byte[] initializationBytes = initializationData.get(0); defaultFontFace = initializationBytes[24]; - defaultColorRgba = ((initializationBytes[26] & 0xFF) << 24) - | ((initializationBytes[27] & 0xFF) << 16) - | ((initializationBytes[28] & 0xFF) << 8) - | (initializationBytes[29] & 0xFF); + defaultColorRgba = + ((initializationBytes[26] & 0xFF) << 24) + | ((initializationBytes[27] & 0xFF) << 16) + | ((initializationBytes[28] & 0xFF) << 8) + | (initializationBytes[29] & 0xFF); String fontFamily = Util.fromUtf8Bytes(initializationBytes, 43, initializationBytes.length - 43); defaultFontFamily = TX3G_SERIF.equals(fontFamily) ? C.SERIF_NAME : C.SANS_SERIF_NAME; - //font size (initializationBytes[25]) is 5% of video height + // font size (initializationBytes[25]) is 5% of video height calculatedVideoTrackHeight = 20 * initializationBytes[25]; customVerticalPlacement = (initializationBytes[0] & 0x20) != 0; if (customVerticalPlacement) { - int requestedVerticalPlacement = ((initializationBytes[10] & 0xFF) << 8) - | (initializationBytes[11] & 0xFF); + int requestedVerticalPlacement = + ((initializationBytes[10] & 0xFF) << 8) | (initializationBytes[11] & 0xFF); defaultVerticalPlacement = Util.constrainValue( (float) requestedVerticalPlacement / calculatedVideoTrackHeight, 0.0f, 0.95f); @@ -131,10 +132,9 @@ protected Subtitle decode(byte[] bytes, int length, boolean reset) } // Attach default styles. SpannableStringBuilder cueText = new SpannableStringBuilder(cueTextString); - attachFontFace(cueText, defaultFontFace, DEFAULT_FONT_FACE, 0, cueText.length(), - SPAN_PRIORITY_LOW); - attachColor(cueText, defaultColorRgba, DEFAULT_COLOR, 0, cueText.length(), - SPAN_PRIORITY_LOW); + attachFontFace( + cueText, defaultFontFace, DEFAULT_FONT_FACE, 0, cueText.length(), SPAN_PRIORITY_LOW); + attachColor(cueText, defaultColorRgba, DEFAULT_COLOR, 0, cueText.length(), SPAN_PRIORITY_LOW); attachFontFamily(cueText, defaultFontFamily, 0, cueText.length()); float verticalPlacement = defaultVerticalPlacement; // Find and attach additional styles. @@ -180,8 +180,8 @@ private static String readSubtitleText(ParsableByteArray parsableByteArray) return parsableByteArray.readString(textLength, Charsets.UTF_8); } - private void applyStyleRecord(ParsableByteArray parsableByteArray, - SpannableStringBuilder cueText) throws SubtitleDecoderException { + private void applyStyleRecord(ParsableByteArray parsableByteArray, SpannableStringBuilder cueText) + throws SubtitleDecoderException { assertTrue(parsableByteArray.bytesLeft() >= SIZE_STYLE_RECORD); int start = parsableByteArray.readUnsignedShort(); int end = parsableByteArray.readUnsignedShort(); @@ -203,8 +203,13 @@ private void applyStyleRecord(ParsableByteArray parsableByteArray, attachColor(cueText, colorRgba, defaultColorRgba, start, end, SPAN_PRIORITY_HIGH); } - private static void attachFontFace(SpannableStringBuilder cueText, int fontFace, - int defaultFontFace, int start, int end, int spanPriority) { + private static void attachFontFace( + SpannableStringBuilder cueText, + int fontFace, + int defaultFontFace, + int start, + int end, + int spanPriority) { if (fontFace != defaultFontFace) { final int flags = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | spanPriority; boolean isBold = (fontFace & FONT_FACE_BOLD) != 0; @@ -228,11 +233,19 @@ private static void attachFontFace(SpannableStringBuilder cueText, int fontFace, } } - private static void attachColor(SpannableStringBuilder cueText, int colorRgba, - int defaultColorRgba, int start, int end, int spanPriority) { + private static void attachColor( + SpannableStringBuilder cueText, + int colorRgba, + int defaultColorRgba, + int start, + int end, + int spanPriority) { if (colorRgba != defaultColorRgba) { int colorArgb = ((colorRgba & 0xFF) << 24) | (colorRgba >>> 8); - cueText.setSpan(new ForegroundColorSpan(colorArgb), start, end, + cueText.setSpan( + new ForegroundColorSpan(colorArgb), + start, + end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | spanPriority); } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/tx3g/Tx3gSubtitle.java b/library/core/src/main/java/com/google/android/exoplayer2/text/tx3g/Tx3gSubtitle.java index adb1190ce4a..100e0800564 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/tx3g/Tx3gSubtitle.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/tx3g/Tx3gSubtitle.java @@ -22,9 +22,7 @@ import java.util.Collections; import java.util.List; -/** - * A representation of a tx3g subtitle. - */ +/** A representation of a tx3g subtitle. */ /* package */ final class Tx3gSubtitle implements Subtitle { public static final Tx3gSubtitle EMPTY = new Tx3gSubtitle(); @@ -59,5 +57,4 @@ public long getEventTime(int index) { public List getCues(long timeUs) { return timeUs >= 0 ? cues : Collections.emptyList(); } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/Mp4WebvttSubtitle.java b/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/Mp4WebvttSubtitle.java index c87c88133c0..00c8ecdc482 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/Mp4WebvttSubtitle.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/Mp4WebvttSubtitle.java @@ -22,9 +22,7 @@ import java.util.Collections; import java.util.List; -/** - * Representation of a Webvtt subtitle embedded in a MP4 container file. - */ +/** Representation of a Webvtt subtitle embedded in a MP4 container file. */ /* package */ final class Mp4WebvttSubtitle implements Subtitle { private final List cues; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/CssParser.java b/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCssParser.java similarity index 86% rename from library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/CssParser.java rename to library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCssParser.java index 0bd13129426..6fd236e98f5 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/CssParser.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCssParser.java @@ -20,8 +20,10 @@ import com.google.android.exoplayer2.text.span.TextAnnotation; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.ColorParser; +import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.Util; +import com.google.common.base.Ascii; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; @@ -31,9 +33,9 @@ * Provides a CSS parser for STYLE blocks in Webvtt files. Supports only a subset of the CSS * features. */ -/* package */ final class CssParser { +/* package */ final class WebvttCssParser { - private static final String TAG = "CssParser"; + private static final String TAG = "WebvttCssParser"; private static final String RULE_START = "{"; private static final String RULE_END = "}"; @@ -41,6 +43,7 @@ private static final String PROPERTY_BGCOLOR = "background-color"; private static final String PROPERTY_FONT_FAMILY = "font-family"; private static final String PROPERTY_FONT_WEIGHT = "font-weight"; + private static final String PROPERTY_FONT_SIZE = "font-size"; private static final String PROPERTY_RUBY_POSITION = "ruby-position"; private static final String VALUE_OVER = "over"; private static final String VALUE_UNDER = "under"; @@ -54,12 +57,14 @@ private static final String VALUE_ITALIC = "italic"; private static final Pattern VOICE_NAME_PATTERN = Pattern.compile("\\[voice=\"([^\"]*)\"\\]"); + private static final Pattern FONT_SIZE_PATTERN = + Pattern.compile("^((?:[0-9]*\\.)?[0-9]+)(px|em|%)$"); // Temporary utility data structures. private final ParsableByteArray styleInput; private final StringBuilder stringBuilder; - public CssParser() { + public WebvttCssParser() { styleInput = new ParsableByteArray(); stringBuilder = new StringBuilder(); } @@ -146,9 +151,7 @@ private static String parseSelector(ParsableByteArray input, StringBuilder strin return target; } - /** - * Reads the contents of ::cue() and returns it as a string. - */ + /** Reads the contents of ::cue() and returns it as a string. */ private static String readCueTarget(ParsableByteArray input) { int position = input.getPosition(); int limit = input.limit(); @@ -161,8 +164,8 @@ private static String readCueTarget(ParsableByteArray input) { // --offset to return ')' to the input. } - private static void parseStyleDeclaration(ParsableByteArray input, WebvttCssStyle style, - StringBuilder stringBuilder) { + private static void parseStyleDeclaration( + ParsableByteArray input, WebvttCssStyle style, StringBuilder stringBuilder) { skipWhitespaceAndComments(input); String property = parseIdentifier(input, stringBuilder); if ("".equals(property)) { @@ -215,6 +218,8 @@ private static void parseStyleDeclaration(ParsableByteArray input, WebvttCssStyl if (VALUE_ITALIC.equals(value)) { style.setItalic(true); } + } else if (PROPERTY_FONT_SIZE.equals(property)) { + parseFontSize(value, style); } // TODO: Fill remaining supported styles. } @@ -243,7 +248,7 @@ private static void parseStyleDeclaration(ParsableByteArray input, WebvttCssStyl } private static boolean maybeSkipWhitespace(ParsableByteArray input) { - switch(peekCharAtPosition(input, input.getPosition())) { + switch (peekCharAtPosition(input, input.getPosition())) { case '\t': case '\r': case '\n': @@ -319,10 +324,15 @@ private static String parseIdentifier(ParsableByteArray input, StringBuilder str int position = input.getPosition(); int limit = input.limit(); boolean identifierEndFound = false; - while (position < limit && !identifierEndFound) { + while (position < limit && !identifierEndFound) { char c = (char) input.getData()[position]; - if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '#' - || c == '-' || c == '.' || c == '_') { + if ((c >= 'A' && c <= 'Z') + || (c >= 'a' && c <= 'z') + || (c >= '0' && c <= '9') + || c == '#' + || c == '-' + || c == '.' + || c == '_') { position++; stringBuilder.append(c); } else { @@ -333,6 +343,31 @@ private static String parseIdentifier(ParsableByteArray input, StringBuilder str return stringBuilder.toString(); } + private static void parseFontSize(String fontSize, WebvttCssStyle style) { + Matcher matcher = FONT_SIZE_PATTERN.matcher(Ascii.toLowerCase(fontSize)); + if (!matcher.matches()) { + Log.w(TAG, "Invalid font-size: '" + fontSize + "'."); + return; + } + String unit = Assertions.checkNotNull(matcher.group(2)); + switch (unit) { + case "px": + style.setFontSizeUnit(WebvttCssStyle.FONT_SIZE_UNIT_PIXEL); + break; + case "em": + style.setFontSizeUnit(WebvttCssStyle.FONT_SIZE_UNIT_EM); + break; + case "%": + style.setFontSizeUnit(WebvttCssStyle.FONT_SIZE_UNIT_PERCENT); + break; + default: + // this line should never be reached because when the fontSize matches the FONT_SIZE_PATTERN + // unit must be one of: px, em, % + throw new IllegalStateException(); + } + style.setFontSize(Float.parseFloat(Assertions.checkNotNull(matcher.group(1)))); + } + /** * Sets the target of a {@link WebvttCssStyle} by splitting a selector of the form {@code * ::cue(tag#id.class1.class2[voice="someone"]}, where every element is optional. @@ -362,5 +397,4 @@ private void applySelectorToStyle(WebvttCssStyle style, String selector) { style.setTargetClasses(Util.nullSafeArrayCopyOfRange(classDivision, 1, classDivision.length)); } } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCssStyle.java b/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCssStyle.java index b8f9e9b343f..587f7d5ab54 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCssStyle.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCssStyle.java @@ -116,7 +116,7 @@ public WebvttCssStyle() { } public void setTargetId(String targetId) { - this.targetId = targetId; + this.targetId = targetId; } public void setTargetTagName(String targetTag) { @@ -134,24 +134,27 @@ public void setTargetVoice(String targetVoice) { /** * Returns a value in a score system compliant with the CSS Specificity rules. * - * @see CSS Cascading - *

      The score works as follows: - *

        - *
      • Id match adds 0x40000000 to the score. - *
      • Each class and voice match adds 4 to the score. - *
      • Tag matching adds 2 to the score. - *
      • Universal selector matching scores 1. - *
      + *

      The score works as follows: + * + *

        + *
      • Id match adds 0x40000000 to the score. + *
      • Each class and voice match adds 4 to the score. + *
      • Tag matching adds 2 to the score. + *
      • Universal selector matching scores 1. + *
      * * @param id The id of the cue if present, {@code null} otherwise. * @param tag Name of the tag, {@code null} if it refers to the entire cue. * @param classes An array containing the classes the tag belongs to. Must not be null. * @param voice Annotated voice if present, {@code null} otherwise. * @return The score of the match, zero if there is no match. + * @see CSS Cascading */ public int getSpecificityScore( @Nullable String id, @Nullable String tag, Set classes, @Nullable String voice) { - if (targetId.isEmpty() && targetTag.isEmpty() && targetClasses.isEmpty() + if (targetId.isEmpty() + && targetTag.isEmpty() + && targetClasses.isEmpty() && targetVoice.isEmpty()) { // The selector is universal. It matches with the minimum score if and only if the given // element is a whole cue. @@ -175,12 +178,12 @@ public int getSpecificityScore( * @return {@link #UNSPECIFIED}, {@link #STYLE_NORMAL}, {@link #STYLE_BOLD}, {@link #STYLE_BOLD} * or {@link #STYLE_BOLD_ITALIC}. */ - @StyleFlags public int getStyle() { + @StyleFlags + public int getStyle() { if (bold == UNSPECIFIED && italic == UNSPECIFIED) { return UNSPECIFIED; } - return (bold == ON ? STYLE_BOLD : STYLE_NORMAL) - | (italic == ON ? STYLE_ITALIC : STYLE_NORMAL); + return (bold == ON ? STYLE_BOLD : STYLE_NORMAL) | (italic == ON ? STYLE_ITALIC : STYLE_NORMAL); } public boolean isLinethrough() { @@ -200,6 +203,7 @@ public WebvttCssStyle setUnderline(boolean underline) { this.underline = underline ? ON : OFF; return this; } + public WebvttCssStyle setBold(boolean bold) { this.bold = bold ? ON : OFF; return this; @@ -259,12 +263,13 @@ public WebvttCssStyle setFontSize(float fontSize) { return this; } - public WebvttCssStyle setFontSizeUnit(short unit) { + public WebvttCssStyle setFontSizeUnit(@FontSizeUnit int unit) { this.fontSizeUnit = unit; return this; } - @FontSizeUnit public int getFontSizeUnit() { + @FontSizeUnit + public int getFontSizeUnit() { return fontSizeUnit; } @@ -298,5 +303,4 @@ private static int updateScoreForMatch( } return target.equals(actual) ? currentScore + score : -1; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCueParser.java b/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCueParser.java index a040a3acf3e..63cfc8b8dd3 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCueParser.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCueParser.java @@ -111,8 +111,8 @@ public final class WebvttCueParser { */ private static final int TEXT_ALIGNMENT_RIGHT = 5; - public static final Pattern CUE_HEADER_PATTERN = Pattern - .compile("^(\\S+)\\s+-->\\s+(\\S+)(.*)?$"); + public static final Pattern CUE_HEADER_PATTERN = + Pattern.compile("^(\\S+)\\s+-->\\s+(\\S+)(.*)?$"); private static final Pattern CUE_SETTING_PATTERN = Pattern.compile("(\\S+?):(\\S+)"); private static final char CHAR_LESS_THAN = '<'; @@ -257,8 +257,8 @@ public static WebvttCueInfo parseCue(ParsableByteArray webvttData, List cueInfos; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelection.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelection.java index 6dc3b2f6368..95df027ac27 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelection.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelection.java @@ -421,8 +421,10 @@ public int evaluateQueueSize(long playbackPositionUs, List Util.getPlayoutDurationForMediaDuration(mediaDurationBeforeThisChunkUs, playbackSpeed); if (playoutDurationBeforeThisChunkUs >= minDurationToRetainAfterDiscardUs && format.bitrate < idealFormat.bitrate - && format.height != Format.NO_VALUE && format.height < 720 - && format.width != Format.NO_VALUE && format.width < 1280 + && format.height != Format.NO_VALUE + && format.height < 720 + && format.width != Format.NO_VALUE + && format.width < 1280 && format.height < idealFormat.height) { return i; } @@ -493,8 +495,9 @@ private int determineIdealSelectedIndex(long nowMs, long chunkDurationUs) { } private long minDurationForQualityIncreaseUs(long availableDurationUs) { - boolean isAvailableDurationTooShort = availableDurationUs != C.TIME_UNSET - && availableDurationUs <= minDurationForQualityIncreaseUs; + boolean isAvailableDurationTooShort = + availableDurationUs != C.TIME_UNSET + && availableDurationUs <= minDurationForQualityIncreaseUs; return isAvailableDurationTooShort ? (long) (availableDurationUs * bufferedFractionToLiveEdgeForQualityIncrease) : minDurationForQualityIncreaseUs; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java index 19b1b03e595..91c4a79d3a2 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java @@ -51,16 +51,14 @@ import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; -import org.checkerframework.checker.initialization.qual.UnderInitialization; import org.checkerframework.checker.nullness.compatqual.NullableType; -import org.checkerframework.checker.nullness.qual.EnsuresNonNull; /** * A default {@link TrackSelector} suitable for most use cases. Track selections are made according * to configurable {@link Parameters}, which can be set by calling {@link * #setParameters(Parameters)}. * - *

      Modifying parameters

      + *

      Modifying parameters

      * * To modify only some aspects of the parameters currently used by a selector, it's possible to * obtain a {@link ParametersBuilder} initialized with the current {@link Parameters}. The desired @@ -93,7 +91,7 @@ * * Selection {@link Parameters} support many different options, some of which are described below. * - *

      Selecting specific tracks

      + *

      Selecting specific tracks

      * * Track selection overrides can be used to select specific tracks. To specify an override for a * renderer, it's first necessary to obtain the tracks that have been mapped to it: @@ -120,7 +118,7 @@ * .setSelectionOverride(rendererIndex, rendererTrackGroups, selectionOverride)); * } * - *

      Constraint based track selection

      + *

      Constraint based track selection

      * * Whilst track selection overrides make it possible to select specific tracks, the recommended way * of controlling which tracks are selected is by specifying constraints. For example consider the @@ -148,14 +146,14 @@ * only applied to periods whose tracks match those for which the override was set. *
    * - *

    Disabling renderers

    + *

    Disabling renderers

    * * Renderers can be disabled using {@link ParametersBuilder#setRendererDisabled}. Disabling a * renderer differs from setting a {@code null} override because the renderer is disabled * unconditionally, whereas a {@code null} override is applied only when the track groups available * to the renderer match the {@link TrackGroupArray} for which it was specified. * - *

    Tunneling

    + *

    Tunneling

    * * Tunneled playback can be enabled in cases where the combination of renderers and selected tracks * support it. Tunneled playback is enabled by passing an audio session ID to {@link @@ -170,32 +168,17 @@ public class DefaultTrackSelector extends MappingTrackSelector { public static final class ParametersBuilder extends TrackSelectionParameters.Builder { // Video - private int maxVideoWidth; - private int maxVideoHeight; - private int maxVideoFrameRate; - private int maxVideoBitrate; - private int minVideoWidth; - private int minVideoHeight; - private int minVideoFrameRate; - private int minVideoBitrate; private boolean exceedVideoConstraintsIfNecessary; private boolean allowVideoMixedMimeTypeAdaptiveness; private boolean allowVideoNonSeamlessAdaptiveness; - private int viewportWidth; - private int viewportHeight; - private boolean viewportOrientationMayChange; - private ImmutableList preferredVideoMimeTypes; // Audio - private int maxAudioChannelCount; - private int maxAudioBitrate; private boolean exceedAudioConstraintsIfNecessary; private boolean allowAudioMixedMimeTypeAdaptiveness; private boolean allowAudioMixedSampleRateAdaptiveness; private boolean allowAudioMixedChannelCountAdaptiveness; - private ImmutableList preferredAudioMimeTypes; + // Text + @C.SelectionFlags private int disabledTextTrackSelectionFlags; // General - private boolean forceLowestBitrate; - private boolean forceHighestSupportedBitrate; private boolean exceedRendererCapabilitiesIfNecessary; private boolean tunnelingEnabled; private boolean allowMultipleAdaptiveSelections; @@ -212,9 +195,9 @@ public static final class ParametersBuilder extends TrackSelectionParameters.Bui @SuppressWarnings({"deprecation"}) public ParametersBuilder() { super(); - setInitialValuesWithoutContext(); selectionOverrides = new SparseArray<>(); rendererDisabledFlags = new SparseBooleanArray(); + init(); } /** @@ -224,10 +207,9 @@ public ParametersBuilder() { */ public ParametersBuilder(Context context) { super(context); - setInitialValuesWithoutContext(); selectionOverrides = new SparseArray<>(); rendererDisabledFlags = new SparseBooleanArray(); - setViewportSizeToPhysicalDisplaySize(context, /* viewportOrientationMayChange= */ true); + init(); } /** @@ -236,34 +218,19 @@ public ParametersBuilder(Context context) { */ private ParametersBuilder(Parameters initialValues) { super(initialValues); + // Text + disabledTextTrackSelectionFlags = initialValues.disabledTextTrackSelectionFlags; // Video - maxVideoWidth = initialValues.maxVideoWidth; - maxVideoHeight = initialValues.maxVideoHeight; - maxVideoFrameRate = initialValues.maxVideoFrameRate; - maxVideoBitrate = initialValues.maxVideoBitrate; - minVideoWidth = initialValues.minVideoWidth; - minVideoHeight = initialValues.minVideoHeight; - minVideoFrameRate = initialValues.minVideoFrameRate; - minVideoBitrate = initialValues.minVideoBitrate; exceedVideoConstraintsIfNecessary = initialValues.exceedVideoConstraintsIfNecessary; allowVideoMixedMimeTypeAdaptiveness = initialValues.allowVideoMixedMimeTypeAdaptiveness; allowVideoNonSeamlessAdaptiveness = initialValues.allowVideoNonSeamlessAdaptiveness; - viewportWidth = initialValues.viewportWidth; - viewportHeight = initialValues.viewportHeight; - viewportOrientationMayChange = initialValues.viewportOrientationMayChange; - preferredVideoMimeTypes = initialValues.preferredVideoMimeTypes; // Audio - maxAudioChannelCount = initialValues.maxAudioChannelCount; - maxAudioBitrate = initialValues.maxAudioBitrate; exceedAudioConstraintsIfNecessary = initialValues.exceedAudioConstraintsIfNecessary; allowAudioMixedMimeTypeAdaptiveness = initialValues.allowAudioMixedMimeTypeAdaptiveness; allowAudioMixedSampleRateAdaptiveness = initialValues.allowAudioMixedSampleRateAdaptiveness; allowAudioMixedChannelCountAdaptiveness = initialValues.allowAudioMixedChannelCountAdaptiveness; - preferredAudioMimeTypes = initialValues.preferredAudioMimeTypes; // General - forceLowestBitrate = initialValues.forceLowestBitrate; - forceHighestSupportedBitrate = initialValues.forceHighestSupportedBitrate; exceedRendererCapabilitiesIfNecessary = initialValues.exceedRendererCapabilitiesIfNecessary; tunnelingEnabled = initialValues.tunnelingEnabled; allowMultipleAdaptiveSelections = initialValues.allowMultipleAdaptiveSelections; @@ -274,91 +241,53 @@ private ParametersBuilder(Parameters initialValues) { // Video - /** - * Equivalent to {@link #setMaxVideoSize setMaxVideoSize(1279, 719)}. - * - * @return This builder. - */ - public ParametersBuilder setMaxVideoSizeSd() { - return setMaxVideoSize(1279, 719); + @Override + public DefaultTrackSelector.ParametersBuilder setMaxVideoSizeSd() { + super.setMaxVideoSizeSd(); + return this; } - /** - * Equivalent to {@link #setMaxVideoSize setMaxVideoSize(Integer.MAX_VALUE, Integer.MAX_VALUE)}. - * - * @return This builder. - */ - public ParametersBuilder clearVideoSizeConstraints() { - return setMaxVideoSize(Integer.MAX_VALUE, Integer.MAX_VALUE); + @Override + public DefaultTrackSelector.ParametersBuilder clearVideoSizeConstraints() { + super.clearVideoSizeConstraints(); + return this; } - /** - * Sets the maximum allowed video width and height. - * - * @param maxVideoWidth Maximum allowed video width in pixels. - * @param maxVideoHeight Maximum allowed video height in pixels. - * @return This builder. - */ - public ParametersBuilder setMaxVideoSize(int maxVideoWidth, int maxVideoHeight) { - this.maxVideoWidth = maxVideoWidth; - this.maxVideoHeight = maxVideoHeight; + @Override + public DefaultTrackSelector.ParametersBuilder setMaxVideoSize( + int maxVideoWidth, int maxVideoHeight) { + super.setMaxVideoSize(maxVideoWidth, maxVideoHeight); return this; } - /** - * Sets the maximum allowed video frame rate. - * - * @param maxVideoFrameRate Maximum allowed video frame rate in hertz. - * @return This builder. - */ - public ParametersBuilder setMaxVideoFrameRate(int maxVideoFrameRate) { - this.maxVideoFrameRate = maxVideoFrameRate; + @Override + public DefaultTrackSelector.ParametersBuilder setMaxVideoFrameRate(int maxVideoFrameRate) { + super.setMaxVideoFrameRate(maxVideoFrameRate); return this; } - /** - * Sets the maximum allowed video bitrate. - * - * @param maxVideoBitrate Maximum allowed video bitrate in bits per second. - * @return This builder. - */ - public ParametersBuilder setMaxVideoBitrate(int maxVideoBitrate) { - this.maxVideoBitrate = maxVideoBitrate; + @Override + public DefaultTrackSelector.ParametersBuilder setMaxVideoBitrate(int maxVideoBitrate) { + super.setMaxVideoBitrate(maxVideoBitrate); return this; } - /** - * Sets the minimum allowed video width and height. - * - * @param minVideoWidth Minimum allowed video width in pixels. - * @param minVideoHeight Minimum allowed video height in pixels. - * @return This builder. - */ - public ParametersBuilder setMinVideoSize(int minVideoWidth, int minVideoHeight) { - this.minVideoWidth = minVideoWidth; - this.minVideoHeight = minVideoHeight; + @Override + public DefaultTrackSelector.ParametersBuilder setMinVideoSize( + int minVideoWidth, int minVideoHeight) { + super.setMinVideoSize(minVideoWidth, minVideoHeight); return this; } - /** - * Sets the minimum allowed video frame rate. - * - * @param minVideoFrameRate Minimum allowed video frame rate in hertz. - * @return This builder. - */ - public ParametersBuilder setMinVideoFrameRate(int minVideoFrameRate) { - this.minVideoFrameRate = minVideoFrameRate; + @Override + public DefaultTrackSelector.ParametersBuilder setMinVideoFrameRate(int minVideoFrameRate) { + super.setMinVideoFrameRate(minVideoFrameRate); return this; } - /** - * Sets the minimum allowed video bitrate. - * - * @param minVideoBitrate Minimum allowed video bitrate in bits per second. - * @return This builder. - */ - public ParametersBuilder setMinVideoBitrate(int minVideoBitrate) { - this.minVideoBitrate = minVideoBitrate; + @Override + public DefaultTrackSelector.ParametersBuilder setMinVideoBitrate(int minVideoBitrate) { + super.setMinVideoBitrate(minVideoBitrate); return this; } @@ -407,70 +336,35 @@ public ParametersBuilder setAllowVideoNonSeamlessAdaptiveness( return this; } - /** - * Equivalent to calling {@link #setViewportSize(int, int, boolean)} with the viewport size - * obtained from {@link Util#getCurrentDisplayModeSize(Context)}. - * - * @param context Any context. - * @param viewportOrientationMayChange Whether the viewport orientation may change during - * playback. - * @return This builder. - */ + @Override public ParametersBuilder setViewportSizeToPhysicalDisplaySize( Context context, boolean viewportOrientationMayChange) { - // Assume the viewport is fullscreen. - Point viewportSize = Util.getCurrentDisplayModeSize(context); - return setViewportSize(viewportSize.x, viewportSize.y, viewportOrientationMayChange); + super.setViewportSizeToPhysicalDisplaySize(context, viewportOrientationMayChange); + return this; } - /** - * Equivalent to {@link #setViewportSize setViewportSize(Integer.MAX_VALUE, Integer.MAX_VALUE, - * true)}. - * - * @return This builder. - */ + @Override public ParametersBuilder clearViewportSizeConstraints() { - return setViewportSize(Integer.MAX_VALUE, Integer.MAX_VALUE, true); + super.clearViewportSizeConstraints(); + return this; } - /** - * Sets the viewport size to constrain adaptive video selections so that only tracks suitable - * for the viewport are selected. - * - * @param viewportWidth Viewport width in pixels. - * @param viewportHeight Viewport height in pixels. - * @param viewportOrientationMayChange Whether the viewport orientation may change during - * playback. - * @return This builder. - */ + @Override public ParametersBuilder setViewportSize( int viewportWidth, int viewportHeight, boolean viewportOrientationMayChange) { - this.viewportWidth = viewportWidth; - this.viewportHeight = viewportHeight; - this.viewportOrientationMayChange = viewportOrientationMayChange; + super.setViewportSize(viewportWidth, viewportHeight, viewportOrientationMayChange); return this; } - /** - * Sets the preferred sample MIME type for video tracks. - * - * @param mimeType The preferred MIME type for video tracks, or {@code null} to clear a - * previously set preference. - * @return This builder. - */ + @Override public ParametersBuilder setPreferredVideoMimeType(@Nullable String mimeType) { - return mimeType == null ? setPreferredVideoMimeTypes() : setPreferredVideoMimeTypes(mimeType); + super.setPreferredVideoMimeType(mimeType); + return this; } - /** - * Sets the preferred sample MIME types for video tracks. - * - * @param mimeTypes The preferred MIME types for video tracks in order of preference, or an - * empty list for no preference. - * @return This builder. - */ + @Override public ParametersBuilder setPreferredVideoMimeTypes(String... mimeTypes) { - preferredVideoMimeTypes = ImmutableList.copyOf(mimeTypes); + super.setPreferredVideoMimeTypes(mimeTypes); return this; } @@ -494,25 +388,15 @@ public ParametersBuilder setPreferredAudioRoleFlags(@C.RoleFlags int preferredAu return this; } - /** - * Sets the maximum allowed audio channel count. - * - * @param maxAudioChannelCount Maximum allowed audio channel count. - * @return This builder. - */ + @Override public ParametersBuilder setMaxAudioChannelCount(int maxAudioChannelCount) { - this.maxAudioChannelCount = maxAudioChannelCount; + super.setMaxAudioChannelCount(maxAudioChannelCount); return this; } - /** - * Sets the maximum allowed audio bitrate. - * - * @param maxAudioBitrate Maximum allowed audio bitrate in bits per second. - * @return This builder. - */ + @Override public ParametersBuilder setMaxAudioBitrate(int maxAudioBitrate) { - this.maxAudioBitrate = maxAudioBitrate; + super.setMaxAudioBitrate(maxAudioBitrate); return this; } @@ -575,26 +459,15 @@ public ParametersBuilder setAllowAudioMixedChannelCountAdaptiveness( return this; } - /** - * Sets the preferred sample MIME type for audio tracks. - * - * @param mimeType The preferred MIME type for audio tracks, or {@code null} to clear a - * previously set preference. - * @return This builder. - */ + @Override public ParametersBuilder setPreferredAudioMimeType(@Nullable String mimeType) { - return mimeType == null ? setPreferredAudioMimeTypes() : setPreferredAudioMimeTypes(mimeType); + super.setPreferredAudioMimeType(mimeType); + return this; } - /** - * Sets the preferred sample MIME types for audio tracks. - * - * @param mimeTypes The preferred MIME types for audio tracks in order of preference, or an - * empty list for no preference. - * @return This builder. - */ + @Override public ParametersBuilder setPreferredAudioMimeTypes(String... mimeTypes) { - preferredAudioMimeTypes = ImmutableList.copyOf(mimeTypes); + super.setPreferredAudioMimeTypes(mimeTypes); return this; } @@ -632,38 +505,30 @@ public ParametersBuilder setSelectUndeterminedTextLanguage( return this; } - @Override + /** + * Sets a bitmask of selection flags that are disabled for text track selections. + * + * @param disabledTextTrackSelectionFlags A bitmask of {@link C.SelectionFlags} that are + * disabled for text track selections. + * @return This builder. + */ public ParametersBuilder setDisabledTextTrackSelectionFlags( @C.SelectionFlags int disabledTextTrackSelectionFlags) { - super.setDisabledTextTrackSelectionFlags(disabledTextTrackSelectionFlags); + this.disabledTextTrackSelectionFlags = disabledTextTrackSelectionFlags; return this; } // General - /** - * Sets whether to force selection of the single lowest bitrate audio and video tracks that - * comply with all other constraints. - * - * @param forceLowestBitrate Whether to force selection of the single lowest bitrate audio and - * video tracks. - * @return This builder. - */ + @Override public ParametersBuilder setForceLowestBitrate(boolean forceLowestBitrate) { - this.forceLowestBitrate = forceLowestBitrate; + super.setForceLowestBitrate(forceLowestBitrate); return this; } - /** - * Sets whether to force selection of the highest bitrate audio and video tracks that comply - * with all other constraints. - * - * @param forceHighestSupportedBitrate Whether to force selection of the highest bitrate audio - * and video tracks. - * @return This builder. - */ + @Override public ParametersBuilder setForceHighestSupportedBitrate(boolean forceHighestSupportedBitrate) { - this.forceHighestSupportedBitrate = forceHighestSupportedBitrate; + super.setForceHighestSupportedBitrate(forceHighestSupportedBitrate); return this; } @@ -826,74 +691,24 @@ public final ParametersBuilder clearSelectionOverrides() { } /** Builds a {@link Parameters} instance with the selected values. */ + @Override public Parameters build() { - return new Parameters( - // Video - maxVideoWidth, - maxVideoHeight, - maxVideoFrameRate, - maxVideoBitrate, - minVideoWidth, - minVideoHeight, - minVideoFrameRate, - minVideoBitrate, - exceedVideoConstraintsIfNecessary, - allowVideoMixedMimeTypeAdaptiveness, - allowVideoNonSeamlessAdaptiveness, - viewportWidth, - viewportHeight, - viewportOrientationMayChange, - preferredVideoMimeTypes, - // Audio - preferredAudioLanguages, - preferredAudioRoleFlags, - maxAudioChannelCount, - maxAudioBitrate, - exceedAudioConstraintsIfNecessary, - allowAudioMixedMimeTypeAdaptiveness, - allowAudioMixedSampleRateAdaptiveness, - allowAudioMixedChannelCountAdaptiveness, - preferredAudioMimeTypes, - // Text - preferredTextLanguages, - preferredTextRoleFlags, - selectUndeterminedTextLanguage, - disabledTextTrackSelectionFlags, - // General - forceLowestBitrate, - forceHighestSupportedBitrate, - exceedRendererCapabilitiesIfNecessary, - tunnelingEnabled, - allowMultipleAdaptiveSelections, - selectionOverrides, - rendererDisabledFlags); + return new Parameters(this); } - @EnsuresNonNull({"preferredVideoMimeTypes", "preferredAudioMimeTypes"}) - private void setInitialValuesWithoutContext(@UnderInitialization ParametersBuilder this) { + private void init(ParametersBuilder this) { // Video - maxVideoWidth = Integer.MAX_VALUE; - maxVideoHeight = Integer.MAX_VALUE; - maxVideoFrameRate = Integer.MAX_VALUE; - maxVideoBitrate = Integer.MAX_VALUE; exceedVideoConstraintsIfNecessary = true; allowVideoMixedMimeTypeAdaptiveness = false; allowVideoNonSeamlessAdaptiveness = true; - viewportWidth = Integer.MAX_VALUE; - viewportHeight = Integer.MAX_VALUE; - viewportOrientationMayChange = true; - preferredVideoMimeTypes = ImmutableList.of(); // Audio - maxAudioChannelCount = Integer.MAX_VALUE; - maxAudioBitrate = Integer.MAX_VALUE; exceedAudioConstraintsIfNecessary = true; allowAudioMixedMimeTypeAdaptiveness = false; allowAudioMixedSampleRateAdaptiveness = false; allowAudioMixedChannelCountAdaptiveness = false; - preferredAudioMimeTypes = ImmutableList.of(); + // Text + disabledTextTrackSelectionFlags = 0; // General - forceLowestBitrate = false; - forceHighestSupportedBitrate = false; exceedRendererCapabilitiesIfNecessary = true; tunnelingEnabled = false; allowMultipleAdaptiveSelections = true; @@ -912,10 +727,9 @@ private void setInitialValuesWithoutContext(@UnderInitialization ParametersBuild } /** - * Extends {@link TrackSelectionParameters} by adding fields that are specific to {@link - * DefaultTrackSelector}. + * Extends {@link Parameters} by adding fields that are specific to {@link DefaultTrackSelector}. */ - public static final class Parameters extends TrackSelectionParameters { + public static final class Parameters extends TrackSelectionParameters implements Parcelable { /** * An instance with default values, except those obtained from the {@link Context}. @@ -935,6 +749,30 @@ public static final class Parameters extends TrackSelectionParameters { */ @SuppressWarnings("deprecation") public static final Parameters DEFAULT_WITHOUT_CONTEXT = new ParametersBuilder().build(); + /** + * @deprecated This instance is not configured using {@link Context} constraints. Use {@link + * #getDefaults(Context)} instead. + */ + @Deprecated public static final Parameters DEFAULT = DEFAULT_WITHOUT_CONTEXT; + + public static final Creator CREATOR = + new Creator() { + + @Override + public Parameters createFromParcel(Parcel in) { + return new Parameters(in); + } + + @Override + public Parameters[] newArray(int size) { + return new Parameters[size]; + } + }; + /** + * Bitmask of selection flags that are disabled for text track selections. See {@link + * C.SelectionFlags}. The default value is {@code 0} (i.e. no flags). + */ + @C.SelectionFlags public final int disabledTextTrackSelectionFlags; /** Returns an instance configured with default values. */ public static Parameters getDefaults(Context context) { @@ -942,45 +780,6 @@ public static Parameters getDefaults(Context context) { } // Video - /** - * Maximum allowed video width in pixels. The default value is {@link Integer#MAX_VALUE} (i.e. - * no constraint). - * - *

    To constrain adaptive video track selections to be suitable for a given viewport (the - * region of the display within which video will be played), use ({@link #viewportWidth}, {@link - * #viewportHeight} and {@link #viewportOrientationMayChange}) instead. - */ - public final int maxVideoWidth; - /** - * Maximum allowed video height in pixels. The default value is {@link Integer#MAX_VALUE} (i.e. - * no constraint). - * - *

    To constrain adaptive video track selections to be suitable for a given viewport (the - * region of the display within which video will be played), use ({@link #viewportWidth}, {@link - * #viewportHeight} and {@link #viewportOrientationMayChange}) instead. - */ - public final int maxVideoHeight; - /** - * Maximum allowed video frame rate in hertz. The default value is {@link Integer#MAX_VALUE} - * (i.e. no constraint). - */ - public final int maxVideoFrameRate; - /** - * Maximum allowed video bitrate in bits per second. The default value is {@link - * Integer#MAX_VALUE} (i.e. no constraint). - */ - public final int maxVideoBitrate; - /** Minimum allowed video width in pixels. The default value is 0 (i.e. no constraint). */ - public final int minVideoWidth; - /** Minimum allowed video height in pixels. The default value is 0 (i.e. no constraint). */ - public final int minVideoHeight; - /** Minimum allowed video frame rate in hertz. The default value is 0 (i.e. no constraint). */ - public final int minVideoFrameRate; - /** - * Minimum allowed video bitrate in bits per second. The default value is 0 (i.e. no - * constraint). - */ - public final int minVideoBitrate; /** * Whether to exceed the {@link #maxVideoWidth}, {@link #maxVideoHeight} and {@link * #maxVideoBitrate} constraints when no selection can be made otherwise. The default value is @@ -999,40 +798,6 @@ public static Parameters getDefaults(Context context) { * The default value is {@code true}. */ public final boolean allowVideoNonSeamlessAdaptiveness; - /** - * Viewport width in pixels. Constrains video track selections for adaptive content so that only - * tracks suitable for the viewport are selected. The default value is the physical width of the - * primary display, in pixels. - */ - public final int viewportWidth; - /** - * Viewport height in pixels. Constrains video track selections for adaptive content so that - * only tracks suitable for the viewport are selected. The default value is the physical height - * of the primary display, in pixels. - */ - public final int viewportHeight; - /** - * Whether the viewport orientation may change during playback. Constrains video track - * selections for adaptive content so that only tracks suitable for the viewport are selected. - * The default value is {@code true}. - */ - public final boolean viewportOrientationMayChange; - /** - * The preferred sample MIME types for video tracks in order of preference, or an empty list for - * no preference. The default is an empty list. - */ - public final ImmutableList preferredVideoMimeTypes; - // Audio - /** - * Maximum allowed audio channel count. The default value is {@link Integer#MAX_VALUE} (i.e. no - * constraint). - */ - public final int maxAudioChannelCount; - /** - * Maximum allowed audio bitrate in bits per second. The default value is {@link - * Integer#MAX_VALUE} (i.e. no constraint). - */ - public final int maxAudioBitrate; /** * Whether to exceed the {@link #maxAudioChannelCount} and {@link #maxAudioBitrate} constraints * when no selection can be made otherwise. The default value is {@code true}. @@ -1054,22 +819,6 @@ public static Parameters getDefaults(Context context) { * false}. */ public final boolean allowAudioMixedChannelCountAdaptiveness; - /** - * The preferred sample MIME types for audio tracks in order of preference, or an empty list for - * no preference. The default is an empty list. - */ - public final ImmutableList preferredAudioMimeTypes; - // General - /** - * Whether to force selection of the single lowest bitrate audio and video tracks that comply - * with all other constraints. The default value is {@code false}. - */ - public final boolean forceLowestBitrate; - /** - * Whether to force selection of the highest bitrate audio and video tracks that comply with all - * other constraints. The default value is {@code false}. - */ - public final boolean forceHighestSupportedBitrate; /** * Whether to exceed renderer capabilities when no selection can be made otherwise. * @@ -1097,122 +846,42 @@ public static Parameters getDefaults(Context context) { selectionOverrides; private final SparseBooleanArray rendererDisabledFlags; - /* package */ Parameters( - // Video - int maxVideoWidth, - int maxVideoHeight, - int maxVideoFrameRate, - int maxVideoBitrate, - int minVideoWidth, - int minVideoHeight, - int minVideoFrameRate, - int minVideoBitrate, - boolean exceedVideoConstraintsIfNecessary, - boolean allowVideoMixedMimeTypeAdaptiveness, - boolean allowVideoNonSeamlessAdaptiveness, - int viewportWidth, - int viewportHeight, - boolean viewportOrientationMayChange, - ImmutableList preferredVideoMimeTypes, - // Audio - ImmutableList preferredAudioLanguages, - @C.RoleFlags int preferredAudioRoleFlags, - int maxAudioChannelCount, - int maxAudioBitrate, - boolean exceedAudioConstraintsIfNecessary, - boolean allowAudioMixedMimeTypeAdaptiveness, - boolean allowAudioMixedSampleRateAdaptiveness, - boolean allowAudioMixedChannelCountAdaptiveness, - ImmutableList preferredAudioMimeTypes, - // Text - ImmutableList preferredTextLanguages, - @C.RoleFlags int preferredTextRoleFlags, - boolean selectUndeterminedTextLanguage, - @C.SelectionFlags int disabledTextTrackSelectionFlags, - // General - boolean forceLowestBitrate, - boolean forceHighestSupportedBitrate, - boolean exceedRendererCapabilitiesIfNecessary, - boolean tunnelingEnabled, - boolean allowMultipleAdaptiveSelections, - // Overrides - SparseArray> selectionOverrides, - SparseBooleanArray rendererDisabledFlags) { - super( - preferredAudioLanguages, - preferredAudioRoleFlags, - preferredTextLanguages, - preferredTextRoleFlags, - selectUndeterminedTextLanguage, - disabledTextTrackSelectionFlags); + private Parameters(ParametersBuilder builder) { + super(builder); // Video - this.maxVideoWidth = maxVideoWidth; - this.maxVideoHeight = maxVideoHeight; - this.maxVideoFrameRate = maxVideoFrameRate; - this.maxVideoBitrate = maxVideoBitrate; - this.minVideoWidth = minVideoWidth; - this.minVideoHeight = minVideoHeight; - this.minVideoFrameRate = minVideoFrameRate; - this.minVideoBitrate = minVideoBitrate; - this.exceedVideoConstraintsIfNecessary = exceedVideoConstraintsIfNecessary; - this.allowVideoMixedMimeTypeAdaptiveness = allowVideoMixedMimeTypeAdaptiveness; - this.allowVideoNonSeamlessAdaptiveness = allowVideoNonSeamlessAdaptiveness; - this.viewportWidth = viewportWidth; - this.viewportHeight = viewportHeight; - this.viewportOrientationMayChange = viewportOrientationMayChange; - this.preferredVideoMimeTypes = preferredVideoMimeTypes; + exceedVideoConstraintsIfNecessary = builder.exceedVideoConstraintsIfNecessary; + allowVideoMixedMimeTypeAdaptiveness = builder.allowVideoMixedMimeTypeAdaptiveness; + allowVideoNonSeamlessAdaptiveness = builder.allowVideoNonSeamlessAdaptiveness; // Audio - this.maxAudioChannelCount = maxAudioChannelCount; - this.maxAudioBitrate = maxAudioBitrate; - this.exceedAudioConstraintsIfNecessary = exceedAudioConstraintsIfNecessary; - this.allowAudioMixedMimeTypeAdaptiveness = allowAudioMixedMimeTypeAdaptiveness; - this.allowAudioMixedSampleRateAdaptiveness = allowAudioMixedSampleRateAdaptiveness; - this.allowAudioMixedChannelCountAdaptiveness = allowAudioMixedChannelCountAdaptiveness; - this.preferredAudioMimeTypes = preferredAudioMimeTypes; + exceedAudioConstraintsIfNecessary = builder.exceedAudioConstraintsIfNecessary; + allowAudioMixedMimeTypeAdaptiveness = builder.allowAudioMixedMimeTypeAdaptiveness; + allowAudioMixedSampleRateAdaptiveness = builder.allowAudioMixedSampleRateAdaptiveness; + allowAudioMixedChannelCountAdaptiveness = builder.allowAudioMixedChannelCountAdaptiveness; + // Text + disabledTextTrackSelectionFlags = builder.disabledTextTrackSelectionFlags; // General - this.forceLowestBitrate = forceLowestBitrate; - this.forceHighestSupportedBitrate = forceHighestSupportedBitrate; - this.exceedRendererCapabilitiesIfNecessary = exceedRendererCapabilitiesIfNecessary; - this.tunnelingEnabled = tunnelingEnabled; - this.allowMultipleAdaptiveSelections = allowMultipleAdaptiveSelections; + exceedRendererCapabilitiesIfNecessary = builder.exceedRendererCapabilitiesIfNecessary; + tunnelingEnabled = builder.tunnelingEnabled; + allowMultipleAdaptiveSelections = builder.allowMultipleAdaptiveSelections; // Overrides - this.selectionOverrides = selectionOverrides; - this.rendererDisabledFlags = rendererDisabledFlags; + selectionOverrides = builder.selectionOverrides; + rendererDisabledFlags = builder.rendererDisabledFlags; } /* package */ Parameters(Parcel in) { super(in); // Video - this.maxVideoWidth = in.readInt(); - this.maxVideoHeight = in.readInt(); - this.maxVideoFrameRate = in.readInt(); - this.maxVideoBitrate = in.readInt(); - this.minVideoWidth = in.readInt(); - this.minVideoHeight = in.readInt(); - this.minVideoFrameRate = in.readInt(); - this.minVideoBitrate = in.readInt(); this.exceedVideoConstraintsIfNecessary = Util.readBoolean(in); this.allowVideoMixedMimeTypeAdaptiveness = Util.readBoolean(in); this.allowVideoNonSeamlessAdaptiveness = Util.readBoolean(in); - this.viewportWidth = in.readInt(); - this.viewportHeight = in.readInt(); - this.viewportOrientationMayChange = Util.readBoolean(in); - ArrayList preferredVideoMimeTypes = new ArrayList<>(); - in.readList(preferredVideoMimeTypes, /* loader= */ null); - this.preferredVideoMimeTypes = ImmutableList.copyOf(preferredVideoMimeTypes); // Audio - this.maxAudioChannelCount = in.readInt(); - this.maxAudioBitrate = in.readInt(); this.exceedAudioConstraintsIfNecessary = Util.readBoolean(in); this.allowAudioMixedMimeTypeAdaptiveness = Util.readBoolean(in); this.allowAudioMixedSampleRateAdaptiveness = Util.readBoolean(in); this.allowAudioMixedChannelCountAdaptiveness = Util.readBoolean(in); - ArrayList preferredAudioMimeTypes = new ArrayList<>(); - in.readList(preferredAudioMimeTypes, /* loader= */ null); - this.preferredAudioMimeTypes = ImmutableList.copyOf(preferredAudioMimeTypes); + // Text + this.disabledTextTrackSelectionFlags = in.readInt(); // General - this.forceLowestBitrate = Util.readBoolean(in); - this.forceHighestSupportedBitrate = Util.readBoolean(in); this.exceedRendererCapabilitiesIfNecessary = Util.readBoolean(in); this.tunnelingEnabled = Util.readBoolean(in); this.allowMultipleAdaptiveSelections = Util.readBoolean(in); @@ -1259,11 +928,11 @@ public final SelectionOverride getSelectionOverride(int rendererIndex, TrackGrou } /** Creates a new {@link ParametersBuilder}, copying the initial values from this instance. */ - @Override public ParametersBuilder buildUpon() { return new ParametersBuilder(this); } + @SuppressWarnings("EqualsGetClass") // Class is not final for backward-compatibility reason. @Override public boolean equals(@Nullable Object obj) { if (this == obj) { @@ -1273,35 +942,20 @@ public boolean equals(@Nullable Object obj) { return false; } Parameters other = (Parameters) obj; - return super.equals(obj) + return super.equals(other) // Video - && maxVideoWidth == other.maxVideoWidth - && maxVideoHeight == other.maxVideoHeight - && maxVideoFrameRate == other.maxVideoFrameRate - && maxVideoBitrate == other.maxVideoBitrate - && minVideoWidth == other.minVideoWidth - && minVideoHeight == other.minVideoHeight - && minVideoFrameRate == other.minVideoFrameRate - && minVideoBitrate == other.minVideoBitrate && exceedVideoConstraintsIfNecessary == other.exceedVideoConstraintsIfNecessary && allowVideoMixedMimeTypeAdaptiveness == other.allowVideoMixedMimeTypeAdaptiveness && allowVideoNonSeamlessAdaptiveness == other.allowVideoNonSeamlessAdaptiveness - && viewportOrientationMayChange == other.viewportOrientationMayChange - && viewportWidth == other.viewportWidth - && viewportHeight == other.viewportHeight - && preferredVideoMimeTypes.equals(other.preferredVideoMimeTypes) // Audio - && maxAudioChannelCount == other.maxAudioChannelCount - && maxAudioBitrate == other.maxAudioBitrate && exceedAudioConstraintsIfNecessary == other.exceedAudioConstraintsIfNecessary && allowAudioMixedMimeTypeAdaptiveness == other.allowAudioMixedMimeTypeAdaptiveness && allowAudioMixedSampleRateAdaptiveness == other.allowAudioMixedSampleRateAdaptiveness && allowAudioMixedChannelCountAdaptiveness == other.allowAudioMixedChannelCountAdaptiveness - && preferredAudioMimeTypes.equals(other.preferredAudioMimeTypes) + // Text + && disabledTextTrackSelectionFlags == other.disabledTextTrackSelectionFlags // General - && forceLowestBitrate == other.forceLowestBitrate - && forceHighestSupportedBitrate == other.forceHighestSupportedBitrate && exceedRendererCapabilitiesIfNecessary == other.exceedRendererCapabilitiesIfNecessary && tunnelingEnabled == other.tunnelingEnabled && allowMultipleAdaptiveSelections == other.allowMultipleAdaptiveSelections @@ -1312,34 +966,20 @@ && areRendererDisabledFlagsEqual(rendererDisabledFlags, other.rendererDisabledFl @Override public int hashCode() { - int result = super.hashCode(); + int result = 1; + result = 31 * result + super.hashCode(); // Video - result = 31 * result + maxVideoWidth; - result = 31 * result + maxVideoHeight; - result = 31 * result + maxVideoFrameRate; - result = 31 * result + maxVideoBitrate; - result = 31 * result + minVideoWidth; - result = 31 * result + minVideoHeight; - result = 31 * result + minVideoFrameRate; - result = 31 * result + minVideoBitrate; result = 31 * result + (exceedVideoConstraintsIfNecessary ? 1 : 0); result = 31 * result + (allowVideoMixedMimeTypeAdaptiveness ? 1 : 0); result = 31 * result + (allowVideoNonSeamlessAdaptiveness ? 1 : 0); - result = 31 * result + (viewportOrientationMayChange ? 1 : 0); - result = 31 * result + viewportWidth; - result = 31 * result + viewportHeight; - result = 31 * result + preferredVideoMimeTypes.hashCode(); // Audio - result = 31 * result + maxAudioChannelCount; - result = 31 * result + maxAudioBitrate; result = 31 * result + (exceedAudioConstraintsIfNecessary ? 1 : 0); result = 31 * result + (allowAudioMixedMimeTypeAdaptiveness ? 1 : 0); result = 31 * result + (allowAudioMixedSampleRateAdaptiveness ? 1 : 0); result = 31 * result + (allowAudioMixedChannelCountAdaptiveness ? 1 : 0); - result = 31 * result + preferredAudioMimeTypes.hashCode(); + // Text + result = 31 * result + disabledTextTrackSelectionFlags; // General - result = 31 * result + (forceLowestBitrate ? 1 : 0); - result = 31 * result + (forceHighestSupportedBitrate ? 1 : 0); result = 31 * result + (exceedRendererCapabilitiesIfNecessary ? 1 : 0); result = 31 * result + (tunnelingEnabled ? 1 : 0); result = 31 * result + (allowMultipleAdaptiveSelections ? 1 : 0); @@ -1358,32 +998,17 @@ public int describeContents() { public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); // Video - dest.writeInt(maxVideoWidth); - dest.writeInt(maxVideoHeight); - dest.writeInt(maxVideoFrameRate); - dest.writeInt(maxVideoBitrate); - dest.writeInt(minVideoWidth); - dest.writeInt(minVideoHeight); - dest.writeInt(minVideoFrameRate); - dest.writeInt(minVideoBitrate); Util.writeBoolean(dest, exceedVideoConstraintsIfNecessary); Util.writeBoolean(dest, allowVideoMixedMimeTypeAdaptiveness); Util.writeBoolean(dest, allowVideoNonSeamlessAdaptiveness); - dest.writeInt(viewportWidth); - dest.writeInt(viewportHeight); - Util.writeBoolean(dest, viewportOrientationMayChange); - dest.writeList(preferredVideoMimeTypes); // Audio - dest.writeInt(maxAudioChannelCount); - dest.writeInt(maxAudioBitrate); Util.writeBoolean(dest, exceedAudioConstraintsIfNecessary); Util.writeBoolean(dest, allowAudioMixedMimeTypeAdaptiveness); Util.writeBoolean(dest, allowAudioMixedSampleRateAdaptiveness); Util.writeBoolean(dest, allowAudioMixedChannelCountAdaptiveness); - dest.writeList(preferredAudioMimeTypes); + // Text + dest.writeInt(disabledTextTrackSelectionFlags); // General - Util.writeBoolean(dest, forceLowestBitrate); - Util.writeBoolean(dest, forceHighestSupportedBitrate); Util.writeBoolean(dest, exceedRendererCapabilitiesIfNecessary); Util.writeBoolean(dest, tunnelingEnabled); Util.writeBoolean(dest, allowMultipleAdaptiveSelections); @@ -1392,20 +1017,6 @@ public void writeToParcel(Parcel dest, int flags) { dest.writeSparseBooleanArray(rendererDisabledFlags); } - public static final Parcelable.Creator CREATOR = - new Parcelable.Creator() { - - @Override - public Parameters createFromParcel(Parcel in) { - return new Parameters(in); - } - - @Override - public Parameters[] newArray(int size) { - return new Parameters[size]; - } - }; - // Static utility methods. private static SparseArray> diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/ExoTrackSelection.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/ExoTrackSelection.java index ee1fa2dcfed..ca4445362d0 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/ExoTrackSelection.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/ExoTrackSelection.java @@ -134,9 +134,9 @@ ExoTrackSelection[] createTrackSelections( * Called to notify the selection of the current playback speed. The playback speed may affect * adaptive track selection. * - * @param speed The factor by which playback is sped up. + * @param playbackSpeed The factor by which playback is sped up. */ - void onPlaybackSpeed(float speed); + void onPlaybackSpeed(float playbackSpeed); /** * Called to notify the selection of a position discontinuity. diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/FixedTrackSelection.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/FixedTrackSelection.java index b630c127acf..7995526408b 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/FixedTrackSelection.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/FixedTrackSelection.java @@ -89,5 +89,4 @@ public int getSelectionReason() { public Object getSelectionData() { return data; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/MappingTrackSelector.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/MappingTrackSelector.java index 05ea4bb3c47..b73eb43c18d 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/MappingTrackSelector.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/MappingTrackSelector.java @@ -325,7 +325,7 @@ public final void onSelectionActivated(@Nullable Object info) { public final TrackSelectorResult selectTracks( RendererCapabilities[] rendererCapabilities, TrackGroupArray trackGroups, - MediaPeriodId mediaPeriodId, + MediaPeriodId periodId, Timeline timeline) throws ExoPlaybackException { // Structures into which data will be written during the selection. The extra item at the end @@ -404,7 +404,7 @@ public final TrackSelectorResult selectTracks( mappedTrackInfo, rendererFormatSupports, rendererMixedMimeTypeAdaptationSupports, - mediaPeriodId, + periodId, timeline); return new TrackSelectorResult(result.first, result.second, mappedTrackInfo); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.java deleted file mode 100644 index 88719bc0abe..00000000000 --- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.java +++ /dev/null @@ -1,406 +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 com.google.android.exoplayer2.trackselection; - -import static com.google.android.exoplayer2.util.Assertions.checkNotNull; - -import android.content.Context; -import android.os.Looper; -import android.os.Parcel; -import android.os.Parcelable; -import android.view.accessibility.CaptioningManager; -import androidx.annotation.Nullable; -import androidx.annotation.RequiresApi; -import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.util.Util; -import com.google.common.collect.ImmutableList; -import java.util.ArrayList; -import java.util.Locale; - -/** Constraint parameters for track selection. */ -public class TrackSelectionParameters implements Parcelable { - - /** - * A builder for {@link TrackSelectionParameters}. See the {@link TrackSelectionParameters} - * documentation for explanations of the parameters that can be configured using this builder. - */ - public static class Builder { - - /* package */ ImmutableList preferredAudioLanguages; - @C.RoleFlags /* package */ int preferredAudioRoleFlags; - /* package */ ImmutableList preferredTextLanguages; - @C.RoleFlags /* package */ int preferredTextRoleFlags; - /* package */ boolean selectUndeterminedTextLanguage; - @C.SelectionFlags /* package */ int disabledTextTrackSelectionFlags; - - /** - * Creates a builder with default initial values. - * - * @param context Any context. - */ - @SuppressWarnings({"deprecation", "nullness:method.invocation.invalid"}) - public Builder(Context context) { - this(); - setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings(context); - } - - /** - * @deprecated {@link Context} constraints will not be set when using this constructor. Use - * {@link #Builder(Context)} instead. - */ - @Deprecated - public Builder() { - preferredAudioLanguages = ImmutableList.of(); - preferredAudioRoleFlags = 0; - preferredTextLanguages = ImmutableList.of(); - preferredTextRoleFlags = 0; - selectUndeterminedTextLanguage = false; - disabledTextTrackSelectionFlags = 0; - } - - /** - * @param initialValues The {@link TrackSelectionParameters} from which the initial values of - * the builder are obtained. - */ - /* package */ Builder(TrackSelectionParameters initialValues) { - preferredAudioLanguages = initialValues.preferredAudioLanguages; - preferredAudioRoleFlags = initialValues.preferredAudioRoleFlags; - preferredTextLanguages = initialValues.preferredTextLanguages; - preferredTextRoleFlags = initialValues.preferredTextRoleFlags; - selectUndeterminedTextLanguage = initialValues.selectUndeterminedTextLanguage; - disabledTextTrackSelectionFlags = initialValues.disabledTextTrackSelectionFlags; - } - - /** - * Sets the preferred language for audio and forced text tracks. - * - * @param preferredAudioLanguage Preferred audio language as an IETF BCP 47 conformant tag, or - * {@code null} to select the default track, or the first track if there's no default. - * @return This builder. - */ - public Builder setPreferredAudioLanguage(@Nullable String preferredAudioLanguage) { - return preferredAudioLanguage == null - ? setPreferredAudioLanguages() - : setPreferredAudioLanguages(preferredAudioLanguage); - } - - /** - * Sets the preferred languages for audio and forced text tracks. - * - * @param preferredAudioLanguages Preferred audio languages as IETF BCP 47 conformant tags in - * order of preference, or an empty array to select the default track, or the first track if - * there's no default. - * @return This builder. - */ - public Builder setPreferredAudioLanguages(String... preferredAudioLanguages) { - ImmutableList.Builder listBuilder = ImmutableList.builder(); - for (String language : checkNotNull(preferredAudioLanguages)) { - listBuilder.add(Util.normalizeLanguageCode(checkNotNull(language))); - } - this.preferredAudioLanguages = listBuilder.build(); - return this; - } - - /** - * Sets the preferred {@link C.RoleFlags} for audio tracks. - * - * @param preferredAudioRoleFlags Preferred audio role flags. - * @return This builder. - */ - public Builder setPreferredAudioRoleFlags(@C.RoleFlags int preferredAudioRoleFlags) { - this.preferredAudioRoleFlags = preferredAudioRoleFlags; - return this; - } - - /** - * Sets the preferred language and role flags for text tracks based on the accessibility - * settings of {@link CaptioningManager}. - * - *

    Does nothing for API levels < 19 or when the {@link CaptioningManager} is disabled. - * - * @param context A {@link Context}. - * @return This builder. - */ - public Builder setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings( - Context context) { - if (Util.SDK_INT >= 19) { - setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettingsV19(context); - } - return this; - } - - /** - * Sets the preferred language for text tracks. - * - * @param preferredTextLanguage Preferred text language as an IETF BCP 47 conformant tag, or - * {@code null} to select the default track if there is one, or no track otherwise. - * @return This builder. - */ - public Builder setPreferredTextLanguage(@Nullable String preferredTextLanguage) { - return preferredTextLanguage == null - ? setPreferredTextLanguages() - : setPreferredTextLanguages(preferredTextLanguage); - } - - /** - * Sets the preferred languages for text tracks. - * - * @param preferredTextLanguages Preferred text languages as IETF BCP 47 conformant tags in - * order of preference, or an empty array to select the default track if there is one, or no - * track otherwise. - * @return This builder. - */ - public Builder setPreferredTextLanguages(String... preferredTextLanguages) { - ImmutableList.Builder listBuilder = ImmutableList.builder(); - for (String language : checkNotNull(preferredTextLanguages)) { - listBuilder.add(Util.normalizeLanguageCode(checkNotNull(language))); - } - this.preferredTextLanguages = listBuilder.build(); - return this; - } - - /** - * Sets the preferred {@link C.RoleFlags} for text tracks. - * - * @param preferredTextRoleFlags Preferred text role flags. - * @return This builder. - */ - public Builder setPreferredTextRoleFlags(@C.RoleFlags int preferredTextRoleFlags) { - this.preferredTextRoleFlags = preferredTextRoleFlags; - return this; - } - - /** - * Sets whether a text track with undetermined language should be selected if no track with - * {@link #setPreferredTextLanguages(String...) a preferred language} is available, or if the - * preferred language is unset. - * - * @param selectUndeterminedTextLanguage Whether a text track with undetermined language should - * be selected if no preferred language track is available. - * @return This builder. - */ - public Builder setSelectUndeterminedTextLanguage(boolean selectUndeterminedTextLanguage) { - this.selectUndeterminedTextLanguage = selectUndeterminedTextLanguage; - return this; - } - - /** - * Sets a bitmask of selection flags that are disabled for text track selections. - * - * @param disabledTextTrackSelectionFlags A bitmask of {@link C.SelectionFlags} that are - * disabled for text track selections. - * @return This builder. - */ - public Builder setDisabledTextTrackSelectionFlags( - @C.SelectionFlags int disabledTextTrackSelectionFlags) { - this.disabledTextTrackSelectionFlags = disabledTextTrackSelectionFlags; - return this; - } - - /** Builds a {@link TrackSelectionParameters} instance with the selected values. */ - public TrackSelectionParameters build() { - return new TrackSelectionParameters( - // Audio - preferredAudioLanguages, - preferredAudioRoleFlags, - // Text - preferredTextLanguages, - preferredTextRoleFlags, - selectUndeterminedTextLanguage, - disabledTextTrackSelectionFlags); - } - - @RequiresApi(19) - private void setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettingsV19( - Context context) { - if (Util.SDK_INT < 23 && Looper.myLooper() == null) { - // Android platform bug (pre-Marshmallow) that causes RuntimeExceptions when - // CaptioningService is instantiated from a non-Looper thread. See [internal: b/143779904]. - return; - } - CaptioningManager captioningManager = - (CaptioningManager) context.getSystemService(Context.CAPTIONING_SERVICE); - if (captioningManager == null || !captioningManager.isEnabled()) { - return; - } - preferredTextRoleFlags = C.ROLE_FLAG_CAPTION | C.ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND; - Locale preferredLocale = captioningManager.getLocale(); - if (preferredLocale != null) { - preferredTextLanguages = ImmutableList.of(Util.getLocaleLanguageTag(preferredLocale)); - } - } - } - - /** - * An instance with default values, except those obtained from the {@link Context}. - * - *

    If possible, use {@link #getDefaults(Context)} instead. - * - *

    This instance will not have the following settings: - * - *

      - *
    • {@link Builder#setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings(Context) - * Preferred text language and role flags} configured to the accessibility settings of - * {@link CaptioningManager}. - *
    - */ - @SuppressWarnings("deprecation") - public static final TrackSelectionParameters DEFAULT_WITHOUT_CONTEXT = new Builder().build(); - - /** - * @deprecated This instance is not configured using {@link Context} constraints. Use {@link - * #getDefaults(Context)} instead. - */ - @Deprecated public static final TrackSelectionParameters DEFAULT = DEFAULT_WITHOUT_CONTEXT; - - /** Returns an instance configured with default values. */ - public static TrackSelectionParameters getDefaults(Context context) { - return new Builder(context).build(); - } - - /** - * The preferred languages for audio and forced text tracks as IETF BCP 47 conformant tags in - * order of preference. An empty list selects the default track, or the first track if there's no - * default. The default value is an empty list. - */ - public final ImmutableList preferredAudioLanguages; - /** - * The preferred {@link C.RoleFlags} for audio tracks. {@code 0} selects the default track if - * there is one, or the first track if there's no default. The default value is {@code 0}. - */ - @C.RoleFlags public final int preferredAudioRoleFlags; - /** - * The preferred languages for text tracks as IETF BCP 47 conformant tags in order of preference. - * An empty list selects the default track if there is one, or no track otherwise. The default - * value is an empty list, or the language of the accessibility {@link CaptioningManager} if - * enabled. - */ - public final ImmutableList preferredTextLanguages; - /** - * The preferred {@link C.RoleFlags} for text tracks. {@code 0} selects the default track if there - * is one, or no track otherwise. The default value is {@code 0}, or {@link C#ROLE_FLAG_SUBTITLE} - * | {@link C#ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND} if the accessibility {@link CaptioningManager} - * is enabled. - */ - @C.RoleFlags public final int preferredTextRoleFlags; - /** - * Whether a text track with undetermined language should be selected if no track with {@link - * #preferredTextLanguages} is available, or if {@link #preferredTextLanguages} is unset. The - * default value is {@code false}. - */ - public final boolean selectUndeterminedTextLanguage; - /** - * Bitmask of selection flags that are disabled for text track selections. See {@link - * C.SelectionFlags}. The default value is {@code 0} (i.e. no flags). - */ - @C.SelectionFlags public final int disabledTextTrackSelectionFlags; - - /* package */ TrackSelectionParameters( - ImmutableList preferredAudioLanguages, - @C.RoleFlags int preferredAudioRoleFlags, - ImmutableList preferredTextLanguages, - @C.RoleFlags int preferredTextRoleFlags, - boolean selectUndeterminedTextLanguage, - @C.SelectionFlags int disabledTextTrackSelectionFlags) { - // Audio - this.preferredAudioLanguages = preferredAudioLanguages; - this.preferredAudioRoleFlags = preferredAudioRoleFlags; - // Text - this.preferredTextLanguages = preferredTextLanguages; - this.preferredTextRoleFlags = preferredTextRoleFlags; - this.selectUndeterminedTextLanguage = selectUndeterminedTextLanguage; - this.disabledTextTrackSelectionFlags = disabledTextTrackSelectionFlags; - } - - /* package */ TrackSelectionParameters(Parcel in) { - ArrayList preferredAudioLanguages = new ArrayList<>(); - in.readList(preferredAudioLanguages, /* loader= */ null); - this.preferredAudioLanguages = ImmutableList.copyOf(preferredAudioLanguages); - this.preferredAudioRoleFlags = in.readInt(); - ArrayList preferredTextLanguages = new ArrayList<>(); - in.readList(preferredTextLanguages, /* loader= */ null); - this.preferredTextLanguages = ImmutableList.copyOf(preferredTextLanguages); - this.preferredTextRoleFlags = in.readInt(); - this.selectUndeterminedTextLanguage = Util.readBoolean(in); - this.disabledTextTrackSelectionFlags = in.readInt(); - } - - /** Creates a new {@link Builder}, copying the initial values from this instance. */ - public Builder buildUpon() { - return new Builder(this); - } - - @Override - @SuppressWarnings("EqualsGetClass") - public boolean equals(@Nullable Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - TrackSelectionParameters other = (TrackSelectionParameters) obj; - return preferredAudioLanguages.equals(other.preferredAudioLanguages) - && preferredAudioRoleFlags == other.preferredAudioRoleFlags - && preferredTextLanguages.equals(other.preferredTextLanguages) - && preferredTextRoleFlags == other.preferredTextRoleFlags - && selectUndeterminedTextLanguage == other.selectUndeterminedTextLanguage - && disabledTextTrackSelectionFlags == other.disabledTextTrackSelectionFlags; - } - - @Override - public int hashCode() { - int result = 1; - result = 31 * result + preferredAudioLanguages.hashCode(); - result = 31 * result + preferredAudioRoleFlags; - result = 31 * result + preferredTextLanguages.hashCode(); - result = 31 * result + preferredTextRoleFlags; - result = 31 * result + (selectUndeterminedTextLanguage ? 1 : 0); - result = 31 * result + disabledTextTrackSelectionFlags; - return result; - } - - // Parcelable implementation. - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeList(preferredAudioLanguages); - dest.writeInt(preferredAudioRoleFlags); - dest.writeList(preferredTextLanguages); - dest.writeInt(preferredTextRoleFlags); - Util.writeBoolean(dest, selectUndeterminedTextLanguage); - dest.writeInt(disabledTextTrackSelectionFlags); - } - - public static final Creator CREATOR = - new Creator() { - - @Override - public TrackSelectionParameters createFromParcel(Parcel in) { - return new TrackSelectionParameters(in); - } - - @Override - public TrackSelectionParameters[] newArray(int size) { - return new TrackSelectionParameters[size]; - } - }; -} diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionUtil.java index 53ae2e9cd6a..a0cc74588d8 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionUtil.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionUtil.java @@ -15,10 +15,12 @@ */ package com.google.android.exoplayer2.trackselection; +import android.os.SystemClock; import androidx.annotation.Nullable; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride; import com.google.android.exoplayer2.trackselection.ExoTrackSelection.Definition; +import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy; import com.google.android.exoplayer2.util.MimeTypes; import org.checkerframework.checker.nullness.compatqual.NullableType; @@ -114,4 +116,29 @@ public static boolean hasTrackOfType(TrackSelectionArray trackSelections, int tr } return false; } + + /** + * Returns the {@link LoadErrorHandlingPolicy.FallbackOptions} with the tracks of the given {@link + * ExoTrackSelection} and with a single location option indicating that there are no alternative + * locations available. + * + * @param trackSelection The track selection to get the number of total and excluded tracks. + * @return The {@link LoadErrorHandlingPolicy.FallbackOptions} for the given track selection. + */ + public static LoadErrorHandlingPolicy.FallbackOptions createFallbackOptions( + ExoTrackSelection trackSelection) { + long nowMs = SystemClock.elapsedRealtime(); + int numberOfTracks = trackSelection.length(); + int numberOfExcludedTracks = 0; + for (int i = 0; i < numberOfTracks; i++) { + if (trackSelection.isBlacklisted(i, nowMs)) { + numberOfExcludedTracks++; + } + } + return new LoadErrorHandlingPolicy.FallbackOptions( + /* numberOfLocations= */ 1, + /* numberOfExcludedLocations= */ 0, + numberOfTracks, + numberOfExcludedTracks); + } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelector.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelector.java index 59c5d5447bf..88736c0a1c3 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelector.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelector.java @@ -32,7 +32,7 @@ * the player's {@link Renderer}s. The {@link DefaultTrackSelector} implementation should be * suitable for most use cases. * - *

    Interactions with the player

    + *

    Interactions with the player

    * * The following interactions occur between the player and its track selector during playback. * @@ -65,7 +65,7 @@ * will call {@link InvalidationListener#onTrackSelectionsInvalidated()}. * * - *

    Renderer configuration

    + *

    Renderer configuration

    * * The {@link TrackSelectorResult} returned by {@link #selectTracks(RendererCapabilities[], * TrackGroupArray, MediaPeriodId, Timeline)} contains not only {@link TrackSelection}s for each @@ -77,7 +77,7 @@ * configure renderers in a particular way if certain tracks are selected. Hence it makes sense to * determine the track selection and corresponding renderer configurations in a single step. * - *

    Threading model

    + *

    Threading model

    * * All calls made by the player into the track selector are on the player's internal playback * thread. The track selector may call {@link InvalidationListener#onTrackSelectionsInvalidated()} @@ -85,9 +85,7 @@ */ public abstract class TrackSelector { - /** - * Notified when selections previously made by a {@link TrackSelector} are no longer valid. - */ + /** Notified when selections previously made by a {@link TrackSelector} are no longer valid. */ public interface InvalidationListener { /** @@ -95,7 +93,6 @@ public interface InvalidationListener { * longer valid. May be called from any thread. */ void onTrackSelectionsInvalidated(); - } @Nullable private InvalidationListener listener; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/Allocation.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/Allocation.java index 4121a408751..7e815d259f6 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/Allocation.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/Allocation.java @@ -29,9 +29,7 @@ public final class Allocation { */ public final byte[] data; - /** - * The offset of the allocated space in {@link #data}. - */ + /** The offset of the allocated space in {@link #data}. */ public final int offset; /** @@ -42,5 +40,4 @@ public Allocation(byte[] data, int offset) { this.data = data; this.offset = offset; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/Allocator.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/Allocator.java index d508d375c30..6b9ddcc1dac 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/Allocator.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/Allocator.java @@ -20,8 +20,8 @@ public interface Allocator { /** * Obtain an {@link Allocation}. - *

    - * When the caller has finished with the {@link Allocation}, it should be returned by calling + * + *

    When the caller has finished with the {@link Allocation}, it should be returned by calling * {@link #release(Allocation)}. * * @return The {@link Allocation}. @@ -43,19 +43,14 @@ public interface Allocator { void release(Allocation[] allocations); /** - * Hints to the allocator that it should make a best effort to release any excess - * {@link Allocation}s. + * Hints to the allocator that it should make a best effort to release any excess {@link + * Allocation}s. */ void trim(); - /** - * Returns the total number of bytes currently allocated. - */ + /** Returns the total number of bytes currently allocated. */ int getTotalBytesAllocated(); - /** - * Returns the length of each individual {@link Allocation}. - */ + /** Returns the length of each individual {@link Allocation}. */ int getIndividualAllocationLength(); - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/AssetDataSource.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/AssetDataSource.java index 05838c8a2df..f295fc5722b 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/AssetDataSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/AssetDataSource.java @@ -23,22 +23,34 @@ import android.net.Uri; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.util.Assertions; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; /** A {@link DataSource} for reading from a local asset. */ public final class AssetDataSource extends BaseDataSource { - /** - * Thrown when an {@link IOException} is encountered reading a local asset. - */ - public static final class AssetDataSourceException extends IOException { + /** Thrown when an {@link IOException} is encountered reading a local asset. */ + public static final class AssetDataSourceException extends DataSourceException { + /** @deprecated Use {@link #AssetDataSourceException(Throwable, int)}. */ + @Deprecated public AssetDataSourceException(IOException cause) { - super(cause); + super(cause, PlaybackException.ERROR_CODE_IO_UNSPECIFIED); } + /** + * Creates a new instance. + * + * @param cause The error cause. + * @param errorCode See {@link PlaybackException.ErrorCode}. + */ + public AssetDataSourceException( + @Nullable Throwable cause, @PlaybackException.ErrorCode int errorCode) { + super(cause, errorCode); + } } private final AssetManager assetManager; @@ -70,7 +82,8 @@ public long open(DataSpec dataSpec) throws AssetDataSourceException { if (skipped < dataSpec.position) { // assetManager.open() returns an AssetInputStream, whose skip() implementation only skips // fewer bytes than requested if the skip is beyond the end of the asset's data. - throw new DataSourceException(DataSourceException.POSITION_OUT_OF_RANGE); + throw new AssetDataSourceException( + /* cause= */ null, PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE); } if (dataSpec.length != C.LENGTH_UNSET) { bytesRemaining = dataSpec.length; @@ -83,8 +96,14 @@ public long open(DataSpec dataSpec) throws AssetDataSourceException { bytesRemaining = C.LENGTH_UNSET; } } + } catch (AssetDataSourceException e) { + throw e; } catch (IOException e) { - throw new AssetDataSourceException(e); + throw new AssetDataSourceException( + e, + e instanceof FileNotFoundException + ? PlaybackException.ERROR_CODE_IO_FILE_NOT_FOUND + : PlaybackException.ERROR_CODE_IO_UNSPECIFIED); } opened = true; @@ -93,8 +112,8 @@ public long open(DataSpec dataSpec) throws AssetDataSourceException { } @Override - public int read(byte[] buffer, int offset, int readLength) throws AssetDataSourceException { - if (readLength == 0) { + public int read(byte[] buffer, int offset, int length) throws AssetDataSourceException { + if (length == 0) { return 0; } else if (bytesRemaining == 0) { return C.RESULT_END_OF_INPUT; @@ -103,10 +122,10 @@ public int read(byte[] buffer, int offset, int readLength) throws AssetDataSourc int bytesRead; try { int bytesToRead = - bytesRemaining == C.LENGTH_UNSET ? readLength : (int) min(bytesRemaining, readLength); + bytesRemaining == C.LENGTH_UNSET ? length : (int) min(bytesRemaining, length); bytesRead = castNonNull(inputStream).read(buffer, offset, bytesToRead); } catch (IOException e) { - throw new AssetDataSourceException(e); + throw new AssetDataSourceException(e, PlaybackException.ERROR_CODE_IO_UNSPECIFIED); } if (bytesRead == -1) { @@ -133,7 +152,7 @@ public void close() throws AssetDataSourceException { inputStream.close(); } } catch (IOException e) { - throw new AssetDataSourceException(e); + throw new AssetDataSourceException(e, PlaybackException.ERROR_CODE_IO_UNSPECIFIED); } finally { inputStream = null; if (opened) { @@ -142,5 +161,4 @@ public void close() throws AssetDataSourceException { } } } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/BandwidthMeter.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/BandwidthMeter.java index c5b28933988..44e0bb4d4b0 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/BandwidthMeter.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/BandwidthMeter.java @@ -24,9 +24,7 @@ /** Provides estimates of the currently available bandwidth. */ public interface BandwidthMeter { - /** - * A listener of {@link BandwidthMeter} events. - */ + /** A listener of {@link BandwidthMeter} events. */ interface EventListener { /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/ByteArrayDataSink.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/ByteArrayDataSink.java index 63b8fd6e190..94714834196 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/ByteArrayDataSink.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/ByteArrayDataSink.java @@ -57,5 +57,4 @@ public void write(byte[] buffer, int offset, int length) { public byte[] getData() { return stream == null ? null : stream.toByteArray(); } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/ByteArrayDataSource.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/ByteArrayDataSource.java index 24d2c728a1f..a770c97ad7b 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/ByteArrayDataSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/ByteArrayDataSource.java @@ -20,6 +20,7 @@ import android.net.Uri; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.util.Assertions; import java.io.IOException; @@ -33,9 +34,7 @@ public final class ByteArrayDataSource extends BaseDataSource { private int bytesRemaining; private boolean opened; - /** - * @param data The data to be read. - */ + /** @param data The data to be read. */ public ByteArrayDataSource(byte[] data) { super(/* isNetwork= */ false); Assertions.checkNotNull(data); @@ -48,7 +47,7 @@ public long open(DataSpec dataSpec) throws IOException { uri = dataSpec.uri; transferInitializing(dataSpec); if (dataSpec.position > data.length) { - throw new DataSourceException(DataSourceException.POSITION_OUT_OF_RANGE); + throw new DataSourceException(PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE); } readPosition = (int) dataSpec.position; bytesRemaining = data.length - (int) dataSpec.position; @@ -61,19 +60,19 @@ public long open(DataSpec dataSpec) throws IOException { } @Override - public int read(byte[] buffer, int offset, int readLength) { - if (readLength == 0) { + public int read(byte[] buffer, int offset, int length) { + if (length == 0) { return 0; } else if (bytesRemaining == 0) { return C.RESULT_END_OF_INPUT; } - readLength = min(readLength, bytesRemaining); - System.arraycopy(data, readPosition, buffer, offset, readLength); - readPosition += readLength; - bytesRemaining -= readLength; - bytesTransferred(readLength); - return readLength; + length = min(length, bytesRemaining); + System.arraycopy(data, readPosition, buffer, offset, length); + readPosition += length; + bytesRemaining -= length; + bytesTransferred(length); + return length; } @Override @@ -90,5 +89,4 @@ public void close() { } uri = null; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java index be93f883fe2..3e53896ac03 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java @@ -24,6 +24,7 @@ import android.net.Uri; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.PlaybackException; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; @@ -32,15 +33,20 @@ /** A {@link DataSource} for reading from a content URI. */ public final class ContentDataSource extends BaseDataSource { - /** - * Thrown when an {@link IOException} is encountered reading from a content URI. - */ - public static class ContentDataSourceException extends IOException { + /** Thrown when an {@link IOException} is encountered reading from a content URI. */ + public static class ContentDataSourceException extends DataSourceException { + /** @deprecated Use {@link #ContentDataSourceException(IOException, int)}. */ + @Deprecated public ContentDataSourceException(IOException cause) { - super(cause); + this(cause, PlaybackException.ERROR_CODE_IO_UNSPECIFIED); } + /** Creates a new instance. */ + public ContentDataSourceException( + @Nullable IOException cause, @PlaybackException.ErrorCode int errorCode) { + super(cause, errorCode); + } } private final ContentResolver resolver; @@ -51,9 +57,7 @@ public ContentDataSourceException(IOException cause) { private long bytesRemaining; private boolean opened; - /** - * @param context A context. - */ + /** @param context A context. */ public ContentDataSource(Context context) { super(/* isNetwork= */ false); this.resolver = context.getContentResolver(); @@ -69,7 +73,10 @@ public long open(DataSpec dataSpec) throws ContentDataSourceException { AssetFileDescriptor assetFileDescriptor = resolver.openAssetFileDescriptor(uri, "r"); this.assetFileDescriptor = assetFileDescriptor; if (assetFileDescriptor == null) { - throw new FileNotFoundException("Could not open file descriptor for: " + uri); + // openAssetFileDescriptor returns null if the provider recently crashed. + throw new ContentDataSourceException( + new IOException("Could not open file descriptor for: " + uri), + PlaybackException.ERROR_CODE_IO_UNSPECIFIED); } long assetFileDescriptorLength = assetFileDescriptor.getLength(); @@ -84,7 +91,8 @@ public long open(DataSpec dataSpec) throws ContentDataSourceException { // file. if (assetFileDescriptorLength != AssetFileDescriptor.UNKNOWN_LENGTH && dataSpec.position > assetFileDescriptorLength) { - throw new DataSourceException(DataSourceException.POSITION_OUT_OF_RANGE); + throw new ContentDataSourceException( + /* cause= */ null, PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE); } long assetFileDescriptorOffset = assetFileDescriptor.getStartOffset(); long skipped = @@ -93,7 +101,8 @@ public long open(DataSpec dataSpec) throws ContentDataSourceException { if (skipped != dataSpec.position) { // We expect the skip to be satisfied in full. If it isn't then we're probably trying to // read beyond the end of the last resource in the file. - throw new DataSourceException(DataSourceException.POSITION_OUT_OF_RANGE); + throw new ContentDataSourceException( + /* cause= */ null, PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE); } if (assetFileDescriptorLength == AssetFileDescriptor.UNKNOWN_LENGTH) { // The asset must extend to the end of the file. We can try and resolve the length with @@ -106,17 +115,25 @@ public long open(DataSpec dataSpec) throws ContentDataSourceException { bytesRemaining = channelSize - channel.position(); if (bytesRemaining < 0) { // The skip above was satisfied in full, but skipped beyond the end of the file. - throw new DataSourceException(DataSourceException.POSITION_OUT_OF_RANGE); + throw new ContentDataSourceException( + /* cause= */ null, PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE); } } } else { bytesRemaining = assetFileDescriptorLength - skipped; if (bytesRemaining < 0) { - throw new DataSourceException(DataSourceException.POSITION_OUT_OF_RANGE); + throw new ContentDataSourceException( + /* cause= */ null, PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE); } } + } catch (ContentDataSourceException e) { + throw e; } catch (IOException e) { - throw new ContentDataSourceException(e); + throw new ContentDataSourceException( + e, + e instanceof FileNotFoundException + ? PlaybackException.ERROR_CODE_IO_FILE_NOT_FOUND + : PlaybackException.ERROR_CODE_IO_UNSPECIFIED); } if (dataSpec.length != C.LENGTH_UNSET) { @@ -129,8 +146,8 @@ public long open(DataSpec dataSpec) throws ContentDataSourceException { } @Override - public int read(byte[] buffer, int offset, int readLength) throws ContentDataSourceException { - if (readLength == 0) { + public int read(byte[] buffer, int offset, int length) throws ContentDataSourceException { + if (length == 0) { return 0; } else if (bytesRemaining == 0) { return C.RESULT_END_OF_INPUT; @@ -139,10 +156,10 @@ public int read(byte[] buffer, int offset, int readLength) throws ContentDataSou int bytesRead; try { int bytesToRead = - bytesRemaining == C.LENGTH_UNSET ? readLength : (int) min(bytesRemaining, readLength); + bytesRemaining == C.LENGTH_UNSET ? length : (int) min(bytesRemaining, length); bytesRead = castNonNull(inputStream).read(buffer, offset, bytesToRead); } catch (IOException e) { - throw new ContentDataSourceException(e); + throw new ContentDataSourceException(e, PlaybackException.ERROR_CODE_IO_UNSPECIFIED); } if (bytesRead == -1) { @@ -170,7 +187,7 @@ public void close() throws ContentDataSourceException { inputStream.close(); } } catch (IOException e) { - throw new ContentDataSourceException(e); + throw new ContentDataSourceException(e, PlaybackException.ERROR_CODE_IO_UNSPECIFIED); } finally { inputStream = null; try { @@ -178,7 +195,7 @@ public void close() throws ContentDataSourceException { assetFileDescriptor.close(); } } catch (IOException e) { - throw new ContentDataSourceException(e); + throw new ContentDataSourceException(e, PlaybackException.ERROR_CODE_IO_UNSPECIFIED); } finally { assetFileDescriptor = null; if (opened) { @@ -188,5 +205,4 @@ public void close() throws ContentDataSourceException { } } } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/DataSchemeDataSource.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/DataSchemeDataSource.java index 0d1166e8a21..786d497730c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/DataSchemeDataSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/DataSchemeDataSource.java @@ -23,6 +23,8 @@ import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ParserException; +import com.google.android.exoplayer2.PlaybackException; +import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Util; import com.google.common.base.Charsets; import java.io.IOException; @@ -48,19 +50,19 @@ public long open(DataSpec dataSpec) throws IOException { this.dataSpec = dataSpec; Uri uri = dataSpec.uri; String scheme = uri.getScheme(); - if (!SCHEME_DATA.equals(scheme)) { - throw new ParserException("Unsupported scheme: " + scheme); - } + Assertions.checkArgument(SCHEME_DATA.equals(scheme), "Unsupported scheme: " + scheme); String[] uriParts = Util.split(uri.getSchemeSpecificPart(), ","); if (uriParts.length != 2) { - throw new ParserException("Unexpected URI format: " + uri); + throw ParserException.createForMalformedDataOfUnknownType( + "Unexpected URI format: " + uri, /* cause= */ null); } String dataString = uriParts[1]; if (uriParts[0].contains(";base64")) { try { data = Base64.decode(dataString, /* flags= */ Base64.DEFAULT); } catch (IllegalArgumentException e) { - throw new ParserException("Error while parsing Base64 encoded string: " + dataString, e); + throw ParserException.createForMalformedDataOfUnknownType( + "Error while parsing Base64 encoded string: " + dataString, e); } } else { // TODO: Add support for other charsets. @@ -68,7 +70,7 @@ public long open(DataSpec dataSpec) throws IOException { } if (dataSpec.position > data.length) { data = null; - throw new DataSourceException(DataSourceException.POSITION_OUT_OF_RANGE); + throw new DataSourceException(PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE); } readPosition = (int) dataSpec.position; bytesRemaining = data.length - readPosition; @@ -80,19 +82,19 @@ public long open(DataSpec dataSpec) throws IOException { } @Override - public int read(byte[] buffer, int offset, int readLength) { - if (readLength == 0) { + public int read(byte[] buffer, int offset, int length) { + if (length == 0) { return 0; } if (bytesRemaining == 0) { return C.RESULT_END_OF_INPUT; } - readLength = min(readLength, bytesRemaining); - System.arraycopy(castNonNull(data), readPosition, buffer, offset, readLength); - readPosition += readLength; - bytesRemaining -= readLength; - bytesTransferred(readLength); - return readLength; + length = min(length, bytesRemaining); + System.arraycopy(castNonNull(data), readPosition, buffer, offset, length); + readPosition += length; + bytesRemaining -= length; + bytesTransferred(length); + return length; } @Override diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/DataSink.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/DataSink.java index 594403c33df..af644a8c487 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/DataSink.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/DataSink.java @@ -20,16 +20,11 @@ /** A component to which streams of data can be written. */ public interface DataSink { - /** - * A factory for {@link DataSink} instances. - */ + /** A factory for {@link DataSink} instances. */ interface Factory { - /** - * Creates a {@link DataSink} instance. - */ + /** Creates a {@link DataSink} instance. */ DataSink createDataSink(); - } /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/DataSourceInputStream.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/DataSourceInputStream.java index c4296bd6f6e..ddc68d137ac 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/DataSourceInputStream.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/DataSourceInputStream.java @@ -44,17 +44,15 @@ public DataSourceInputStream(DataSource dataSource, DataSpec dataSpec) { singleByteArray = new byte[1]; } - /** - * Returns the total number of bytes that have been read or skipped. - */ + /** Returns the total number of bytes that have been read or skipped. */ public long bytesRead() { return totalBytesRead; } /** * Optional call to open the underlying {@link DataSource}. - *

    - * Calling this method does nothing if the {@link DataSource} is already open. Calling this + * + *

    Calling this method does nothing if the {@link DataSource} is already open. Calling this * method is optional, since the read and skip methods will automatically open the underlying * {@link DataSource} if it's not open already. * @@ -102,5 +100,4 @@ private void checkOpened() throws IOException { opened = true; } } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultAllocator.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultAllocator.java index f354dc58ef1..b79b66c9304 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultAllocator.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultAllocator.java @@ -51,16 +51,16 @@ public DefaultAllocator(boolean trimOnReset, int individualAllocationSize) { /** * Constructs an instance with some {@link Allocation}s created up front. - *

    - * Note: {@link Allocation}s created up front will never be discarded by {@link #trim()}. + * + *

    Note: {@link Allocation}s created up front will never be discarded by {@link #trim()}. * * @param trimOnReset Whether memory is freed when the allocator is reset. Should be true unless * the allocator will be re-used by multiple player instances. * @param individualAllocationSize The length of each individual {@link Allocation}. * @param initialAllocationCount The number of allocations to create up front. */ - public DefaultAllocator(boolean trimOnReset, int individualAllocationSize, - int initialAllocationCount) { + public DefaultAllocator( + boolean trimOnReset, int individualAllocationSize, int initialAllocationCount) { Assertions.checkArgument(individualAllocationSize > 0); Assertions.checkArgument(initialAllocationCount >= 0); this.trimOnReset = trimOnReset; @@ -179,5 +179,4 @@ public synchronized int getTotalBytesAllocated() { public int getIndividualAllocationLength() { return individualAllocationSize; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultBandwidthMeter.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultBandwidthMeter.java index 1c0b3f26429..7fd0928c61b 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultBandwidthMeter.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultBandwidthMeter.java @@ -372,11 +372,11 @@ public synchronized void onTransferStart( @Override public synchronized void onBytesTransferred( - DataSource source, DataSpec dataSpec, boolean isNetwork, int bytes) { + DataSource source, DataSpec dataSpec, boolean isNetwork, int bytesTransferred) { if (!isTransferAtFullNetworkSpeed(dataSpec, isNetwork)) { return; } - sampleBytesTransferred += bytes; + sampleBytesTransferred += bytesTransferred; } @Override diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultDataSource.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultDataSource.java index cf89180b431..c2963f386e8 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultDataSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultDataSource.java @@ -202,8 +202,8 @@ public long open(DataSpec dataSpec) throws IOException { } @Override - public int read(byte[] buffer, int offset, int readLength) throws IOException { - return Assertions.checkNotNull(dataSource).read(buffer, offset, readLength); + public int read(byte[] buffer, int offset, int length) throws IOException { + return Assertions.checkNotNull(dataSource).read(buffer, offset, length); } @Override @@ -263,10 +263,8 @@ private DataSource getContentDataSource() { private DataSource getRtmpDataSource() { if (rtmpDataSource == null) { try { - // LINT.IfChange Class clazz = Class.forName("com.google.android.exoplayer2.ext.rtmp.RtmpDataSource"); rtmpDataSource = (DataSource) clazz.getConstructor().newInstance(); - // LINT.ThenChange(../../../../../../../../proguard-rules.txt) addListenersToDataSource(rtmpDataSource); } catch (ClassNotFoundException e) { // Expected if the app was built without the RTMP extension. diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSourceFactory.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSourceFactory.java index 88b9112af88..ca309ad5921 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSourceFactory.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSourceFactory.java @@ -61,8 +61,12 @@ public DefaultHttpDataSourceFactory(@Nullable String userAgent) { */ public DefaultHttpDataSourceFactory( @Nullable String userAgent, @Nullable TransferListener listener) { - this(userAgent, listener, DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS, - DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS, false); + this( + userAgent, + listener, + DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS, + DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS, + false); } /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultLoadErrorHandlingPolicy.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultLoadErrorHandlingPolicy.java index 091c57de108..8544a294a86 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultLoadErrorHandlingPolicy.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultLoadErrorHandlingPolicy.java @@ -17,6 +17,7 @@ import static java.lang.Math.min; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.upstream.HttpDataSource.CleartextNotPermittedException; @@ -36,7 +37,11 @@ public class DefaultLoadErrorHandlingPolicy implements LoadErrorHandlingPolicy { */ public static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT_PROGRESSIVE_LIVE = 6; /** The default duration for which a track is excluded in milliseconds. */ - public static final long DEFAULT_TRACK_BLACKLIST_MS = 60_000; + public static final long DEFAULT_TRACK_EXCLUSION_MS = 60_000; + /** @deprecated Use {@link #DEFAULT_TRACK_EXCLUSION_MS} instead. */ + @Deprecated public static final long DEFAULT_TRACK_BLACKLIST_MS = DEFAULT_TRACK_EXCLUSION_MS; + /** The default duration for which a location is excluded in milliseconds. */ + public static final long DEFAULT_LOCATION_EXCLUSION_MS = 5 * 60_000; private static final int DEFAULT_BEHAVIOR_MIN_LOADABLE_RETRY_COUNT = -1; @@ -64,25 +69,33 @@ public DefaultLoadErrorHandlingPolicy(int minimumLoadableRetryCount) { } /** - * Returns the exclusion duration, given by {@link #DEFAULT_TRACK_BLACKLIST_MS}, if the load error - * was an {@link InvalidResponseCodeException} with response code HTTP 404, 410 or 416, or {@link - * C#TIME_UNSET} otherwise. + * Returns whether a loader should fall back to using another resource on encountering an error, + * and if so the duration for which the failing resource should be excluded. + * + *

      + *
    • This policy will only specify a fallback if {@link #isEligibleForFallback} returns {@code + * true} for the error. + *
    • This policy will always specify a location fallback rather than a track fallback if both + * {@link FallbackOptions#isFallbackAvailable(int) are available}. + *
    • When a fallback is specified, the duration for which the failing resource will be + * excluded is {@link #DEFAULT_LOCATION_EXCLUSION_MS} or {@link + * #DEFAULT_TRACK_EXCLUSION_MS}, depending on the fallback type. + *
    */ @Override - public long getBlacklistDurationMsFor(LoadErrorInfo loadErrorInfo) { - IOException exception = loadErrorInfo.exception; - if (exception instanceof InvalidResponseCodeException) { - int responseCode = ((InvalidResponseCodeException) exception).responseCode; - return responseCode == 403 // HTTP 403 Forbidden. - || responseCode == 404 // HTTP 404 Not Found. - || responseCode == 410 // HTTP 410 Gone. - || responseCode == 416 // HTTP 416 Range Not Satisfiable. - || responseCode == 500 // HTTP 500 Internal Server Error. - || responseCode == 503 // HTTP 503 Service Unavailable. - ? DEFAULT_TRACK_BLACKLIST_MS - : C.TIME_UNSET; + @Nullable + public FallbackSelection getFallbackSelectionFor( + FallbackOptions fallbackOptions, LoadErrorInfo loadErrorInfo) { + if (!isEligibleForFallback(loadErrorInfo.exception)) { + return null; + } + // Prefer location fallbacks to track fallbacks, when both are available. + if (fallbackOptions.isFallbackAvailable(FALLBACK_TYPE_LOCATION)) { + return new FallbackSelection(FALLBACK_TYPE_LOCATION, DEFAULT_LOCATION_EXCLUSION_MS); + } else if (fallbackOptions.isFallbackAvailable(FALLBACK_TYPE_TRACK)) { + return new FallbackSelection(FALLBACK_TYPE_TRACK, DEFAULT_TRACK_EXCLUSION_MS); } - return C.TIME_UNSET; + return null; } /** @@ -116,4 +129,19 @@ public int getMinimumLoadableRetryCount(int dataType) { return minimumLoadableRetryCount; } } + + /** Returns whether an error should trigger a fallback if possible. */ + protected boolean isEligibleForFallback(IOException exception) { + if (!(exception instanceof InvalidResponseCodeException)) { + return false; + } + InvalidResponseCodeException invalidResponseCodeException = + (InvalidResponseCodeException) exception; + return invalidResponseCodeException.responseCode == 403 // HTTP 403 Forbidden. + || invalidResponseCodeException.responseCode == 404 // HTTP 404 Not Found. + || invalidResponseCodeException.responseCode == 410 // HTTP 410 Gone. + || invalidResponseCodeException.responseCode == 416 // HTTP 416 Range Not Satisfiable. + || invalidResponseCodeException.responseCode == 500 // HTTP 500 Internal Server Error. + || invalidResponseCodeException.responseCode == 503; // HTTP 503 Service Unavailable. + } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/DummyDataSource.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/DummyDataSource.java index 5303e7f6eb7..5f9860f2b58 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/DummyDataSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/DummyDataSource.java @@ -40,7 +40,7 @@ public long open(DataSpec dataSpec) throws IOException { } @Override - public int read(byte[] buffer, int offset, int readLength) { + public int read(byte[] buffer, int offset, int length) { throw new UnsupportedOperationException(); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/FileDataSource.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/FileDataSource.java index 7fba170f365..85284ee2202 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/FileDataSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/FileDataSource.java @@ -19,10 +19,16 @@ import static java.lang.Math.min; import android.net.Uri; +import android.system.ErrnoException; +import android.system.OsConstants; import android.text.TextUtils; +import androidx.annotation.DoNotInline; import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.util.Assertions; +import com.google.android.exoplayer2.util.Util; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; @@ -31,14 +37,31 @@ public final class FileDataSource extends BaseDataSource { /** Thrown when a {@link FileDataSource} encounters an error reading a file. */ - public static class FileDataSourceException extends IOException { + public static class FileDataSourceException extends DataSourceException { - public FileDataSourceException(IOException cause) { - super(cause); + /** @deprecated Use {@link #FileDataSourceException(Throwable, int)} */ + @Deprecated + public FileDataSourceException(Exception cause) { + super(cause, PlaybackException.ERROR_CODE_IO_UNSPECIFIED); } + /** @deprecated Use {@link #FileDataSourceException(String, Throwable, int)} */ + @Deprecated public FileDataSourceException(String message, IOException cause) { - super(message, cause); + super(message, cause, PlaybackException.ERROR_CODE_IO_UNSPECIFIED); + } + + /** Creates a {@code FileDataSourceException}. */ + public FileDataSourceException(Throwable cause, @PlaybackException.ErrorCode int errorCode) { + super(cause, errorCode); + } + + /** Creates a {@code FileDataSourceException}. */ + public FileDataSourceException( + @Nullable String message, + @Nullable Throwable cause, + @PlaybackException.ErrorCode int errorCode) { + super(message, cause, errorCode); } } @@ -79,21 +102,22 @@ public FileDataSource() { @Override public long open(DataSpec dataSpec) throws FileDataSourceException { + Uri uri = dataSpec.uri; + this.uri = uri; + transferInitializing(dataSpec); + this.file = openLocalFile(uri); try { - Uri uri = dataSpec.uri; - this.uri = uri; - - transferInitializing(dataSpec); - - this.file = openLocalFile(uri); file.seek(dataSpec.position); - bytesRemaining = dataSpec.length == C.LENGTH_UNSET ? file.length() - dataSpec.position - : dataSpec.length; - if (bytesRemaining < 0) { - throw new DataSourceException(DataSourceException.POSITION_OUT_OF_RANGE); - } + bytesRemaining = + dataSpec.length == C.LENGTH_UNSET ? file.length() - dataSpec.position : dataSpec.length; } catch (IOException e) { - throw new FileDataSourceException(e); + throw new FileDataSourceException(e, PlaybackException.ERROR_CODE_IO_UNSPECIFIED); + } + if (bytesRemaining < 0) { + throw new FileDataSourceException( + /* message= */ null, + /* cause= */ null, + PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE); } opened = true; @@ -103,17 +127,17 @@ public long open(DataSpec dataSpec) throws FileDataSourceException { } @Override - public int read(byte[] buffer, int offset, int readLength) throws FileDataSourceException { - if (readLength == 0) { + public int read(byte[] buffer, int offset, int length) throws FileDataSourceException { + if (length == 0) { return 0; } else if (bytesRemaining == 0) { return C.RESULT_END_OF_INPUT; } else { int bytesRead; try { - bytesRead = castNonNull(file).read(buffer, offset, (int) min(bytesRemaining, readLength)); + bytesRead = castNonNull(file).read(buffer, offset, (int) min(bytesRemaining, length)); } catch (IOException e) { - throw new FileDataSourceException(e); + throw new FileDataSourceException(e, PlaybackException.ERROR_CODE_IO_UNSPECIFIED); } if (bytesRead > 0) { @@ -139,7 +163,7 @@ public void close() throws FileDataSourceException { file.close(); } } catch (IOException e) { - throw new FileDataSourceException(e); + throw new FileDataSourceException(e, PlaybackException.ERROR_CODE_IO_UNSPECIFIED); } finally { file = null; if (opened) { @@ -160,9 +184,29 @@ private static RandomAccessFile openLocalFile(Uri uri) throws FileDataSourceExce + " on a string containing '?' or '#'? Use Uri.fromFile(new File(path)) to" + " avoid this. path=%s,query=%s,fragment=%s", uri.getPath(), uri.getQuery(), uri.getFragment()), - e); + e, + PlaybackException.ERROR_CODE_FAILED_RUNTIME_CHECK); } - throw new FileDataSourceException(e); + + // TODO(internal b/193503588): Add tests to ensure the correct error codes are assigned under + // different SDK versions. + throw new FileDataSourceException( + e, + Util.SDK_INT >= 21 && PlatformOperationsWrapperV21.isPermissionError(e.getCause()) + ? PlaybackException.ERROR_CODE_IO_NO_PERMISSION + : PlaybackException.ERROR_CODE_IO_FILE_NOT_FOUND); + } catch (SecurityException e) { + throw new FileDataSourceException(e, PlaybackException.ERROR_CODE_IO_NO_PERMISSION); + } catch (RuntimeException e) { + throw new FileDataSourceException(e, PlaybackException.ERROR_CODE_IO_UNSPECIFIED); + } + } + + @RequiresApi(21) + private static final class PlatformOperationsWrapperV21 { + @DoNotInline + private static boolean isPermissionError(@Nullable Throwable e) { + return e instanceof ErrnoException && ((ErrnoException) e).errno == OsConstants.EACCES; } } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/LoadErrorHandlingPolicy.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/LoadErrorHandlingPolicy.java index 0102ea78713..0815f9ed5f6 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/LoadErrorHandlingPolicy.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/LoadErrorHandlingPolicy.java @@ -15,29 +15,57 @@ */ package com.google.android.exoplayer2.upstream; +import static com.google.android.exoplayer2.util.Assertions.checkArgument; + +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.source.LoadEventInfo; import com.google.android.exoplayer2.source.MediaLoadData; import com.google.android.exoplayer2.upstream.Loader.Callback; import com.google.android.exoplayer2.upstream.Loader.Loadable; import java.io.IOException; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; /** - * Defines how errors encountered by loaders are handled. + * A policy that defines how load errors are handled. * - *

    A loader that can choose between one of a number of resources can exclude a resource when a - * load error occurs. In this case, {@link #getBlacklistDurationMsFor(int, long, IOException, int)} - * defines whether the resource should be excluded. Exclusion will succeed unless all of the - * alternatives are already excluded. + *

    Some loaders are able to choose between a number of alternate resources. Such loaders will + * call {@link #getFallbackSelectionFor(FallbackOptions, LoadErrorInfo)} when a load error occurs. + * The {@link FallbackSelection} returned by the policy defines whether the loader should fall back + * to using another resource, and if so the duration for which the failing resource should be + * excluded. * - *

    When exclusion does not take place, {@link #getRetryDelayMsFor(int, long, IOException, int)} - * defines whether the load is retried. An error that's not retried will always be propagated. An - * error that is retried will be propagated according to {@link #getMinimumLoadableRetryCount(int)}. + *

    When fallback does not take place, a loader will call {@link + * #getRetryDelayMsFor(LoadErrorInfo)}. The value returned by the policy defines whether the failed + * load can be retried, and if so the duration to wait before retrying. If the policy indicates that + * a load error should not be retried, it will be considered fatal by the loader. The loader may + * also consider load errors that can be retried fatal if at least {@link + * #getMinimumLoadableRetryCount(int)} retries have been attempted. * *

    Methods are invoked on the playback thread. */ public interface LoadErrorHandlingPolicy { + /** Fallback type. One of {@link #FALLBACK_TYPE_LOCATION} or {@link #FALLBACK_TYPE_TRACK}. */ + @Documented + @Retention(RetentionPolicy.SOURCE) + @IntDef({FALLBACK_TYPE_LOCATION, FALLBACK_TYPE_TRACK}) + @interface FallbackType {} + + /** + * Fallback to the same resource at a different location (i.e., a different URL through which the + * exact same data can be requested). + */ + int FALLBACK_TYPE_LOCATION = 1; + /** + * Fallback to a different track (i.e., a different representation of the same content; for + * example the same video encoded at a different bitrate or resolution). + */ + int FALLBACK_TYPE_TRACK = 2; + /** Holds information about a load task error. */ final class LoadErrorInfo { @@ -63,57 +91,87 @@ public LoadErrorInfo( } } - /** @deprecated Implement {@link #getBlacklistDurationMsFor(LoadErrorInfo)} instead. */ - @Deprecated - default long getBlacklistDurationMsFor( - int dataType, long loadDurationMs, IOException exception, int errorCount) { - throw new UnsupportedOperationException(); + /** Holds information about the available fallback options. */ + final class FallbackOptions { + /** The number of available locations. */ + public final int numberOfLocations; + /** The number of locations that are already excluded. */ + public final int numberOfExcludedLocations; + /** The number of tracks. */ + public final int numberOfTracks; + /** The number of tracks that are already excluded. */ + public final int numberOfExcludedTracks; + + /** Creates an instance. */ + public FallbackOptions( + int numberOfLocations, + int numberOfExcludedLocations, + int numberOfTracks, + int numberOfExcludedTracks) { + this.numberOfLocations = numberOfLocations; + this.numberOfExcludedLocations = numberOfExcludedLocations; + this.numberOfTracks = numberOfTracks; + this.numberOfExcludedTracks = numberOfExcludedTracks; + } + + /** Returns whether a fallback is available for the given {@link FallbackType fallback type}. */ + public boolean isFallbackAvailable(@FallbackType int type) { + return type == FALLBACK_TYPE_LOCATION + ? numberOfLocations - numberOfExcludedLocations > 1 + : numberOfTracks - numberOfExcludedTracks > 1; + } + } + + /** A selected fallback option. */ + final class FallbackSelection { + /** The type of fallback. */ + @FallbackType public final int type; + /** The duration for which the failing resource should be excluded, in milliseconds. */ + public final long exclusionDurationMs; + + /** + * Creates an instance. + * + * @param type The type of fallback. + * @param exclusionDurationMs The duration for which the failing resource should be excluded, in + * milliseconds. Must be non-negative. + */ + public FallbackSelection(@FallbackType int type, long exclusionDurationMs) { + checkArgument(exclusionDurationMs >= 0); + this.type = type; + this.exclusionDurationMs = exclusionDurationMs; + } } /** - * Returns the number of milliseconds for which a resource associated to a provided load error - * should be excluded, or {@link C#TIME_UNSET} if the resource should not be excluded. + * Returns whether a loader should fall back to using another resource on encountering an error, + * and if so the duration for which the failing resource should be excluded. * + *

    If the returned {@link FallbackSelection#type fallback type} was not {@link + * FallbackOptions#isFallbackAvailable(int) advertised as available}, then the loader will not + * fall back. + * + * @param fallbackOptions The available fallback options. * @param loadErrorInfo A {@link LoadErrorInfo} holding information about the load error. - * @return The exclusion duration in milliseconds, or {@link C#TIME_UNSET} if the resource should - * not be excluded. + * @return The selected fallback, or {@code null} if the calling loader should not fall back. */ - @SuppressWarnings("deprecation") - default long getBlacklistDurationMsFor(LoadErrorInfo loadErrorInfo) { - return getBlacklistDurationMsFor( - loadErrorInfo.mediaLoadData.dataType, - loadErrorInfo.loadEventInfo.loadDurationMs, - loadErrorInfo.exception, - loadErrorInfo.errorCount); - } - - /** @deprecated Implement {@link #getRetryDelayMsFor(LoadErrorInfo)} instead. */ - @Deprecated - default long getRetryDelayMsFor( - int dataType, long loadDurationMs, IOException exception, int errorCount) { - throw new UnsupportedOperationException(); - } + @Nullable + FallbackSelection getFallbackSelectionFor( + FallbackOptions fallbackOptions, LoadErrorInfo loadErrorInfo); /** - * Returns the number of milliseconds to wait before attempting the load again, or {@link - * C#TIME_UNSET} if the error is fatal and should not be retried. + * Returns whether a loader can retry on encountering an error, and if so the duration to wait + * before retrying. A return value of {@link C#TIME_UNSET} indicates that the error is fatal and + * should not be retried. * - *

    Loaders may ignore the retry delay returned by this method in order to wait for a specific - * event before retrying. However, the load is retried if and only if this method does not return - * {@link C#TIME_UNSET}. + *

    For loads that can be retried, loaders may ignore the retry delay returned by this method in + * order to wait for a specific event before retrying. * * @param loadErrorInfo A {@link LoadErrorInfo} holding information about the load error. - * @return The number of milliseconds to wait before attempting the load again, or {@link - * C#TIME_UNSET} if the error is fatal and should not be retried. + * @return The duration to wait before retrying in milliseconds, or {@link C#TIME_UNSET} if the + * error is fatal and should not be retried. */ - @SuppressWarnings("deprecation") - default long getRetryDelayMsFor(LoadErrorInfo loadErrorInfo) { - return getRetryDelayMsFor( - loadErrorInfo.mediaLoadData.dataType, - loadErrorInfo.loadEventInfo.loadDurationMs, - loadErrorInfo.exception, - loadErrorInfo.errorCount); - } + long getRetryDelayMsFor(LoadErrorInfo loadErrorInfo); /** * Called once {@code loadTaskId} will not be associated with any more load errors. @@ -124,13 +182,13 @@ default long getRetryDelayMsFor(LoadErrorInfo loadErrorInfo) { default void onLoadTaskConcluded(long loadTaskId) {} /** - * Returns the minimum number of times to retry a load in the case of a load error, before - * propagating the error. + * Returns the minimum number of times to retry a load before a load error that can be retried may + * be considered fatal. * - * @param dataType One of the {@link C C.DATA_TYPE_*} constants indicating the type of data to - * load. - * @return The minimum number of times to retry a load in the case of a load error, before - * propagating the error. + * @param dataType One of the {@link C C.DATA_TYPE_*} constants indicating the type of data being + * loaded. + * @return The minimum number of times to retry a load before a load error that can be retried may + * be considered fatal. * @see Loader#startLoading(Loadable, Callback, int) */ int getMinimumLoadableRetryCount(int dataType); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/Loader.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/Loader.java index d731455e516..8c9d9caff14 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/Loader.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/Loader.java @@ -39,20 +39,15 @@ /** Manages the background loading of {@link Loadable}s. */ public final class Loader implements LoaderErrorThrower { - /** - * Thrown when an unexpected exception or error is encountered during loading. - */ + /** Thrown when an unexpected exception or error is encountered during loading. */ public static final class UnexpectedLoaderException extends IOException { public UnexpectedLoaderException(Throwable cause) { super("Unexpected " + cause.getClass().getSimpleName() + ": " + cause.getMessage(), cause); } - } - /** - * An object that can be loaded using a {@link Loader}. - */ + /** An object that can be loaded using a {@link Loader}. */ public interface Loadable { /** @@ -83,9 +78,7 @@ public interface Loadable { void load() throws IOException; } - /** - * A callback to be notified of {@link Loader} events. - */ + /** A callback to be notified of {@link Loader} events. */ public interface Callback { /** @@ -138,16 +131,11 @@ LoadErrorAction onLoadError( T loadable, long elapsedRealtimeMs, long loadDurationMs, IOException error, int errorCount); } - /** - * A callback to be notified when a {@link Loader} has finished being released. - */ + /** A callback to be notified when a {@link Loader} has finished being released. */ public interface ReleaseCallback { - /** - * Called when the {@link Loader} has finished being released. - */ + /** Called when the {@link Loader} has finished being released. */ void onLoaderReleased(); - } private static final String THREAD_NAME_PREFIX = "ExoPlayer:Loader:"; @@ -314,8 +302,8 @@ public void maybeThrowError(int minRetryCount) throws IOException { if (fatalError != null) { throw fatalError; } else if (currentTask != null) { - currentTask.maybeThrowError(minRetryCount == Integer.MIN_VALUE - ? currentTask.defaultMinRetryCount : minRetryCount); + currentTask.maybeThrowError( + minRetryCount == Integer.MIN_VALUE ? currentTask.defaultMinRetryCount : minRetryCount); } } @@ -344,8 +332,12 @@ private final class LoadTask extends Handler implements Runn private boolean canceled; private volatile boolean released; - public LoadTask(Looper looper, T loadable, Loader.Callback callback, - int defaultMinRetryCount, long startTimeMs) { + public LoadTask( + Looper looper, + T loadable, + Loader.Callback callback, + int defaultMinRetryCount, + long startTimeMs) { super(looper); this.loadable = loadable; this.callback = callback; @@ -522,7 +514,6 @@ private void finish() { private long getRetryDelayMillis() { return min((errorCount - 1) * 1000, 5000); } - } private static final class ReleaseTask implements Runnable { @@ -537,7 +528,5 @@ public ReleaseTask(ReleaseCallback callback) { public void run() { callback.onLoaderReleased(); } - } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/LoaderErrorThrower.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/LoaderErrorThrower.java index 64d5938c89b..eea3da8556b 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/LoaderErrorThrower.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/LoaderErrorThrower.java @@ -32,8 +32,8 @@ public interface LoaderErrorThrower { /** * Throws a fatal error, or a non-fatal error if loading is currently backed off and the current - * {@link Loadable} has incurred a number of errors greater than the specified minimum number - * of retries. Else does nothing. + * {@link Loadable} has incurred a number of errors greater than the specified minimum number of + * retries. Else does nothing. * * @param minRetryCount A minimum retry count that must be exceeded for a non-fatal error to be * thrown. Should be non-negative. @@ -41,9 +41,7 @@ public interface LoaderErrorThrower { */ void maybeThrowError(int minRetryCount) throws IOException; - /** - * A {@link LoaderErrorThrower} that never throws. - */ + /** A {@link LoaderErrorThrower} that never throws. */ final class Dummy implements LoaderErrorThrower { @Override @@ -56,5 +54,4 @@ public void maybeThrowError(int minRetryCount) { // Do nothing. } } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/ParsingLoadable.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/ParsingLoadable.java index c9701ed9c91..0296e093c1a 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/ParsingLoadable.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/ParsingLoadable.java @@ -35,9 +35,7 @@ */ public final class ParsingLoadable implements Loadable { - /** - * Parses an object from loaded data. - */ + /** Parses an object from loaded data. */ public interface Parser { /** @@ -50,7 +48,6 @@ public interface Parser { * @throws IOException If an error occurs reading data from the stream. */ T parse(Uri uri, InputStream inputStream) throws IOException; - } /** @@ -123,8 +120,8 @@ public ParsingLoadable(DataSource dataSource, Uri uri, int type, Parser parser) { + public ParsingLoadable( + DataSource dataSource, DataSpec dataSpec, int type, Parser parser) { this.dataSource = new StatsDataSource(dataSource); this.dataSpec = dataSpec; this.type = type; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/PriorityDataSource.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/PriorityDataSource.java index 2f0d2443077..33e57ee2d15 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/PriorityDataSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/PriorityDataSource.java @@ -47,8 +47,8 @@ public final class PriorityDataSource implements DataSource { * @param priorityTaskManager The priority manager to which the task is registered. * @param priority The priority of the task. */ - public PriorityDataSource(DataSource upstream, PriorityTaskManager priorityTaskManager, - int priority) { + public PriorityDataSource( + DataSource upstream, PriorityTaskManager priorityTaskManager, int priority) { this.upstream = Assertions.checkNotNull(upstream); this.priorityTaskManager = Assertions.checkNotNull(priorityTaskManager); this.priority = priority; @@ -67,9 +67,9 @@ public long open(DataSpec dataSpec) throws IOException { } @Override - public int read(byte[] buffer, int offset, int max) throws IOException { + public int read(byte[] buffer, int offset, int length) throws IOException { priorityTaskManager.proceedOrThrow(priority); - return upstream.read(buffer, offset, max); + return upstream.read(buffer, offset, length); } @Override @@ -87,5 +87,4 @@ public Map> getResponseHeaders() { public void close() throws IOException { upstream.close(); } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/PriorityDataSourceFactory.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/PriorityDataSourceFactory.java index cec2c9a79da..8f614803002 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/PriorityDataSourceFactory.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/PriorityDataSourceFactory.java @@ -31,8 +31,8 @@ public final class PriorityDataSourceFactory implements Factory { * @param priorityTaskManager The priority manager to which PriorityDataSource task is registered. * @param priority The priority of PriorityDataSource task. */ - public PriorityDataSourceFactory(Factory upstreamFactory, PriorityTaskManager priorityTaskManager, - int priority) { + public PriorityDataSourceFactory( + Factory upstreamFactory, PriorityTaskManager priorityTaskManager, int priority) { this.upstreamFactory = upstreamFactory; this.priorityTaskManager = priorityTaskManager; this.priority = priority; @@ -40,8 +40,7 @@ public PriorityDataSourceFactory(Factory upstreamFactory, PriorityTaskManager pr @Override public PriorityDataSource createDataSource() { - return new PriorityDataSource(upstreamFactory.createDataSource(), priorityTaskManager, - priority); + return new PriorityDataSource( + upstreamFactory.createDataSource(), priorityTaskManager, priority); } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/RawResourceDataSource.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/RawResourceDataSource.java index ccdf7975a6f..d896acef2fd 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/RawResourceDataSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/RawResourceDataSource.java @@ -26,6 +26,7 @@ import android.text.TextUtils; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.util.Assertions; import java.io.EOFException; import java.io.FileInputStream; @@ -53,16 +54,26 @@ */ public final class RawResourceDataSource extends BaseDataSource { - /** - * Thrown when an {@link IOException} is encountered reading from a raw resource. - */ - public static class RawResourceDataSourceException extends IOException { + /** Thrown when an {@link IOException} is encountered reading from a raw resource. */ + public static class RawResourceDataSourceException extends DataSourceException { + /** @deprecated Use {@link #RawResourceDataSourceException(String, Throwable, int)}. */ + @Deprecated public RawResourceDataSourceException(String message) { - super(message); + super(message, /* cause= */ null, PlaybackException.ERROR_CODE_IO_UNSPECIFIED); + } + + /** @deprecated Use {@link #RawResourceDataSourceException(String, Throwable, int)}. */ + @Deprecated + public RawResourceDataSourceException(Throwable cause) { + super(cause, PlaybackException.ERROR_CODE_IO_UNSPECIFIED); } - public RawResourceDataSourceException(Throwable e) { - super(e); + /** Creates a new instance. */ + public RawResourceDataSourceException( + @Nullable String message, + @Nullable Throwable cause, + @PlaybackException.ErrorCode int errorCode) { + super(message, cause, errorCode); } } @@ -88,9 +99,7 @@ public static Uri buildRawResourceUri(int rawResourceId) { private long bytesRemaining; private boolean opened; - /** - * @param context A context. - */ + /** @param context A context. */ public RawResourceDataSource(Context context) { super(/* isNetwork= */ false); this.resources = context.getResources(); @@ -110,7 +119,10 @@ public long open(DataSpec dataSpec) throws RawResourceDataSourceException { try { resourceId = Integer.parseInt(Assertions.checkNotNull(uri.getLastPathSegment())); } catch (NumberFormatException e) { - throw new RawResourceDataSourceException("Resource identifier must be an integer."); + throw new RawResourceDataSourceException( + "Resource identifier must be an integer.", + /* cause= */ null, + PlaybackException.ERROR_CODE_FAILED_RUNTIME_CHECK); } } else if (TextUtils.equals(ContentResolver.SCHEME_ANDROID_RESOURCE, uri.getScheme())) { String path = Assertions.checkNotNull(uri.getPath()); @@ -123,14 +135,19 @@ public long open(DataSpec dataSpec) throws RawResourceDataSourceException { resources.getIdentifier( resourceName, /* defType= */ "raw", /* defPackage= */ packageName); if (resourceId == 0) { - throw new RawResourceDataSourceException("Resource not found."); + throw new RawResourceDataSourceException( + "Resource not found.", + /* cause= */ null, + PlaybackException.ERROR_CODE_IO_FILE_NOT_FOUND); } } else { throw new RawResourceDataSourceException( "URI must either use scheme " + RAW_RESOURCE_SCHEME + " or " - + ContentResolver.SCHEME_ANDROID_RESOURCE); + + ContentResolver.SCHEME_ANDROID_RESOURCE, + /* cause= */ null, + PlaybackException.ERROR_CODE_FAILED_RUNTIME_CHECK); } transferInitializing(dataSpec); @@ -139,12 +156,16 @@ public long open(DataSpec dataSpec) throws RawResourceDataSourceException { try { assetFileDescriptor = resources.openRawResourceFd(resourceId); } catch (Resources.NotFoundException e) { - throw new RawResourceDataSourceException(e); + throw new RawResourceDataSourceException( + /* message= */ null, e, PlaybackException.ERROR_CODE_IO_FILE_NOT_FOUND); } this.assetFileDescriptor = assetFileDescriptor; if (assetFileDescriptor == null) { - throw new RawResourceDataSourceException("Resource is compressed: " + uri); + throw new RawResourceDataSourceException( + "Resource is compressed: " + uri, + /* cause= */ null, + PlaybackException.ERROR_CODE_IO_UNSPECIFIED); } long assetFileDescriptorLength = assetFileDescriptor.getLength(); @@ -160,7 +181,10 @@ public long open(DataSpec dataSpec) throws RawResourceDataSourceException { // extends to the end of the file. if (assetFileDescriptorLength != AssetFileDescriptor.UNKNOWN_LENGTH && dataSpec.position > assetFileDescriptorLength) { - throw new DataSourceException(DataSourceException.POSITION_OUT_OF_RANGE); + throw new RawResourceDataSourceException( + /* message= */ null, + /* cause= */ null, + PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE); } long assetFileDescriptorOffset = assetFileDescriptor.getStartOffset(); long skipped = @@ -169,7 +193,10 @@ public long open(DataSpec dataSpec) throws RawResourceDataSourceException { if (skipped != dataSpec.position) { // We expect the skip to be satisfied in full. If it isn't then we're probably trying to // read beyond the end of the last resource in the file. - throw new DataSourceException(DataSourceException.POSITION_OUT_OF_RANGE); + throw new RawResourceDataSourceException( + /* message= */ null, + /* cause= */ null, + PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE); } if (assetFileDescriptorLength == AssetFileDescriptor.UNKNOWN_LENGTH) { // The asset must extend to the end of the file. We can try and resolve the length with @@ -181,17 +208,23 @@ public long open(DataSpec dataSpec) throws RawResourceDataSourceException { bytesRemaining = channel.size() - channel.position(); if (bytesRemaining < 0) { // The skip above was satisfied in full, but skipped beyond the end of the file. - throw new DataSourceException(DataSourceException.POSITION_OUT_OF_RANGE); + throw new RawResourceDataSourceException( + /* message= */ null, + /* cause= */ null, + PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE); } } } else { bytesRemaining = assetFileDescriptorLength - skipped; if (bytesRemaining < 0) { - throw new DataSourceException(DataSourceException.POSITION_OUT_OF_RANGE); + throw new DataSourceException(PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE); } } + } catch (RawResourceDataSourceException e) { + throw e; } catch (IOException e) { - throw new RawResourceDataSourceException(e); + throw new RawResourceDataSourceException( + /* message= */ null, e, PlaybackException.ERROR_CODE_IO_UNSPECIFIED); } if (dataSpec.length != C.LENGTH_UNSET) { @@ -204,8 +237,8 @@ public long open(DataSpec dataSpec) throws RawResourceDataSourceException { } @Override - public int read(byte[] buffer, int offset, int readLength) throws RawResourceDataSourceException { - if (readLength == 0) { + public int read(byte[] buffer, int offset, int length) throws RawResourceDataSourceException { + if (length == 0) { return 0; } else if (bytesRemaining == 0) { return C.RESULT_END_OF_INPUT; @@ -214,16 +247,20 @@ public int read(byte[] buffer, int offset, int readLength) throws RawResourceDat int bytesRead; try { int bytesToRead = - bytesRemaining == C.LENGTH_UNSET ? readLength : (int) min(bytesRemaining, readLength); + bytesRemaining == C.LENGTH_UNSET ? length : (int) min(bytesRemaining, length); bytesRead = castNonNull(inputStream).read(buffer, offset, bytesToRead); } catch (IOException e) { - throw new RawResourceDataSourceException(e); + throw new RawResourceDataSourceException( + /* message= */ null, e, PlaybackException.ERROR_CODE_IO_UNSPECIFIED); } if (bytesRead == -1) { if (bytesRemaining != C.LENGTH_UNSET) { // End of stream reached having not read sufficient data. - throw new RawResourceDataSourceException(new EOFException()); + throw new RawResourceDataSourceException( + "End of stream reached having not read sufficient data.", + new EOFException(), + PlaybackException.ERROR_CODE_IO_UNSPECIFIED); } return C.RESULT_END_OF_INPUT; } @@ -249,7 +286,8 @@ public void close() throws RawResourceDataSourceException { inputStream.close(); } } catch (IOException e) { - throw new RawResourceDataSourceException(e); + throw new RawResourceDataSourceException( + /* message= */ null, e, PlaybackException.ERROR_CODE_IO_UNSPECIFIED); } finally { inputStream = null; try { @@ -257,7 +295,8 @@ public void close() throws RawResourceDataSourceException { assetFileDescriptor.close(); } } catch (IOException e) { - throw new RawResourceDataSourceException(e); + throw new RawResourceDataSourceException( + /* message= */ null, e, PlaybackException.ERROR_CODE_IO_UNSPECIFIED); } finally { assetFileDescriptor = null; if (opened) { @@ -267,5 +306,4 @@ public void close() throws RawResourceDataSourceException { } } } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/ResolvingDataSource.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/ResolvingDataSource.java index 958780cbc33..56301245e60 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/ResolvingDataSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/ResolvingDataSource.java @@ -109,8 +109,8 @@ public long open(DataSpec dataSpec) throws IOException { } @Override - public int read(byte[] buffer, int offset, int readLength) throws IOException { - return upstreamDataSource.read(buffer, offset, readLength); + public int read(byte[] buffer, int offset, int length) throws IOException { + return upstreamDataSource.read(buffer, offset, length); } @Override diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/StatsDataSource.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/StatsDataSource.java index 4340169f451..325865b26a7 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/StatsDataSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/StatsDataSource.java @@ -88,8 +88,8 @@ public long open(DataSpec dataSpec) throws IOException { } @Override - public int read(byte[] buffer, int offset, int readLength) throws IOException { - int bytesRead = dataSource.read(buffer, offset, readLength); + public int read(byte[] buffer, int offset, int length) throws IOException { + int bytesRead = dataSource.read(buffer, offset, length); if (bytesRead != C.RESULT_END_OF_INPUT) { this.bytesRead += bytesRead; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/TeeDataSource.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/TeeDataSource.java index 3ece5c16175..53e99cc3466 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/TeeDataSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/TeeDataSource.java @@ -63,11 +63,11 @@ public long open(DataSpec dataSpec) throws IOException { } @Override - public int read(byte[] buffer, int offset, int max) throws IOException { + public int read(byte[] buffer, int offset, int length) throws IOException { if (bytesRemaining == 0) { return C.RESULT_END_OF_INPUT; } - int bytesRead = upstream.read(buffer, offset, max); + int bytesRead = upstream.read(buffer, offset, length); if (bytesRead > 0) { // TODO: Consider continuing even if writes to the sink fail. dataSink.write(buffer, offset, bytesRead); @@ -100,5 +100,4 @@ public void close() throws IOException { } } } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/UdpDataSource.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/UdpDataSource.java index 2da837e788f..df0ff1f1cc9 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/UdpDataSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/UdpDataSource.java @@ -20,22 +20,30 @@ import android.net.Uri; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.PlaybackException; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.MulticastSocket; -import java.net.SocketException; +import java.net.SocketTimeoutException; /** A UDP {@link DataSource}. */ public final class UdpDataSource extends BaseDataSource { /** Thrown when an error is encountered when trying to read from a {@link UdpDataSource}. */ - public static final class UdpDataSourceException extends IOException { - - public UdpDataSourceException(IOException cause) { - super(cause); + public static final class UdpDataSourceException extends DataSourceException { + + /** + * Creates a {@code UdpDataSourceException}. + * + * @param cause The error cause. + * @param errorCode Reason of the error, should be one of the {@code ERROR_CODE_IO_*} in {@link + * PlaybackException.ErrorCode}. + */ + public UdpDataSourceException(Throwable cause, @PlaybackException.ErrorCode int errorCode) { + super(cause, errorCode); } } @@ -103,14 +111,12 @@ public long open(DataSpec dataSpec) throws UdpDataSourceException { } else { socket = new DatagramSocket(socketAddress); } - } catch (IOException e) { - throw new UdpDataSourceException(e); - } - - try { socket.setSoTimeout(socketTimeoutMillis); - } catch (SocketException e) { - throw new UdpDataSourceException(e); + } catch (SecurityException e) { + throw new UdpDataSourceException(e, PlaybackException.ERROR_CODE_IO_NO_PERMISSION); + } catch (IOException e) { + throw new UdpDataSourceException( + e, PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED); } opened = true; @@ -119,8 +125,8 @@ public long open(DataSpec dataSpec) throws UdpDataSourceException { } @Override - public int read(byte[] buffer, int offset, int readLength) throws UdpDataSourceException { - if (readLength == 0) { + public int read(byte[] buffer, int offset, int length) throws UdpDataSourceException { + if (length == 0) { return 0; } @@ -128,15 +134,19 @@ public int read(byte[] buffer, int offset, int readLength) throws UdpDataSourceE // We've read all of the data from the current packet. Get another. try { socket.receive(packet); + } catch (SocketTimeoutException e) { + throw new UdpDataSourceException( + e, PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT); } catch (IOException e) { - throw new UdpDataSourceException(e); + throw new UdpDataSourceException( + e, PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED); } packetRemaining = packet.getLength(); bytesTransferred(packetRemaining); } int packetOffset = packet.getLength() - packetRemaining; - int bytesToRead = min(packetRemaining, readLength); + int bytesToRead = min(packetRemaining, length); System.arraycopy(packetBuffer, packetOffset, buffer, offset, bytesToRead); packetRemaining -= bytesToRead; return bytesToRead; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/Cache.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/Cache.java index eb782bd334f..cdce51aa1cf 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/Cache.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/Cache.java @@ -26,7 +26,7 @@ /** * A cache that supports partial caching of resources. * - *

    Terminology

    + *

    Terminology

    * *
      *
    • A resource is a complete piece of logical data, for example a complete media file. @@ -41,9 +41,7 @@ */ public interface Cache { - /** - * Listener of {@link Cache} events. - */ + /** Listener of {@link Cache} events. */ interface Listener { /** @@ -77,9 +75,7 @@ interface Listener { void onSpanTouched(Cache cache, CacheSpan oldSpan, CacheSpan newSpan); } - /** - * Thrown when an error is encountered when writing data. - */ + /** Thrown when an error is encountered when writing data. */ class CacheException extends IOException { public CacheException(String message) { @@ -152,9 +148,7 @@ public CacheException(String message, Throwable cause) { /** Returns the cache keys of all of the resources that are at least partially cached. */ Set getKeys(); - /** - * Returns the total disk space in bytes used by the cache. - */ + /** Returns the total disk space in bytes used by the cache. */ long getCacheSpace(); /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSink.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSink.java index 76a833ddb5a..7661171e4ca 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSink.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSink.java @@ -242,8 +242,8 @@ private void openNextOutputStream(DataSpec dataSpec) throws IOException { FileOutputStream underlyingFileOutputStream = new FileOutputStream(file); if (bufferSize > 0) { if (bufferedOutputStream == null) { - bufferedOutputStream = new ReusableBufferedOutputStream(underlyingFileOutputStream, - bufferSize); + bufferedOutputStream = + new ReusableBufferedOutputStream(underlyingFileOutputStream, bufferSize); } else { bufferedOutputStream.reset(underlyingFileOutputStream); } @@ -275,5 +275,4 @@ private void closeCurrentOutputStream() throws IOException { } } } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSource.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSource.java index efccb0cf78d..931cdf45526 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSource.java @@ -23,6 +23,7 @@ import androidx.annotation.IntDef; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.upstream.DataSink; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSourceException; @@ -342,9 +343,9 @@ public interface EventListener { public static final int FLAG_BLOCK_ON_CACHE = 1; /** - * A flag indicating whether the cache is bypassed following any cache related error. If set - * then cache related exceptions may be thrown for one cycle of open, read and close calls. - * Subsequent cycles of these calls will then bypass the cache. + * A flag indicating whether the cache is bypassed following any cache related error. If set then + * cache related exceptions may be thrown for one cycle of open, read and close calls. Subsequent + * cycles of these calls will then bypass the cache. */ public static final int FLAG_IGNORE_CACHE_ON_ERROR = 1 << 1; // 2 @@ -573,7 +574,8 @@ public long open(DataSpec dataSpec) throws IOException { if (bytesRemaining != C.LENGTH_UNSET) { bytesRemaining -= dataSpec.position; if (bytesRemaining < 0) { - throw new DataSourceException(DataSourceException.POSITION_OUT_OF_RANGE); + throw new DataSourceException( + PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE); } } } @@ -594,10 +596,10 @@ public long open(DataSpec dataSpec) throws IOException { } @Override - public int read(byte[] buffer, int offset, int readLength) throws IOException { + public int read(byte[] buffer, int offset, int length) throws IOException { DataSpec requestDataSpec = checkNotNull(this.requestDataSpec); DataSpec currentDataSpec = checkNotNull(this.currentDataSpec); - if (readLength == 0) { + if (length == 0) { return 0; } if (bytesRemaining == 0) { @@ -607,7 +609,7 @@ public int read(byte[] buffer, int offset, int readLength) throws IOException { if (readPosition >= checkCachePosition) { openNextSource(requestDataSpec, true); } - int bytesRead = checkNotNull(currentDataSource).read(buffer, offset, readLength); + int bytesRead = checkNotNull(currentDataSource).read(buffer, offset, length); if (bytesRead != C.RESULT_END_OF_INPUT) { if (isReadingFromCache()) { totalCachedBytesRead += bytesRead; @@ -627,7 +629,7 @@ public int read(byte[] buffer, int offset, int readLength) throws IOException { } else if (bytesRemaining > 0 || bytesRemaining == C.LENGTH_UNSET) { closeCurrentSource(); openNextSource(requestDataSpec, false); - return read(buffer, offset, readLength); + return read(buffer, offset, length); } return bytesRead; } catch (Throwable e) { @@ -863,5 +865,4 @@ private void notifyBytesRead() { totalCachedBytesRead = 0; } } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceFactory.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceFactory.java index 2c51da8a8d4..0f6159e3491 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceFactory.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceFactory.java @@ -109,5 +109,4 @@ public CacheDataSource createDataSource() { eventListener, cacheKeyFactory); } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheEvictor.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheEvictor.java index 6ebfe01df41..6e59c4ecdc8 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheEvictor.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheEvictor.java @@ -30,9 +30,7 @@ public interface CacheEvictor extends Cache.Listener { */ boolean requiresCacheSpanTouches(); - /** - * Called when cache has been initialized. - */ + /** Called when cache has been initialized. */ void onCacheInitialized(); /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheFileMetadataIndex.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheFileMetadataIndex.java index e288a5258ea..ec0ff46ac25 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheFileMetadataIndex.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheFileMetadataIndex.java @@ -15,6 +15,8 @@ */ package com.google.android.exoplayer2.upstream.cache; +import static com.google.android.exoplayer2.util.Assertions.checkNotNull; + import android.content.ContentValues; import android.database.Cursor; import android.database.SQLException; @@ -146,7 +148,7 @@ public Map getAll() throws DatabaseIOException { try (Cursor cursor = getCursor()) { Map fileMetadata = new HashMap<>(cursor.getCount()); while (cursor.moveToNext()) { - String name = cursor.getString(COLUMN_INDEX_NAME); + String name = checkNotNull(cursor.getString(COLUMN_INDEX_NAME)); long length = cursor.getLong(COLUMN_INDEX_LENGTH); long lastTouchTimestamp = cursor.getLong(COLUMN_INDEX_LAST_TOUCH_TIMESTAMP); fileMetadata.put(name, new CacheFileMetadata(length, lastTouchTimestamp)); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheSpan.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheSpan.java index cba8f350098..ceb8ee74107 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheSpan.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheSpan.java @@ -71,16 +71,12 @@ public CacheSpan( this.lastTouchTimestamp = lastTouchTimestamp; } - /** - * Returns whether this is an open-ended {@link CacheSpan}. - */ + /** Returns whether this is an open-ended {@link CacheSpan}. */ public boolean isOpenEnded() { return length == C.LENGTH_UNSET; } - /** - * Returns whether this is a hole {@link CacheSpan}. - */ + /** Returns whether this is a hole {@link CacheSpan}. */ public boolean isHoleSpan() { return !isCached; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedContentIndex.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedContentIndex.java index ce69d5a46c5..f8289809f8c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedContentIndex.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedContentIndex.java @@ -832,7 +832,7 @@ public void load( try (Cursor cursor = getCursor()) { while (cursor.moveToNext()) { int id = cursor.getInt(COLUMN_INDEX_ID); - String key = cursor.getString(COLUMN_INDEX_KEY); + String key = checkNotNull(cursor.getString(COLUMN_INDEX_KEY)); byte[] metadataBytes = cursor.getBlob(COLUMN_INDEX_METADATA); ByteArrayInputStream inputStream = new ByteArrayInputStream(metadataBytes); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedRegionTracker.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedRegionTracker.java index d26e8036d7d..3306b032ef9 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedRegionTracker.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedRegionTracker.java @@ -66,19 +66,20 @@ public void release() { } /** - * When provided with a byte offset, this method locates the cached region within which the - * offset falls, and returns the approximate end position in milliseconds of that region. If the - * byte offset does not fall within a cached region then {@link #NOT_CACHED} is returned. - * If the cached region extends to the end of the stream, {@link #CACHED_TO_END} is returned. + * When provided with a byte offset, this method locates the cached region within which the offset + * falls, and returns the approximate end position in milliseconds of that region. If the byte + * offset does not fall within a cached region then {@link #NOT_CACHED} is returned. If the cached + * region extends to the end of the stream, {@link #CACHED_TO_END} is returned. * * @param byteOffset The byte offset in the underlying stream. - * @return The end position of the corresponding cache region, {@link #NOT_CACHED}, or - * {@link #CACHED_TO_END}. + * @return The end position of the corresponding cache region, {@link #NOT_CACHED}, or {@link + * #CACHED_TO_END}. */ public synchronized int getRegionEndTimeMs(long byteOffset) { lookupRegion.startOffset = byteOffset; @Nullable Region floorRegion = regions.floor(lookupRegion); - if (floorRegion == null || byteOffset > floorRegion.endOffset + if (floorRegion == null + || byteOffset > floorRegion.endOffset || floorRegion.endOffsetIndex == -1) { return NOT_CACHED; } @@ -87,8 +88,9 @@ public synchronized int getRegionEndTimeMs(long byteOffset) { && floorRegion.endOffset == (chunkIndex.offsets[index] + chunkIndex.sizes[index])) { return CACHED_TO_END; } - long segmentFractionUs = (chunkIndex.durationsUs[index] - * (floorRegion.endOffset - chunkIndex.offsets[index])) / chunkIndex.sizes[index]; + long segmentFractionUs = + (chunkIndex.durationsUs[index] * (floorRegion.endOffset - chunkIndex.offsets[index])) + / chunkIndex.sizes[index]; return (int) ((chunkIndex.timesUs[index] + segmentFractionUs) / 1000); } @@ -174,13 +176,9 @@ private boolean regionsConnect(@Nullable Region lower, @Nullable Region upper) { private static class Region implements Comparable { - /** - * The first byte of the region (inclusive). - */ + /** The first byte of the region (inclusive). */ public long startOffset; - /** - * End offset of the region (exclusive). - */ + /** End offset of the region (exclusive). */ public long endOffset; /** * The index in chunkIndex that contains the end offset. May be -1 if the end offset comes @@ -198,7 +196,5 @@ public Region(long position, long endOffset) { public int compareTo(Region another) { return Util.compareLong(startOffset, another.startOffset); } - } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/ContentMetadataMutations.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/ContentMetadataMutations.java index f6cac589979..7f84f808438 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/ContentMetadataMutations.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/ContentMetadataMutations.java @@ -122,7 +122,7 @@ public List getRemovedValues() { return Collections.unmodifiableList(new ArrayList<>(removedValues)); } - /** Returns a map of metadata name, value pairs to be set. Values are copied. */ + /** Returns a map of metadata name, value pairs to be set. Values are copied. */ public Map getEditedValues() { HashMap hashMap = new HashMap<>(editedValues); for (Entry entry : hashMap.entrySet()) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/DefaultContentMetadata.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/DefaultContentMetadata.java index 706fa0d2c3b..4b42146e978 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/DefaultContentMetadata.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/DefaultContentMetadata.java @@ -65,8 +65,8 @@ public Set> entrySet() { @Override @Nullable - public final byte[] get(String name, @Nullable byte[] defaultValue) { - @Nullable byte[] bytes = metadata.get(name); + public final byte[] get(String key, @Nullable byte[] defaultValue) { + @Nullable byte[] bytes = metadata.get(key); if (bytes != null) { return Arrays.copyOf(bytes, bytes.length); } else { @@ -76,8 +76,8 @@ public final byte[] get(String name, @Nullable byte[] defaultValue) { @Override @Nullable - public final String get(String name, @Nullable String defaultValue) { - @Nullable byte[] bytes = metadata.get(name); + public final String get(String key, @Nullable String defaultValue) { + @Nullable byte[] bytes = metadata.get(key); if (bytes != null) { return new String(bytes, Charsets.UTF_8); } else { @@ -86,8 +86,8 @@ public final String get(String name, @Nullable String defaultValue) { } @Override - public final long get(String name, long defaultValue) { - @Nullable byte[] bytes = metadata.get(name); + public final long get(String key, long defaultValue) { + @Nullable byte[] bytes = metadata.get(key); if (bytes != null) { return ByteBuffer.wrap(bytes).getLong(); } else { @@ -96,8 +96,8 @@ public final long get(String name, long defaultValue) { } @Override - public final boolean contains(String name) { - return metadata.containsKey(name); + public final boolean contains(String key) { + return metadata.containsKey(key); } @Override @@ -168,5 +168,4 @@ private static byte[] getBytes(Object value) { throw new IllegalArgumentException(); } } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/NoOpCacheEvictor.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/NoOpCacheEvictor.java index db3cd2ef34a..a4113de0dfa 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/NoOpCacheEvictor.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/NoOpCacheEvictor.java @@ -34,7 +34,7 @@ public void onCacheInitialized() { } @Override - public void onStartFile(Cache cache, String key, long position, long maxLength) { + public void onStartFile(Cache cache, String key, long position, long length) { // Do nothing. } @@ -52,5 +52,4 @@ public void onSpanRemoved(Cache cache, CacheSpan span) { public void onSpanTouched(Cache cache, CacheSpan oldSpan, CacheSpan newSpan) { // Do nothing. } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheSpan.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheSpan.java index d02f7c0988b..c9a70761b55 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheSpan.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheSpan.java @@ -29,12 +29,12 @@ /* package */ static final String COMMON_SUFFIX = ".exo"; private static final String SUFFIX = ".v3" + COMMON_SUFFIX; - private static final Pattern CACHE_FILE_PATTERN_V1 = Pattern.compile( - "^(.+)\\.(\\d+)\\.(\\d+)\\.v1\\.exo$", Pattern.DOTALL); - private static final Pattern CACHE_FILE_PATTERN_V2 = Pattern.compile( - "^(.+)\\.(\\d+)\\.(\\d+)\\.v2\\.exo$", Pattern.DOTALL); - private static final Pattern CACHE_FILE_PATTERN_V3 = Pattern.compile( - "^(\\d+)\\.(\\d+)\\.(\\d+)\\.v3\\.exo$", Pattern.DOTALL); + private static final Pattern CACHE_FILE_PATTERN_V1 = + Pattern.compile("^(.+)\\.(\\d+)\\.(\\d+)\\.v1\\.exo$", Pattern.DOTALL); + private static final Pattern CACHE_FILE_PATTERN_V2 = + Pattern.compile("^(.+)\\.(\\d+)\\.(\\d+)\\.v2\\.exo$", Pattern.DOTALL); + private static final Pattern CACHE_FILE_PATTERN_V3 = + Pattern.compile("^(\\d+)\\.(\\d+)\\.(\\d+)\\.v3\\.exo$", Pattern.DOTALL); /** * Returns a new {@link File} instance from {@code cacheDir}, {@code id}, {@code position}, {@code @@ -203,5 +203,4 @@ public SimpleCacheSpan copyWithFileAndLastTouchTimestamp(File file, long lastTou Assertions.checkState(isCached); return new SimpleCacheSpan(key, position, length, lastTouchTimestamp, file); } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/crypto/AesCipherDataSink.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/crypto/AesCipherDataSink.java index b29c5fac700..691e496c3b1 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/crypto/AesCipherDataSink.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/crypto/AesCipherDataSink.java @@ -73,18 +73,18 @@ public void open(DataSpec dataSpec) throws IOException { } @Override - public void write(byte[] data, int offset, int length) throws IOException { + public void write(byte[] buffer, int offset, int length) throws IOException { if (scratch == null) { // In-place mode. Writes over the input data. - castNonNull(cipher).updateInPlace(data, offset, length); - wrappedDataSink.write(data, offset, length); + castNonNull(cipher).updateInPlace(buffer, offset, length); + wrappedDataSink.write(buffer, offset, length); } else { // Use scratch space. The original data remains intact. int bytesProcessed = 0; while (bytesProcessed < length) { int bytesToProcess = min(length - bytesProcessed, scratch.length); castNonNull(cipher) - .update(data, offset + bytesProcessed, bytesToProcess, scratch, /* outOffset= */ 0); + .update(buffer, offset + bytesProcessed, bytesToProcess, scratch, /* outOffset= */ 0); wrappedDataSink.write(scratch, /* offset= */ 0, bytesToProcess); bytesProcessed += bytesToProcess; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/crypto/AesCipherDataSource.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/crypto/AesCipherDataSource.java index 43a100ca69c..52352729eb7 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/crypto/AesCipherDataSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/crypto/AesCipherDataSource.java @@ -59,15 +59,15 @@ public long open(DataSpec dataSpec) throws IOException { } @Override - public int read(byte[] data, int offset, int readLength) throws IOException { - if (readLength == 0) { + public int read(byte[] buffer, int offset, int length) throws IOException { + if (length == 0) { return 0; } - int read = upstream.read(data, offset, readLength); + int read = upstream.read(buffer, offset, length); if (read == C.RESULT_END_OF_INPUT) { return C.RESULT_END_OF_INPUT; } - castNonNull(cipher).updateInPlace(data, offset, read); + castNonNull(cipher).updateInPlace(buffer, offset, read); return read; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/crypto/AesFlushingCipher.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/crypto/AesFlushingCipher.java index 6df114442be..b539d31ab98 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/crypto/AesFlushingCipher.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/crypto/AesFlushingCipher.java @@ -57,7 +57,9 @@ public AesFlushingCipher(int mode, byte[] secretKey, long nonce, long offset) { if (startPadding != 0) { updateInPlace(new byte[startPadding], 0, startPadding); } - } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException + } catch (NoSuchAlgorithmException + | NoSuchPaddingException + | InvalidKeyException | InvalidAlgorithmParameterException e) { // Should never happen. throw new RuntimeException(e); @@ -119,5 +121,4 @@ private int nonFlushingUpdate(byte[] in, int inOffset, int length, byte[] out, i private byte[] getInitializationVector(long nonce, long counter) { return ByteBuffer.allocate(16).putLong(nonce).putLong(counter).array(); } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/crypto/CryptoUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/crypto/CryptoUtil.java index 3418f46ed0e..20681ee15a7 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/crypto/CryptoUtil.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/crypto/CryptoUtil.java @@ -17,9 +17,7 @@ import androidx.annotation.Nullable; -/** - * Utility functions for the crypto package. - */ +/** Utility functions for the crypto package. */ /* package */ final class CryptoUtil { private CryptoUtil() {} @@ -42,5 +40,4 @@ public static long getFNV64Hash(@Nullable String input) { } return hash; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/AtomicFile.java b/library/core/src/main/java/com/google/android/exoplayer2/util/AtomicFile.java index fa40f0f0129..2e3b00044c9 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/AtomicFile.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/AtomicFile.java @@ -65,8 +65,8 @@ public void delete() { /** * Start a new write operation on the file. This returns an {@link OutputStream} to which you can * write the new file data. If the whole data is written successfully you must call - * {@link #endWrite(OutputStream)}. On failure you should call {@link OutputStream#close()} - * only to free up resources used by it. + * {@link #endWrite(OutputStream)}. On failure you should call {@link OutputStream#close()} only + * to free up resources used by it. * *

      Example usage: * diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/ColorParser.java b/library/core/src/main/java/com/google/android/exoplayer2/util/ColorParser.java index 6f35168d087..1200fcb70b4 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/ColorParser.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/ColorParser.java @@ -35,14 +35,14 @@ public final class ColorParser { private static final String RGB = "rgb"; private static final String RGBA = "rgba"; - private static final Pattern RGB_PATTERN = Pattern.compile( - "^rgb\\((\\d{1,3}),(\\d{1,3}),(\\d{1,3})\\)$"); + private static final Pattern RGB_PATTERN = + Pattern.compile("^rgb\\((\\d{1,3}),(\\d{1,3}),(\\d{1,3})\\)$"); - private static final Pattern RGBA_PATTERN_INT_ALPHA = Pattern.compile( - "^rgba\\((\\d{1,3}),(\\d{1,3}),(\\d{1,3}),(\\d{1,3})\\)$"); + private static final Pattern RGBA_PATTERN_INT_ALPHA = + Pattern.compile("^rgba\\((\\d{1,3}),(\\d{1,3}),(\\d{1,3}),(\\d{1,3})\\)$"); - private static final Pattern RGBA_PATTERN_FLOAT_ALPHA = Pattern.compile( - "^rgba\\((\\d{1,3}),(\\d{1,3}),(\\d{1,3}),(\\d*\\.?\\d*?)\\)$"); + private static final Pattern RGBA_PATTERN_FLOAT_ALPHA = + Pattern.compile("^rgba\\((\\d{1,3}),(\\d{1,3}),(\\d{1,3}),(\\d*\\.?\\d*?)\\)$"); private static final Map COLOR_MAP; @@ -86,8 +86,9 @@ private static int parseColorInternal(String colorExpression, boolean alphaHasFl } return color; } else if (colorExpression.startsWith(RGBA)) { - Matcher matcher = (alphaHasFloatFormat ? RGBA_PATTERN_FLOAT_ALPHA : RGBA_PATTERN_INT_ALPHA) - .matcher(colorExpression); + Matcher matcher = + (alphaHasFloatFormat ? RGBA_PATTERN_FLOAT_ALPHA : RGBA_PATTERN_INT_ALPHA) + .matcher(colorExpression); if (matcher.matches()) { return Color.argb( alphaHasFloatFormat diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/DebugTextViewHelper.java b/library/core/src/main/java/com/google/android/exoplayer2/util/DebugTextViewHelper.java index f7aac3bdae4..9c11f37fb51 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/DebugTextViewHelper.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/DebugTextViewHelper.java @@ -84,7 +84,7 @@ public final void onPlaybackStateChanged(@Player.State int playbackState) { @Override public final void onPlayWhenReadyChanged( - boolean playWhenReady, @Player.PlayWhenReadyChangeReason int playbackState) { + boolean playWhenReady, @Player.PlayWhenReadyChangeReason int reason) { updateAndPost(); } @@ -190,16 +190,23 @@ private static String getDecoderCountersBufferCountString(DecoderCounters counte return ""; } counters.ensureUpdated(); - return " sib:" + counters.skippedInputBufferCount - + " sb:" + counters.skippedOutputBufferCount - + " rb:" + counters.renderedOutputBufferCount - + " db:" + counters.droppedBufferCount - + " mcdb:" + counters.maxConsecutiveDroppedBufferCount - + " dk:" + counters.droppedToKeyframeCount; + return " sib:" + + counters.skippedInputBufferCount + + " sb:" + + counters.skippedOutputBufferCount + + " rb:" + + counters.renderedOutputBufferCount + + " db:" + + counters.droppedBufferCount + + " mcdb:" + + counters.maxConsecutiveDroppedBufferCount + + " dk:" + + counters.droppedToKeyframeCount; } private static String getPixelAspectRatioString(float pixelAspectRatio) { - return pixelAspectRatio == Format.NO_VALUE || pixelAspectRatio == 1f ? "" + return pixelAspectRatio == Format.NO_VALUE || pixelAspectRatio == 1f + ? "" : (" par:" + String.format(Locale.US, "%.02f", pixelAspectRatio)); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/EGLSurfaceTexture.java b/library/core/src/main/java/com/google/android/exoplayer2/util/EGLSurfaceTexture.java index 60bd4f0c773..b4b7ec1a960 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/EGLSurfaceTexture.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/EGLSurfaceTexture.java @@ -131,7 +131,7 @@ public void init(@SecureMode int secureMode) { } /** Releases all allocated resources. */ - @SuppressWarnings({"nullness:argument.type.incompatible"}) + @SuppressWarnings("nullness:argument") public void release() { handler.removeCallbacks(this); try { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/EventLogger.java b/library/core/src/main/java/com/google/android/exoplayer2/util/EventLogger.java index 12513f597ad..8352c3aca87 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/EventLogger.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/EventLogger.java @@ -21,9 +21,9 @@ import android.text.TextUtils; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player.PlaybackSuppressionReason; @@ -47,7 +47,6 @@ import com.google.android.exoplayer2.video.VideoSize; import java.io.IOException; import java.text.NumberFormat; -import java.util.List; import java.util.Locale; /** Logs events from {@link Player} and other core components using {@link Log}. */ @@ -57,6 +56,7 @@ public class EventLogger implements AnalyticsListener { private static final String DEFAULT_TAG = "EventLogger"; private static final int MAX_TIMELINE_ITEM_LINES = 3; private static final NumberFormat TIME_FORMAT; + static { TIME_FORMAT = NumberFormat.getInstance(Locale.US); TIME_FORMAT.setMinimumFractionDigits(2); @@ -243,13 +243,13 @@ public void onMediaItemTransition( } @Override - public void onPlayerError(EventTime eventTime, ExoPlaybackException e) { - loge(eventTime, "playerFailed", e); + public void onPlayerError(EventTime eventTime, PlaybackException error) { + loge(eventTime, "playerFailed", error); } @Override public void onTracksChanged( - EventTime eventTime, TrackGroupArray ignored, TrackSelectionArray trackSelections) { + EventTime eventTime, TrackGroupArray trackGroups, TrackSelectionArray trackSelections) { MappedTrackInfo mappedTrackInfo = trackSelector != null ? trackSelector.getCurrentMappedTrackInfo() : null; if (mappedTrackInfo == null) { @@ -333,20 +333,6 @@ public void onTracksChanged( logd("]"); } - @Override - public void onStaticMetadataChanged(EventTime eventTime, List metadataList) { - logd("staticMetadata [" + getEventTimeString(eventTime)); - for (int i = 0; i < metadataList.size(); i++) { - Metadata metadata = metadataList.get(i); - if (metadata.length() != 0) { - logd(" Metadata:" + i + " ["); - printMetadata(metadata, " "); - logd(" ]"); - } - } - logd("]"); - } - @Override public void onMetadata(EventTime eventTime, Metadata metadata) { logd("metadata [" + getEventTimeString(eventTime)); @@ -355,7 +341,7 @@ public void onMetadata(EventTime eventTime, Metadata metadata) { } @Override - public void onAudioEnabled(EventTime eventTime, DecoderCounters counters) { + public void onAudioEnabled(EventTime eventTime, DecoderCounters decoderCounters) { logd(eventTime, "audioEnabled"); } @@ -387,7 +373,7 @@ public void onAudioDecoderReleased(EventTime eventTime, String decoderName) { } @Override - public void onAudioDisabled(EventTime eventTime, DecoderCounters counters) { + public void onAudioDisabled(EventTime eventTime, DecoderCounters decoderCounters) { logd(eventTime, "audioDisabled"); } @@ -421,7 +407,7 @@ public void onVolumeChanged(EventTime eventTime, float volume) { } @Override - public void onVideoEnabled(EventTime eventTime, DecoderCounters counters) { + public void onVideoEnabled(EventTime eventTime, DecoderCounters decoderCounters) { logd(eventTime, "videoEnabled"); } @@ -438,8 +424,8 @@ public void onVideoInputFormatChanged( } @Override - public void onDroppedVideoFrames(EventTime eventTime, int count, long elapsedMs) { - logd(eventTime, "droppedFrames", Integer.toString(count)); + public void onDroppedVideoFrames(EventTime eventTime, int droppedFrames, long elapsedMs) { + logd(eventTime, "droppedFrames", Integer.toString(droppedFrames)); } @Override @@ -448,7 +434,7 @@ public void onVideoDecoderReleased(EventTime eventTime, String decoderName) { } @Override - public void onVideoDisabled(EventTime eventTime, DecoderCounters counters) { + public void onVideoDisabled(EventTime eventTime, DecoderCounters decoderCounters) { logd(eventTime, "videoDisabled"); } @@ -517,8 +503,8 @@ public void onDrmSessionAcquired(EventTime eventTime, @DrmSession.State int stat } @Override - public void onDrmSessionManagerError(EventTime eventTime, Exception e) { - printInternalError(eventTime, "drmSessionManagerError", e); + public void onDrmSessionManagerError(EventTime eventTime, Exception error) { + printInternalError(eventTime, "drmSessionManagerError", error); } @Override @@ -597,6 +583,9 @@ private String getEventString( @Nullable String eventDescription, @Nullable Throwable throwable) { String eventString = eventName + " [" + getEventTimeString(eventTime); + if (throwable instanceof PlaybackException) { + eventString += ", errorCode=" + ((PlaybackException) throwable).getErrorCodeName(); + } if (eventDescription != null) { eventString += ", " + eventDescription; } @@ -667,8 +656,10 @@ private static String getAdaptiveSupportString( @SuppressWarnings("ReferenceEquality") private static String getTrackStatusString( @Nullable TrackSelection selection, TrackGroup group, int trackIndex) { - return getTrackStatusString(selection != null && selection.getTrackGroup() == group - && selection.indexOf(trackIndex) != C.INDEX_UNSET); + return getTrackStatusString( + selection != null + && selection.getTrackGroup() == group + && selection.indexOf(trackIndex) != C.INDEX_UNSET); } private static String getTrackStatusString(boolean enabled) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/LibraryLoader.java b/library/core/src/main/java/com/google/android/exoplayer2/util/LibraryLoader.java index be8ebe2f5ce..f46f7a223b7 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/LibraryLoader.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/LibraryLoader.java @@ -26,25 +26,21 @@ public final class LibraryLoader { private boolean loadAttempted; private boolean isAvailable; - /** - * @param libraries The names of the libraries to load. - */ + /** @param libraries The names of the libraries to load. */ public LibraryLoader(String... libraries) { nativeLibraries = libraries; } /** - * Overrides the names of the libraries to load. Must be called before any call to - * {@link #isAvailable()}. + * Overrides the names of the libraries to load. Must be called before any call to {@link + * #isAvailable()}. */ public synchronized void setLibraries(String... libraries) { Assertions.checkState(!loadAttempted, "Cannot set libraries after loading"); nativeLibraries = libraries; } - /** - * Returns whether the underlying libraries are available, loading them if necessary. - */ + /** Returns whether the underlying libraries are available, loading them if necessary. */ public synchronized boolean isAvailable() { if (loadAttempted) { return isAvailable; @@ -62,5 +58,4 @@ public synchronized boolean isAvailable() { } return isAvailable; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/MediaClock.java b/library/core/src/main/java/com/google/android/exoplayer2/util/MediaClock.java index 48954cb9dfa..baa48023725 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/MediaClock.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/MediaClock.java @@ -20,9 +20,7 @@ /** Tracks the progression of media time. */ public interface MediaClock { - /** - * Returns the current media position in microseconds. - */ + /** Returns the current media position in microseconds. */ long getPositionUs(); /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/NetworkTypeObserver.java b/library/core/src/main/java/com/google/android/exoplayer2/util/NetworkTypeObserver.java index fb433961564..58501d63cc4 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/NetworkTypeObserver.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/NetworkTypeObserver.java @@ -58,6 +58,24 @@ public interface Listener { void onNetworkTypeChanged(@C.NetworkType int networkType); } + /* + * Static configuration that may need to be set at app startup time is located in a separate + * static Config class. This allows apps to set their desired config without incurring unnecessary + * class loading costs during startup. + */ + /** Configuration for {@link NetworkTypeObserver}. */ + public static final class Config { + + private static volatile boolean disable5GNsaDisambiguation; + + /** Disables logic to disambiguate 5G-NSA networks from 4G networks. */ + public static void disable5GNsaDisambiguation() { + disable5GNsaDisambiguation = true; + } + + private Config() {} + } + @Nullable private static NetworkTypeObserver staticInstance; private final Handler mainHandler; @@ -217,7 +235,9 @@ private final class Receiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { @C.NetworkType int networkType = getNetworkTypeFromConnectivityManager(context); - if (networkType == C.NETWORK_TYPE_4G && Util.SDK_INT >= 29) { + if (Util.SDK_INT >= 29 + && !Config.disable5GNsaDisambiguation + && networkType == C.NETWORK_TYPE_4G) { // Delay update of the network type to check whether this is actually 5G-NSA. try { // We can't access TelephonyManager getters like getServiceState() directly as they diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/PriorityTaskManager.java b/library/core/src/main/java/com/google/android/exoplayer2/util/PriorityTaskManager.java index 9021e262117..e380d84e35b 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/PriorityTaskManager.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/PriorityTaskManager.java @@ -31,15 +31,12 @@ */ public final class PriorityTaskManager { - /** - * Thrown when task attempts to proceed when another registered task has a higher priority. - */ + /** Thrown when task attempts to proceed when another registered task has a higher priority. */ public static class PriorityTooLowException extends IOException { public PriorityTooLowException(int priority, int highestPriority) { super("Priority too low [priority=" + priority + ", highest=" + highestPriority + "]"); } - } private final Object lock = new Object(); @@ -117,5 +114,4 @@ public void remove(int priority) { lock.notifyAll(); } } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/RunnableFutureTask.java b/library/core/src/main/java/com/google/android/exoplayer2/util/RunnableFutureTask.java index 9da5f096290..ac785295b95 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/RunnableFutureTask.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/RunnableFutureTask.java @@ -161,7 +161,7 @@ protected void cancelWork() { // The return value is guaranteed to be non-null if and only if R is a non-null type, but there's // no way to assert this. Suppress the warning instead. - @SuppressWarnings("return.type.incompatible") + @SuppressWarnings("nullness:return") @UnknownNull private R getResult() throws ExecutionException { if (canceled) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/SlidingPercentile.java b/library/core/src/main/java/com/google/android/exoplayer2/util/SlidingPercentile.java index 829f252c223..ebe5c2a5f42 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/SlidingPercentile.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/SlidingPercentile.java @@ -55,9 +55,7 @@ public class SlidingPercentile { private int totalWeight; private int recycledSampleCount; - /** - * @param maxWeight The maximum weight. - */ + /** @param maxWeight The maximum weight. */ public SlidingPercentile(int maxWeight) { this.maxWeight = maxWeight; recycledSamples = new Sample[MAX_RECYCLED_SAMPLES]; @@ -82,8 +80,8 @@ public void reset() { public void addSample(int weight, float value) { ensureSortedByIndex(); - Sample newSample = recycledSampleCount > 0 ? recycledSamples[--recycledSampleCount] - : new Sample(); + Sample newSample = + recycledSampleCount > 0 ? recycledSamples[--recycledSampleCount] : new Sample(); newSample.index = nextSampleIndex++; newSample.weight = weight; newSample.value = value; @@ -127,9 +125,7 @@ public float getPercentile(float percentile) { return samples.isEmpty() ? Float.NaN : samples.get(samples.size() - 1).value; } - /** - * Sorts the samples by index. - */ + /** Sorts the samples by index. */ private void ensureSortedByIndex() { if (currentSortOrder != SORT_ORDER_BY_INDEX) { Collections.sort(samples, INDEX_COMPARATOR); @@ -137,9 +133,7 @@ private void ensureSortedByIndex() { } } - /** - * Sorts the samples by value. - */ + /** Sorts the samples by value. */ private void ensureSortedByValue() { if (currentSortOrder != SORT_ORDER_BY_VALUE) { Collections.sort(samples, VALUE_COMPARATOR); @@ -152,7 +146,5 @@ private static class Sample { public int index; public int weight; public float value; - } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/StandaloneMediaClock.java b/library/core/src/main/java/com/google/android/exoplayer2/util/StandaloneMediaClock.java index 87970d3c003..4c4d4d114b6 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/StandaloneMediaClock.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/StandaloneMediaClock.java @@ -41,9 +41,7 @@ public StandaloneMediaClock(Clock clock) { playbackParameters = PlaybackParameters.DEFAULT; } - /** - * Starts the clock. Does nothing if the clock is already started. - */ + /** Starts the clock. Does nothing if the clock is already started. */ public void start() { if (!started) { baseElapsedMs = clock.elapsedRealtime(); @@ -51,9 +49,7 @@ public void start() { } } - /** - * Stops the clock. Does nothing if the clock is already stopped. - */ + /** Stops the clock. Does nothing if the clock is already stopped. */ public void stop() { if (started) { resetPosition(getPositionUs()); @@ -102,5 +98,4 @@ public void setPlaybackParameters(PlaybackParameters playbackParameters) { public PlaybackParameters getPlaybackParameters() { return playbackParameters; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/UriUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/util/UriUtil.java index ecc5c91ae3a..40bd4de36bc 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/UriUtil.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/UriUtil.java @@ -22,39 +22,37 @@ /** Utility methods for manipulating URIs. */ public final class UriUtil { - /** - * The length of arrays returned by {@link #getUriIndices(String)}. - */ + /** The length of arrays returned by {@link #getUriIndices(String)}. */ private static final int INDEX_COUNT = 4; /** * An index into an array returned by {@link #getUriIndices(String)}. - *

      - * The value at this position in the array is the index of the ':' after the scheme. Equals -1 if - * the URI is a relative reference (no scheme). The hier-part starts at (schemeColon + 1), + * + *

      The value at this position in the array is the index of the ':' after the scheme. Equals -1 + * if the URI is a relative reference (no scheme). The hier-part starts at (schemeColon + 1), * including when the URI has no scheme. */ private static final int SCHEME_COLON = 0; /** * An index into an array returned by {@link #getUriIndices(String)}. - *

      - * The value at this position in the array is the index of the path part. Equals (schemeColon + 1) - * if no authority part, (schemeColon + 3) if the authority part consists of just "//", and + * + *

      The value at this position in the array is the index of the path part. Equals (schemeColon + + * 1) if no authority part, (schemeColon + 3) if the authority part consists of just "//", and * (query) if no path part. The characters starting at this index can be "//" only if the * authority part is non-empty (in this case the double-slash means the first segment is empty). */ private static final int PATH = 1; /** * An index into an array returned by {@link #getUriIndices(String)}. - *

      - * The value at this position in the array is the index of the query part, including the '?' + * + *

      The value at this position in the array is the index of the query part, including the '?' * before the query. Equals fragment if no query part, and (fragment - 1) if the query part is a * single '?' with no data. */ private static final int QUERY = 2; /** * An index into an array returned by {@link #getUriIndices(String)}. - *

      - * The value at this position in the array is the index of the fragment part, including the '#' + * + *

      The value at this position in the array is the index of the fragment part, including the '#' * before the fragment. Equal to the length of the URI if no fragment part, and (length - 1) if * the fragment part is a single '#' with no data. */ @@ -142,12 +140,17 @@ public static String resolve(@Nullable String baseUri, @Nullable String referenc } } + /** Returns true if the URI is starting with a scheme component, false otherwise. */ + public static boolean isAbsolute(@Nullable String uri) { + return uri != null && getUriIndices(uri)[SCHEME_COLON] != -1; + } + /** - * Removes query parameter from an Uri, if present. + * Removes query parameter from a URI, if present. * - * @param uri The uri. + * @param uri The URI. * @param queryParameterName The name of the query parameter. - * @return The uri without the query parameter. + * @return The URI without the query parameter. */ public static Uri removeQueryParameter(Uri uri, String queryParameterName) { Uri.Builder builder = uri.buildUpon(); @@ -198,7 +201,8 @@ private static String removeDotSegments(StringBuilder uri, int offset, int limit uri.delete(segmentStart, nextSegmentStart); limit -= nextSegmentStart - segmentStart; i = segmentStart; - } else if (i == segmentStart + 2 && uri.charAt(segmentStart) == '.' + } else if (i == segmentStart + 2 + && uri.charAt(segmentStart) == '.' && uri.charAt(segmentStart + 1) == '.') { // Given "abc/def/../ghi", remove "def/../" to get "abc/ghi". int prevSegmentStart = uri.lastIndexOf("/", segmentStart - 2) + 1; @@ -254,9 +258,10 @@ private static int[] getUriIndices(String uriString) { // Determine hier-part structure: hier-part = "//" authority path / path // This block can also cope with schemeIndex == -1. - boolean hasAuthority = schemeIndex + 2 < queryIndex - && uriString.charAt(schemeIndex + 1) == '/' - && uriString.charAt(schemeIndex + 2) == '/'; + boolean hasAuthority = + schemeIndex + 2 < queryIndex + && uriString.charAt(schemeIndex + 1) == '/' + && uriString.charAt(schemeIndex + 2) == '/'; int pathIndex; if (hasAuthority) { pathIndex = uriString.indexOf('/', schemeIndex + 3); // find first '/' after "://" @@ -273,5 +278,4 @@ private static int[] getUriIndices(String uriString) { indices[FRAGMENT] = fragmentIndex; return indices; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/DecoderVideoRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/video/DecoderVideoRenderer.java index d351442192b..66283303383 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/DecoderVideoRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/DecoderVideoRenderer.java @@ -34,6 +34,7 @@ import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.FormatHolder; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.PlayerMessage.Target; import com.google.android.exoplayer2.decoder.Decoder; import com.google.android.exoplayer2.decoder.DecoderCounters; @@ -211,7 +212,7 @@ public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackEx } catch (DecoderException e) { Log.e(TAG, "Video codec error", e); eventDispatcher.videoCodecError(e); - throw createRendererException(e, inputFormat); + throw createRendererException(e, inputFormat, PlaybackException.ERROR_CODE_DECODING_FAILED); } decoderCounters.ensureUpdated(); } @@ -691,9 +692,11 @@ private void maybeInitDecoder() throws ExoPlaybackException { } catch (DecoderException e) { Log.e(TAG, "Video codec error", e); eventDispatcher.videoCodecError(e); - throw createRendererException(e, inputFormat); + throw createRendererException( + e, inputFormat, PlaybackException.ERROR_CODE_DECODER_INIT_FAILED); } catch (OutOfMemoryError e) { - throw createRendererException(e, inputFormat); + throw createRendererException( + e, inputFormat, PlaybackException.ERROR_CODE_DECODER_INIT_FAILED); } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/DummySurface.java b/library/core/src/main/java/com/google/android/exoplayer2/video/DummySurface.java index a68a64b28d2..51e23dbbba5 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/DummySurface.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/DummySurface.java @@ -41,9 +41,7 @@ public final class DummySurface extends Surface { private static final String TAG = "DummySurface"; - /** - * Whether the surface is secure. - */ + /** Whether the surface is secure. */ public final boolean secure; private static @SecureMode int secureMode; @@ -214,7 +212,5 @@ private void releaseInternal() { Assertions.checkNotNull(eglSurfaceTexture); eglSurfaceTexture.release(); } - } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java index 816f2c9da68..e1eb1da0ba3 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java @@ -97,8 +97,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { private static final String KEY_CROP_TOP = "crop-top"; // Long edge length in pixels for standard video formats, in decreasing in order. - private static final int[] STANDARD_LONG_EDGE_VIDEO_PX = new int[] { - 1920, 1600, 1440, 1280, 960, 854, 640, 540, 480}; + private static final int[] STANDARD_LONG_EDGE_VIDEO_PX = + new int[] {1920, 1600, 1440, 1280, 960, 854, 640, 540, 480}; /** * Scale factor for the initial maximum input size used to configure the codec in non-adaptive @@ -166,8 +166,8 @@ public MediaCodecVideoRenderer(Context context, MediaCodecSelector mediaCodecSel * @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer * can attempt to seamlessly join an ongoing playback. */ - public MediaCodecVideoRenderer(Context context, MediaCodecSelector mediaCodecSelector, - long allowedJoiningTimeMs) { + public MediaCodecVideoRenderer( + Context context, MediaCodecSelector mediaCodecSelector, long allowedJoiningTimeMs) { this( context, mediaCodecSelector, @@ -683,8 +683,8 @@ protected float getCodecOperatingRateV23( } @Override - protected void onCodecInitialized(String name, long initializedTimestampMs, - long initializationDurationMs) { + protected void onCodecInitialized( + String name, long initializedTimestampMs, long initializationDurationMs) { eventDispatcher.decoderInitialized(name, initializedTimestampMs, initializationDurationMs); codecNeedsSetOutputSurfaceWorkaround = codecNeedsSetOutputSurfaceWorkaround(name); codecHandlesHdr10PlusOutOfBandMetadata = @@ -1072,9 +1072,7 @@ protected void dropOutputBuffer(MediaCodecAdapter codec, int index, long present * @throws ExoPlaybackException If an error occurs flushing the codec. */ protected boolean maybeDropBuffersToKeyframe( - long positionUs, - boolean treatDroppedBuffersAsSkipped) - throws ExoPlaybackException { + long positionUs, boolean treatDroppedBuffersAsSkipped) throws ExoPlaybackException { int droppedSourceBufferCount = skipSource(positionUs); if (droppedSourceBufferCount == 0) { return false; @@ -1169,8 +1167,10 @@ private boolean shouldUseDummySurface(MediaCodecInfo codecInfo) { } private void setJoiningDeadlineMs() { - joiningDeadlineMs = allowedJoiningTimeMs > 0 - ? (SystemClock.elapsedRealtime() + allowedJoiningTimeMs) : C.TIME_UNSET; + joiningDeadlineMs = + allowedJoiningTimeMs > 0 + ? (SystemClock.elapsedRealtime() + allowedJoiningTimeMs) + : C.TIME_UNSET; } private void clearRenderedFirstFrame() { @@ -1430,8 +1430,10 @@ private static Point getCodecMaxSize(MediaCodecInfo codecInfo, Format format) { // Don't return a size not larger than the format for which the codec is being configured. return null; } else if (Util.SDK_INT >= 21) { - Point alignedSize = codecInfo.alignVideoSizeV21(isVerticalVideo ? shortEdgePx : longEdgePx, - isVerticalVideo ? longEdgePx : shortEdgePx); + Point alignedSize = + codecInfo.alignVideoSizeV21( + isVerticalVideo ? shortEdgePx : longEdgePx, + isVerticalVideo ? longEdgePx : shortEdgePx); float frameRate = format.frameRate; if (codecInfo.isVideoSizeAndRateSupportedV21(alignedSize.x, alignedSize.y, frameRate)) { return alignedSize; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/VideoDecoderGLSurfaceView.java b/library/core/src/main/java/com/google/android/exoplayer2/video/VideoDecoderGLSurfaceView.java index 06d9e412e20..f47a76760f6 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/VideoDecoderGLSurfaceView.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/VideoDecoderGLSurfaceView.java @@ -52,11 +52,7 @@ public VideoDecoderGLSurfaceView(Context context) { * @param context A {@link Context}. * @param attrs Custom attributes. */ - @SuppressWarnings({ - "nullness:assignment.type.incompatible", - "nullness:argument.type.incompatible", - "nullness:method.invocation.invalid" - }) + @SuppressWarnings({"nullness:assignment", "nullness:argument", "nullness:method.invocation"}) public VideoDecoderGLSurfaceView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); renderer = new Renderer(/* surfaceView= */ this); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/VideoDecoderOutputBuffer.java b/library/core/src/main/java/com/google/android/exoplayer2/video/VideoDecoderOutputBuffer.java index 4a0a0fbe099..0386b7a17c2 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/VideoDecoderOutputBuffer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/VideoDecoderOutputBuffer.java @@ -24,15 +24,10 @@ /** Video decoder output buffer containing video frame data. */ public class VideoDecoderOutputBuffer extends OutputBuffer { - // LINT.IfChange public static final int COLORSPACE_UNKNOWN = 0; public static final int COLORSPACE_BT601 = 1; public static final int COLORSPACE_BT709 = 2; public static final int COLORSPACE_BT2020 = 3; - // LINT.ThenChange( - // ../../../../../../../../../../../../media/libraries/decoder_av1/src/main/jni/gav1_jni.cc, - // ../../../../../../../../../../../../media/libraries/decoder_vp9/src/main/jni/vpx_jni.cc - // ) /** Decoder private data. Used from native code. */ public int decoderPrivate; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/VideoFrameReleaseHelper.java b/library/core/src/main/java/com/google/android/exoplayer2/video/VideoFrameReleaseHelper.java index bb3b0b64c2c..524460ab7a9 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/VideoFrameReleaseHelper.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/VideoFrameReleaseHelper.java @@ -519,7 +519,6 @@ public void onDisplayRemoved(int displayId) { private Display getDefaultDisplay() { return displayManager.getDisplay(Display.DEFAULT_DISPLAY); } - } /** @@ -579,21 +578,17 @@ public void doFrame(long vsyncTimeNs) { @Override public boolean handleMessage(Message message) { switch (message.what) { - case CREATE_CHOREOGRAPHER: { + case CREATE_CHOREOGRAPHER: createChoreographerInstanceInternal(); return true; - } - case MSG_ADD_OBSERVER: { + case MSG_ADD_OBSERVER: addObserverInternal(); return true; - } - case MSG_REMOVE_OBSERVER: { + case MSG_REMOVE_OBSERVER: removeObserverInternal(); return true; - } - default: { + default: return false; - } } } @@ -615,6 +610,5 @@ private void removeObserverInternal() { sampledVsyncTimeNs = C.TIME_UNSET; } } - } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/VideoRendererEventListener.java b/library/core/src/main/java/com/google/android/exoplayer2/video/VideoRendererEventListener.java index 63370e7e545..116f6060adc 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/VideoRendererEventListener.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/VideoRendererEventListener.java @@ -261,5 +261,4 @@ public void videoCodecError(Exception videoCodecError) { } } } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/spherical/TouchTracker.java b/library/core/src/main/java/com/google/android/exoplayer2/video/spherical/TouchTracker.java index c159fbee59e..2348fcce231 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/spherical/TouchTracker.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/spherical/TouchTracker.java @@ -69,10 +69,7 @@ default boolean onSingleTapUp(MotionEvent event) { // on the sensor thread and read on the UI thread. private volatile float roll; - @SuppressWarnings({ - "nullness:assignment.type.incompatible", - "nullness:argument.type.incompatible" - }) + @SuppressWarnings({"nullness:assignment", "nullness:argument"}) public TouchTracker(Context context, Listener listener, float pxPerDegrees) { this.listener = listener; this.pxPerDegrees = pxPerDegrees; diff --git a/library/core/src/test/java/com/google/android/exoplayer2/AudioFocusManagerTest.java b/library/core/src/test/java/com/google/android/exoplayer2/AudioFocusManagerTest.java index b13b7fe5b1a..1ff0c074905 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/AudioFocusManagerTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/AudioFocusManagerTest.java @@ -21,7 +21,6 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.fail; import static org.robolectric.Shadows.shadowOf; -import static org.robolectric.annotation.Config.TARGET_SDK; import android.content.Context; import android.media.AudioFocusRequest; @@ -100,7 +99,7 @@ public void setAudioAttributes_withNullUsage_abandonsAudioFocus() { } @Test - @Config(minSdk = 26, maxSdk = TARGET_SDK) + @Config(minSdk = 26) public void setAudioAttributes_withNullUsage_abandonsAudioFocus_v26() { Shadows.shadowOf(audioManager) .setNextFocusRequestResponse(AudioManager.AUDIOFOCUS_REQUEST_GRANTED); @@ -286,7 +285,7 @@ public void updateAudioFocus_readyToIdle_abandonsAudioFocus() { } @Test - @Config(minSdk = 26, maxSdk = TARGET_SDK) + @Config(minSdk = 26) public void updateAudioFocus_readyToIdle_abandonsAudioFocus_v26() { Shadows.shadowOf(audioManager) .setNextFocusRequestResponse(AudioManager.AUDIOFOCUS_REQUEST_GRANTED); @@ -324,7 +323,7 @@ public void updateAudioFocus_readyToIdle_withoutFocus_isNoOp() { } @Test - @Config(minSdk = 26, maxSdk = TARGET_SDK) + @Config(minSdk = 26) public void updateAudioFocus_readyToIdle_withoutFocus_isNoOp_v26() { Shadows.shadowOf(audioManager) .setNextFocusRequestResponse(AudioManager.AUDIOFOCUS_REQUEST_GRANTED); @@ -455,7 +454,7 @@ public void onAudioFocusChange_withFocusLoss_sendsDoNotPlayAndAbandonsFocus() { } @Test - @Config(minSdk = 26, maxSdk = TARGET_SDK) + @Config(minSdk = 26) public void onAudioFocusChange_withFocusLoss_sendsDoNotPlayAndAbandonsFocus_v26() { Shadows.shadowOf(audioManager) .setNextFocusRequestResponse(AudioManager.AUDIOFOCUS_REQUEST_GRANTED); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/DefaultMediaClockTest.java b/library/core/src/test/java/com/google/android/exoplayer2/DefaultMediaClockTest.java index 867857cbe5d..9be4c76e62d 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/DefaultMediaClockTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/DefaultMediaClockTest.java @@ -282,8 +282,9 @@ public void getPositionWithPlaybackSpeedChange_shouldTriggerCallback() @Test public void rendererNotReady_shouldStillUseRendererClock() throws ExoPlaybackException { - MediaClockRenderer mediaClockRenderer = new MediaClockRenderer(/* isReady= */ false, - /* isEnded= */ false, /* hasReadStreamToEnd= */ false); + MediaClockRenderer mediaClockRenderer = + new MediaClockRenderer( + /* isReady= */ false, /* isEnded= */ false, /* hasReadStreamToEnd= */ false); mediaClock.start(); mediaClock.onRendererEnabled(mediaClockRenderer); // We're not advancing the renderer media clock. Thus, the clock should appear to be stopped. @@ -293,8 +294,9 @@ public void rendererNotReady_shouldStillUseRendererClock() throws ExoPlaybackExc @Test public void rendererNotReadyAndReadStreamToEnd_shouldFallbackToStandaloneClock() throws ExoPlaybackException { - MediaClockRenderer mediaClockRenderer = new MediaClockRenderer(/* isReady= */ false, - /* isEnded= */ false, /* hasReadStreamToEnd= */ true); + MediaClockRenderer mediaClockRenderer = + new MediaClockRenderer( + /* isReady= */ false, /* isEnded= */ false, /* hasReadStreamToEnd= */ true); mediaClock.start(); mediaClock.onRendererEnabled(mediaClockRenderer); assertClockIsRunning(/* isReadingAhead= */ false); @@ -312,18 +314,17 @@ public void rendererNotReadyAndReadingAhead_shouldFallbackToStandaloneClock() } @Test - public void rendererEnded_shouldFallbackToStandaloneClock() - throws ExoPlaybackException { - MediaClockRenderer mediaClockRenderer = new MediaClockRenderer(/* isReady= */ true, - /* isEnded= */ true, /* hasReadStreamToEnd= */ true); + public void rendererEnded_shouldFallbackToStandaloneClock() throws ExoPlaybackException { + MediaClockRenderer mediaClockRenderer = + new MediaClockRenderer( + /* isReady= */ true, /* isEnded= */ true, /* hasReadStreamToEnd= */ true); mediaClock.start(); mediaClock.onRendererEnabled(mediaClockRenderer); assertClockIsRunning(/* isReadingAhead= */ false); } @Test - public void staleDisableRendererClock_shouldNotThrow() - throws ExoPlaybackException { + public void staleDisableRendererClock_shouldNotThrow() throws ExoPlaybackException { MediaClockRenderer mediaClockRenderer = new MediaClockRenderer(); mediaClockRenderer.positionUs = TEST_POSITION_US; mediaClock.onRendererDisabled(mediaClockRenderer); @@ -332,8 +333,7 @@ public void staleDisableRendererClock_shouldNotThrow() } @Test - public void enableSameRendererClockTwice_shouldNotThrow() - throws ExoPlaybackException { + public void enableSameRendererClockTwice_shouldNotThrow() throws ExoPlaybackException { MediaClockRenderer mediaClockRenderer = new MediaClockRenderer(); mediaClock.onRendererEnabled(mediaClockRenderer); mediaClock.onRendererEnabled(mediaClockRenderer); @@ -343,8 +343,7 @@ public void enableSameRendererClockTwice_shouldNotThrow() } @Test - public void enableOtherRendererClock_shouldThrow() - throws ExoPlaybackException { + public void enableOtherRendererClock_shouldThrow() throws ExoPlaybackException { MediaClockRenderer mediaClockRenderer1 = new MediaClockRenderer(); MediaClockRenderer mediaClockRenderer2 = new MediaClockRenderer(); mediaClockRenderer1.positionUs = TEST_POSITION_US; @@ -459,5 +458,4 @@ public boolean isEnded() { return isEnded; } } - } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java b/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java index 6ad8b5c38ae..69483fe91cc 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java @@ -20,27 +20,35 @@ import static com.google.android.exoplayer2.Player.COMMAND_GET_AUDIO_ATTRIBUTES; import static com.google.android.exoplayer2.Player.COMMAND_GET_CURRENT_MEDIA_ITEM; import static com.google.android.exoplayer2.Player.COMMAND_GET_DEVICE_VOLUME; -import static com.google.android.exoplayer2.Player.COMMAND_GET_MEDIA_ITEMS; import static com.google.android.exoplayer2.Player.COMMAND_GET_MEDIA_ITEMS_METADATA; import static com.google.android.exoplayer2.Player.COMMAND_GET_TEXT; +import static com.google.android.exoplayer2.Player.COMMAND_GET_TIMELINE; import static com.google.android.exoplayer2.Player.COMMAND_GET_VOLUME; import static com.google.android.exoplayer2.Player.COMMAND_PLAY_PAUSE; import static com.google.android.exoplayer2.Player.COMMAND_PREPARE_STOP; -import static com.google.android.exoplayer2.Player.COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_BACK; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_FORWARD; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_IN_CURRENT_WINDOW; import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_DEFAULT_POSITION; -import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_MEDIA_ITEM; -import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM; -import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_NEXT; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_NEXT_WINDOW; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_PREVIOUS; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_PREVIOUS_WINDOW; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_WINDOW; import static com.google.android.exoplayer2.Player.COMMAND_SET_DEVICE_VOLUME; +import static com.google.android.exoplayer2.Player.COMMAND_SET_MEDIA_ITEMS_METADATA; import static com.google.android.exoplayer2.Player.COMMAND_SET_REPEAT_MODE; import static com.google.android.exoplayer2.Player.COMMAND_SET_SHUFFLE_MODE; import static com.google.android.exoplayer2.Player.COMMAND_SET_SPEED_AND_PITCH; import static com.google.android.exoplayer2.Player.COMMAND_SET_VIDEO_SURFACE; import static com.google.android.exoplayer2.Player.COMMAND_SET_VOLUME; +import static com.google.android.exoplayer2.Player.STATE_ENDED; import static com.google.android.exoplayer2.robolectric.RobolectricUtil.runMainLooperUntil; +import static com.google.android.exoplayer2.robolectric.TestPlayerRunHelper.playUntilPosition; import static com.google.android.exoplayer2.robolectric.TestPlayerRunHelper.playUntilStartOfWindow; import static com.google.android.exoplayer2.robolectric.TestPlayerRunHelper.runUntilPendingCommandsAreFullyHandled; import static com.google.android.exoplayer2.robolectric.TestPlayerRunHelper.runUntilPlaybackState; +import static com.google.android.exoplayer2.robolectric.TestPlayerRunHelper.runUntilPositionDiscontinuity; import static com.google.android.exoplayer2.robolectric.TestPlayerRunHelper.runUntilReceiveOffloadSchedulingEnabledNewState; import static com.google.android.exoplayer2.robolectric.TestPlayerRunHelper.runUntilSleepingForOffload; import static com.google.android.exoplayer2.robolectric.TestPlayerRunHelper.runUntilTimelineChanged; @@ -60,6 +68,7 @@ import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.robolectric.Shadows.shadowOf; @@ -118,6 +127,7 @@ import com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition; import com.google.android.exoplayer2.testutil.FakeTrackSelection; import com.google.android.exoplayer2.testutil.FakeTrackSelector; +import com.google.android.exoplayer2.testutil.FakeVideoRenderer; import com.google.android.exoplayer2.testutil.NoUidTimeline; import com.google.android.exoplayer2.testutil.TestExoPlayerBuilder; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; @@ -151,6 +161,7 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatcher; +import org.mockito.ArgumentMatchers; import org.mockito.InOrder; import org.mockito.Mockito; import org.robolectric.shadows.ShadowAudioManager; @@ -1664,7 +1675,9 @@ public void reprepareAfterPlaybackError() throws Exception { ActionSchedule actionSchedule = new ActionSchedule.Builder(TAG) .waitForPlaybackState(Player.STATE_READY) - .throwPlaybackException(ExoPlaybackException.createForSource(new IOException())) + .throwPlaybackException( + ExoPlaybackException.createForSource( + new IOException(), PlaybackException.ERROR_CODE_IO_UNSPECIFIED)) .waitForPlaybackState(Player.STATE_IDLE) .prepare() .waitForPlaybackState(Player.STATE_BUFFERING) @@ -1699,10 +1712,11 @@ public void seekAndReprepareAfterPlaybackError_keepsSeekPositionAndTimeline() th player .createMessage( (type, payload) -> { - throw ExoPlaybackException.createForSource(new IOException()); + throw ExoPlaybackException.createForSource( + new IOException(), PlaybackException.ERROR_CODE_IO_UNSPECIFIED); }) .send(); - runUntilPlaybackState(player, Player.STATE_IDLE); + TestPlayerRunHelper.runUntilError(player); player.seekTo(/* positionMs= */ 50); runUntilPendingCommandsAreFullyHandled(player); long positionAfterSeekHandled = player.getCurrentPosition(); @@ -1774,7 +1788,9 @@ public void playbackErrorAndReprepareDoesNotResetPosition() throws Exception { .pause() .waitForPlaybackState(Player.STATE_READY) .playUntilPosition(/* windowIndex= */ 1, /* positionMs= */ 500) - .throwPlaybackException(ExoPlaybackException.createForSource(new IOException())) + .throwPlaybackException( + ExoPlaybackException.createForSource( + new IOException(), PlaybackException.ERROR_CODE_IO_UNSPECIFIED)) .waitForPlaybackState(Player.STATE_IDLE) .executeRunnable( new PlayerRunnable() { @@ -1837,7 +1853,9 @@ public void seekAfterPlaybackError() throws Exception { .pause() .waitForPlaybackState(Player.STATE_READY) .playUntilPosition(/* windowIndex= */ 1, /* positionMs= */ 500) - .throwPlaybackException(ExoPlaybackException.createForSource(new IOException())) + .throwPlaybackException( + ExoPlaybackException.createForSource( + new IOException(), PlaybackException.ERROR_CODE_IO_UNSPECIFIED)) .waitForPlaybackState(Player.STATE_IDLE) .executeRunnable( new PlayerRunnable() { @@ -1899,7 +1917,9 @@ public void playbackErrorAndReprepareWithPositionResetKeepsWindowSequenceNumber( new ActionSchedule.Builder(TAG) .pause() .waitForPlaybackState(Player.STATE_READY) - .throwPlaybackException(ExoPlaybackException.createForSource(new IOException())) + .throwPlaybackException( + ExoPlaybackException.createForSource( + new IOException(), PlaybackException.ERROR_CODE_IO_UNSPECIFIED)) .waitForPlaybackState(Player.STATE_IDLE) .seek(0, C.TIME_UNSET) .prepare() @@ -1948,12 +1968,16 @@ public void playbackErrorTwiceStillKeepsTimeline() throws Exception { new ActionSchedule.Builder(TAG) .pause() .waitForPlaybackState(Player.STATE_READY) - .throwPlaybackException(ExoPlaybackException.createForSource(new IOException())) + .throwPlaybackException( + ExoPlaybackException.createForSource( + new IOException(), PlaybackException.ERROR_CODE_IO_UNSPECIFIED)) .waitForPlaybackState(Player.STATE_IDLE) .setMediaSources(/* resetPosition= */ false, mediaSource2) .prepare() .waitForPlaybackState(Player.STATE_BUFFERING) - .throwPlaybackException(ExoPlaybackException.createForSource(new IOException())) + .throwPlaybackException( + ExoPlaybackException.createForSource( + new IOException(), PlaybackException.ERROR_CODE_IO_UNSPECIFIED)) .waitForTimelineChanged(timeline, Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE) .waitForPlaybackState(Player.STATE_IDLE) .build(); @@ -2546,9 +2570,10 @@ public void setAndSwitchSurface() throws Exception { Renderer videoRenderer = new FakeRenderer(C.TRACK_TYPE_VIDEO) { @Override - public void handleMessage(int what, @Nullable Object object) throws ExoPlaybackException { - super.handleMessage(what, object); - rendererMessages.add(what); + public void handleMessage(int messageType, @Nullable Object message) + throws ExoPlaybackException { + super.handleMessage(messageType, message); + rendererMessages.add(messageType); } }; ActionSchedule actionSchedule = addSurfaceSwitch(new ActionSchedule.Builder(TAG)).build(); @@ -2730,8 +2755,7 @@ public MediaPeriod createPeriod( player.play(); // When the ad finishes, the player position should be at or after the requested seek position. - TestPlayerRunHelper.runUntilPositionDiscontinuity( - player, Player.DISCONTINUITY_REASON_AUTO_TRANSITION); + runUntilPositionDiscontinuity(player, Player.DISCONTINUITY_REASON_AUTO_TRANSITION); assertThat(player.getCurrentPosition()).isAtLeast(seekPositionMs); } @@ -2846,6 +2870,38 @@ public void run(SimpleExoPlayer player) { assertThat(position[0]).isEqualTo(0L); } + @Test + public void onPlayerErrorChanged_isNotifiedForNullError() throws Exception { + ExoPlayer player = new TestExoPlayerBuilder(context).build(); + player.addMediaSource( + new FakeMediaSource(/* timeline= */ null) { + @Override + public void maybeThrowSourceInfoRefreshError() throws IOException { + throw new IOException(); + } + }); + Player.Listener mockListener = mock(Player.Listener.class); + player.addListener(mockListener); + + player.prepare(); + player.play(); + ExoPlaybackException error = TestPlayerRunHelper.runUntilError(player); + // The media source fails preparation, so we expect both methods to be called. + verify(mockListener).onPlayerErrorChanged(error); + verify(mockListener).onPlayerError(error); + + reset(mockListener); + + player.setMediaSource(new FakeMediaSource()); + player.prepare(); + player.play(); + TestPlayerRunHelper.runUntilPlaybackState(player, STATE_ENDED); + // Now the player, which had a playback error, was re-prepared causing the error to be cleared. + // We expect the change to null to be notified, but not onPlayerError. + verify(mockListener).onPlayerErrorChanged(ArgumentMatchers.isNull()); + verify(mockListener, never()).onPlayerError(any()); + } + @Test public void recursivePlayerChangesReportConsistentValuesForAllListeners() throws Exception { // We add two listeners to the player. The first stops the player as soon as it's ready and both @@ -2964,8 +3020,8 @@ public void recursiveTimelineChangeInStopAreReportedInCorrectOrder() throws Exce final Player.Listener playerListener = new Player.Listener() { @Override - public void onPlaybackStateChanged(int state) { - if (state == Player.STATE_IDLE) { + public void onPlaybackStateChanged(int playbackState) { + if (playbackState == Player.STATE_IDLE) { playerReference.get().setMediaSource(secondMediaSource); } } @@ -3390,6 +3446,55 @@ public void run(SimpleExoPlayer player) { assertThat(contentStartPositionMs.get()).isAtLeast(5_000L); } + @Test + public void adInMovingLiveWindow_keepsContentPosition() throws Exception { + SimpleExoPlayer player = new TestExoPlayerBuilder(context).build(); + AdPlaybackState adPlaybackState = + FakeTimeline.createAdPlaybackState( + /* adsPerAdGroup= */ 1, /* adGroupTimesUs...= */ 42_000_004_000_000L); + Timeline liveTimeline1 = + new FakeTimeline( + new TimelineWindowDefinition( + /* periodCount= */ 1, + /* id= */ 0, + /* isSeekable= */ true, + /* isDynamic= */ true, + /* isLive= */ true, + /* isPlaceholder= */ false, + /* durationUs= */ 10_000_000, + /* defaultPositionUs= */ 3_000_000, + /* windowOffsetInFirstPeriodUs= */ 42_000_000_000_000L, + adPlaybackState)); + Timeline liveTimeline2 = + new FakeTimeline( + new TimelineWindowDefinition( + /* periodCount= */ 1, + /* id= */ 0, + /* isSeekable= */ true, + /* isDynamic= */ true, + /* isLive= */ true, + /* isPlaceholder= */ false, + /* durationUs= */ 10_000_000, + /* defaultPositionUs= */ 3_000_000, + /* windowOffsetInFirstPeriodUs= */ 42_000_002_000_000L, + adPlaybackState)); + FakeMediaSource fakeMediaSource = new FakeMediaSource(liveTimeline1); + + player.setMediaSource(fakeMediaSource); + player.prepare(); + player.play(); + // Wait until the ad is playing. + runUntilPositionDiscontinuity(player, Player.DISCONTINUITY_REASON_AUTO_TRANSITION); + long contentPositionBeforeLiveWindowUpdateMs = player.getContentPosition(); + fakeMediaSource.setNewSourceInfo(liveTimeline2); + runUntilTimelineChanged(player); + long contentPositionAfterLiveWindowUpdateMs = player.getContentPosition(); + player.release(); + + assertThat(contentPositionBeforeLiveWindowUpdateMs).isEqualTo(4000); + assertThat(contentPositionAfterLiveWindowUpdateMs).isEqualTo(2000); + } + @Test public void setPlaybackSpeedConsecutivelyNotifiesListenerForEveryChangeOnceAndIsMasked() throws Exception { @@ -7092,7 +7197,9 @@ protected void onEnabled(boolean joining, boolean mayRenderStartOfStream) if (audioRendererEnableCount.incrementAndGet() == 2) { // Fail when enabling the renderer for the second time during the playlist update. throw createRendererException( - new IllegalStateException(), ExoPlayerTestRunner.AUDIO_FORMAT); + new IllegalStateException(), + ExoPlayerTestRunner.AUDIO_FORMAT, + PlaybackException.ERROR_CODE_UNSPECIFIED); } } }; @@ -7109,8 +7216,7 @@ public void run(SimpleExoPlayer player) { player.addAnalyticsListener( new AnalyticsListener() { @Override - public void onPlayerError( - EventTime eventTime, ExoPlaybackException error) { + public void onPlayerError(EventTime eventTime, PlaybackException error) { timelineAfterError.set(player.getCurrentTimeline()); trackGroupsAfterError.set(player.getCurrentTrackGroups()); trackSelectionsAfterError.set(player.getCurrentTrackSelections()); @@ -7594,8 +7700,7 @@ protected boolean shouldProcessBuffer(long bufferTimeUs, long playbackPositionUs // Update media with a non-zero default start position and window offset. firstMediaSource.setNewSourceInfo(timelineWithOffsets); // Wait until player transitions to second source (which also has non-zero offsets). - TestPlayerRunHelper.runUntilPositionDiscontinuity( - player, Player.DISCONTINUITY_REASON_AUTO_TRANSITION); + runUntilPositionDiscontinuity(player, Player.DISCONTINUITY_REASON_AUTO_TRANSITION); assertThat(player.getCurrentWindowIndex()).isEqualTo(1); player.release(); @@ -8074,16 +8179,21 @@ public void isCommandAvailable_isTrueForAvailableCommands() { assertThat(player.isCommandAvailable(COMMAND_PLAY_PAUSE)).isTrue(); assertThat(player.isCommandAvailable(COMMAND_PREPARE_STOP)).isTrue(); assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_DEFAULT_POSITION)).isTrue(); - assertThat(player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM)).isFalse(); - assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM)).isTrue(); - assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM)).isFalse(); - assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_MEDIA_ITEM)).isTrue(); + assertThat(player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_WINDOW)).isFalse(); + assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS_WINDOW)).isFalse(); + assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS)).isTrue(); + assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_NEXT_WINDOW)).isTrue(); + assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_NEXT)).isTrue(); + assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_WINDOW)).isTrue(); + assertThat(player.isCommandAvailable(COMMAND_SEEK_BACK)).isFalse(); + assertThat(player.isCommandAvailable(COMMAND_SEEK_FORWARD)).isFalse(); assertThat(player.isCommandAvailable(COMMAND_SET_SPEED_AND_PITCH)).isTrue(); assertThat(player.isCommandAvailable(COMMAND_SET_SHUFFLE_MODE)).isTrue(); assertThat(player.isCommandAvailable(COMMAND_SET_REPEAT_MODE)).isTrue(); assertThat(player.isCommandAvailable(COMMAND_GET_CURRENT_MEDIA_ITEM)).isTrue(); - assertThat(player.isCommandAvailable(COMMAND_GET_MEDIA_ITEMS)).isTrue(); + assertThat(player.isCommandAvailable(COMMAND_GET_TIMELINE)).isTrue(); assertThat(player.isCommandAvailable(COMMAND_GET_MEDIA_ITEMS_METADATA)).isTrue(); + assertThat(player.isCommandAvailable(COMMAND_SET_MEDIA_ITEMS_METADATA)).isTrue(); assertThat(player.isCommandAvailable(COMMAND_CHANGE_MEDIA_ITEMS)).isTrue(); assertThat(player.isCommandAvailable(COMMAND_GET_AUDIO_ATTRIBUTES)).isTrue(); assertThat(player.isCommandAvailable(COMMAND_GET_VOLUME)).isTrue(); @@ -8120,14 +8230,19 @@ public void isCommandAvailable_duringAd_isFalseForSeekCommands() throws Exceptio player.prepare(); runUntilPlaybackState(player, Player.STATE_READY); - assertThat(player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM)).isFalse(); - assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM)).isFalse(); - assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM)).isFalse(); - assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_MEDIA_ITEM)).isFalse(); + assertThat(player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_WINDOW)).isFalse(); + assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS_WINDOW)).isFalse(); + assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS)).isFalse(); + assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_NEXT_WINDOW)).isFalse(); + assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_NEXT)).isFalse(); + assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_WINDOW)).isFalse(); + assertThat(player.isCommandAvailable(COMMAND_SEEK_BACK)).isFalse(); + assertThat(player.isCommandAvailable(COMMAND_SEEK_FORWARD)).isFalse(); } @Test - public void isCommandAvailable_duringUnseekableItem_isFalseForSeekInCurrent() throws Exception { + public void isCommandAvailable_duringUnseekableItem_isFalseForSeekInCurrentCommands() + throws Exception { Timeline timelineWithUnseekableWindow = new FakeTimeline( new TimelineWindowDefinition( @@ -8140,18 +8255,97 @@ public void isCommandAvailable_duringUnseekableItem_isFalseForSeekInCurrent() th player.prepare(); runUntilPlaybackState(player, Player.STATE_READY); - assertThat(player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM)).isFalse(); + assertThat(player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_WINDOW)).isFalse(); + assertThat(player.isCommandAvailable(COMMAND_SEEK_BACK)).isFalse(); + assertThat(player.isCommandAvailable(COMMAND_SEEK_FORWARD)).isFalse(); + } + + @Test + public void isCommandAvailable_duringUnseekableLiveItem_isFalseForSeekToPrevious() + throws Exception { + Timeline timelineWithUnseekableLiveWindow = + new FakeTimeline( + new TimelineWindowDefinition( + /* periodCount= */ 1, + /* id= */ 0, + /* isSeekable= */ false, + /* isDynamic= */ true, + /* isLive= */ true, + /* isPlaceholder= */ false, + /* durationUs= */ C.TIME_UNSET, + /* defaultPositionUs= */ 10_000_000, + TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US, + AdPlaybackState.NONE)); + ExoPlayer player = new TestExoPlayerBuilder(context).build(); + + player.addMediaSource(new FakeMediaSource(timelineWithUnseekableLiveWindow)); + player.prepare(); + runUntilPlaybackState(player, Player.STATE_READY); + + assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS)).isFalse(); + } + + @Test + public void + isCommandAvailable_duringUnseekableLiveItemWithPreviousWindow_isTrueForSeekToPrevious() + throws Exception { + Timeline timelineWithUnseekableLiveWindow = + new FakeTimeline( + new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ 0), + new TimelineWindowDefinition( + /* periodCount= */ 1, + /* id= */ 1, + /* isSeekable= */ false, + /* isDynamic= */ true, + /* isLive= */ true, + /* isPlaceholder= */ false, + /* durationUs= */ C.TIME_UNSET, + /* defaultPositionUs= */ 10_000_000, + TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US, + AdPlaybackState.NONE)); + ExoPlayer player = new TestExoPlayerBuilder(context).build(); + + player.addMediaSource(new FakeMediaSource(timelineWithUnseekableLiveWindow)); + player.seekTo(/* windowIndex= */ 1, /* positionMs= */ 0); + player.prepare(); + runUntilPlaybackState(player, Player.STATE_READY); + + assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS)).isTrue(); + } + + @Test + public void isCommandAvailable_duringLiveItem_isTrueForSeekToNext() throws Exception { + Timeline timelineWithLiveWindow = + new FakeTimeline( + new TimelineWindowDefinition( + /* periodCount= */ 1, + /* id= */ 0, + /* isSeekable= */ true, + /* isDynamic= */ true, + /* isLive= */ true, + /* isPlaceholder= */ false, + /* durationUs= */ C.TIME_UNSET, + /* defaultPositionUs= */ 10_000_000, + TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US, + AdPlaybackState.NONE)); + ExoPlayer player = new TestExoPlayerBuilder(context).build(); + + player.addMediaSource(new FakeMediaSource(timelineWithLiveWindow)); + player.prepare(); + runUntilPlaybackState(player, Player.STATE_READY); + + assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_NEXT)).isTrue(); } @Test public void seekTo_nextWindow_notifiesAvailableCommandsChanged() { - Player.Commands commandsWithSeekToNext = - createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); - Player.Commands commandsWithSeekToPrevious = - createWithDefaultCommands(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); - Player.Commands commandsWithSeekToNextAndPrevious = + Player.Commands commandsWithSeekToPreviousWindow = + createWithDefaultCommands(COMMAND_SEEK_TO_PREVIOUS_WINDOW); + Player.Commands commandsWithSeekToNextWindow = + createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_WINDOW, COMMAND_SEEK_TO_NEXT); + Player.Commands commandsWithSeekToPreviousAndNextWindow = createWithDefaultCommands( - COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); + COMMAND_SEEK_TO_PREVIOUS_WINDOW, COMMAND_SEEK_TO_NEXT_WINDOW, COMMAND_SEEK_TO_NEXT); Player.Listener mockListener = mock(Player.Listener.class); ExoPlayer player = new TestExoPlayerBuilder(context).build(); player.addListener(mockListener); @@ -8162,31 +8356,31 @@ public void seekTo_nextWindow_notifiesAvailableCommandsChanged() { new FakeMediaSource(), new FakeMediaSource(), new FakeMediaSource())); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToNext); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToNextWindow); // Check that there were no other calls to onAvailableCommandsChanged. verify(mockListener).onAvailableCommandsChanged(any()); player.seekTo(/* windowIndex= */ 1, /* positionMs= */ 0); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToNextAndPrevious); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToPreviousAndNextWindow); verify(mockListener, times(2)).onAvailableCommandsChanged(any()); player.seekTo(/* windowIndex= */ 2, /* positionMs= */ 0); verify(mockListener, times(2)).onAvailableCommandsChanged(any()); player.seekTo(/* windowIndex= */ 3, /* positionMs= */ 0); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToPrevious); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToPreviousWindow); verify(mockListener, times(3)).onAvailableCommandsChanged(any()); } @Test public void seekTo_previousWindow_notifiesAvailableCommandsChanged() { - Player.Commands commandsWithSeekToNext = - createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); - Player.Commands commandsWithSeekToPrevious = - createWithDefaultCommands(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); - Player.Commands commandsWithSeekToNextAndPrevious = + Player.Commands commandsWithSeekToPreviousWindow = + createWithDefaultCommands(COMMAND_SEEK_TO_PREVIOUS_WINDOW); + Player.Commands commandsWithSeekToNextWindow = + createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_WINDOW, COMMAND_SEEK_TO_NEXT); + Player.Commands commandsWithSeekToPreviousAndNextWindow = createWithDefaultCommands( - COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); + COMMAND_SEEK_TO_PREVIOUS_WINDOW, COMMAND_SEEK_TO_NEXT_WINDOW, COMMAND_SEEK_TO_NEXT); Player.Listener mockListener = mock(Player.Listener.class); ExoPlayer player = new TestExoPlayerBuilder(context).build(); player.addListener(mockListener); @@ -8198,49 +8392,63 @@ public void seekTo_previousWindow_notifiesAvailableCommandsChanged() { new FakeMediaSource(), new FakeMediaSource(), new FakeMediaSource())); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToPrevious); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToPreviousWindow); // Check that there were no other calls to onAvailableCommandsChanged. verify(mockListener).onAvailableCommandsChanged(any()); player.seekTo(/* windowIndex= */ 2, /* positionMs= */ 0); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToNextAndPrevious); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToPreviousAndNextWindow); verify(mockListener, times(2)).onAvailableCommandsChanged(any()); player.seekTo(/* windowIndex= */ 1, /* positionMs= */ 0); verify(mockListener, times(2)).onAvailableCommandsChanged(any()); player.seekTo(/* windowIndex= */ 0, /* positionMs= */ 0); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToNext); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToNextWindow); verify(mockListener, times(3)).onAvailableCommandsChanged(any()); } @Test public void seekTo_sameWindow_doesNotNotifyAvailableCommandsChanged() { + Player.Commands defaultCommands = createWithDefaultCommands(); Player.Listener mockListener = mock(Player.Listener.class); ExoPlayer player = new TestExoPlayerBuilder(context).build(); player.addListener(mockListener); player.addMediaSources(ImmutableList.of(new FakeMediaSource())); + verify(mockListener).onAvailableCommandsChanged(defaultCommands); + player.seekTo(/* windowIndex= */ 0, /* positionMs= */ 200); player.seekTo(/* windowIndex= */ 0, /* positionMs= */ 100); - verify(mockListener, never()).onAvailableCommandsChanged(any()); + // Check that there were no other calls to onAvailableCommandsChanged. + verify(mockListener).onAvailableCommandsChanged(any()); } @Test public void automaticWindowTransition_notifiesAvailableCommandsChanged() throws Exception { - Player.Commands commandsWithSeekToNext = - createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); - Player.Commands commandsWithSeekInCurrentAndToNext = + Player.Commands commandsWithSeekToNextWindow = + createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_WINDOW, COMMAND_SEEK_TO_NEXT); + Player.Commands commandsWithSeekInCurrentAndToNextWindow = createWithDefaultCommands( - COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); - Player.Commands commandsWithSeekInCurrentAndToPrevious = + COMMAND_SEEK_IN_CURRENT_WINDOW, + COMMAND_SEEK_TO_NEXT_WINDOW, + COMMAND_SEEK_TO_NEXT, + COMMAND_SEEK_BACK, + COMMAND_SEEK_FORWARD); + Player.Commands commandsWithSeekInCurrentAndToPreviousWindow = createWithDefaultCommands( - COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); + COMMAND_SEEK_IN_CURRENT_WINDOW, + COMMAND_SEEK_TO_PREVIOUS_WINDOW, + COMMAND_SEEK_BACK, + COMMAND_SEEK_FORWARD); Player.Commands commandsWithSeekAnywhere = createWithDefaultCommands( - COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, - COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, - COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); + COMMAND_SEEK_IN_CURRENT_WINDOW, + COMMAND_SEEK_TO_PREVIOUS_WINDOW, + COMMAND_SEEK_TO_NEXT_WINDOW, + COMMAND_SEEK_TO_NEXT, + COMMAND_SEEK_BACK, + COMMAND_SEEK_FORWARD); Player.Listener mockListener = mock(Player.Listener.class); ExoPlayer player = new TestExoPlayerBuilder(context).build(); player.addListener(mockListener); @@ -8251,13 +8459,13 @@ public void automaticWindowTransition_notifiesAvailableCommandsChanged() throws new FakeMediaSource(), new FakeMediaSource(), new FakeMediaSource())); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToNext); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToNextWindow); // Check that there were no other calls to onAvailableCommandsChanged. verify(mockListener).onAvailableCommandsChanged(any()); player.prepare(); runUntilPlaybackState(player, Player.STATE_READY); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekInCurrentAndToNext); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekInCurrentAndToNextWindow); verify(mockListener, times(2)).onAvailableCommandsChanged(any()); playUntilStartOfWindow(player, /* windowIndex= */ 1); @@ -8271,62 +8479,67 @@ public void automaticWindowTransition_notifiesAvailableCommandsChanged() throws player.play(); runUntilPlaybackState(player, Player.STATE_ENDED); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekInCurrentAndToPrevious); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekInCurrentAndToPreviousWindow); verify(mockListener, times(4)).onAvailableCommandsChanged(any()); } @Test public void addMediaSource_atTheEnd_notifiesAvailableCommandsChanged() { - Player.Commands commandsWithSeekToNext = - createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); + Player.Commands defaultCommands = createWithDefaultCommands(); + Player.Commands commandsWithSeekToNextWindow = + createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_WINDOW, COMMAND_SEEK_TO_NEXT); Player.Listener mockListener = mock(Player.Listener.class); ExoPlayer player = new TestExoPlayerBuilder(context).build(); player.addListener(mockListener); player.addMediaSource(new FakeMediaSource()); - verify(mockListener, never()).onAvailableCommandsChanged(any()); - - player.addMediaSource(new FakeMediaSource()); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToNext); + verify(mockListener).onAvailableCommandsChanged(defaultCommands); // Check that there were no other calls to onAvailableCommandsChanged. verify(mockListener).onAvailableCommandsChanged(any()); player.addMediaSource(new FakeMediaSource()); - verify(mockListener).onAvailableCommandsChanged(any()); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToNextWindow); + verify(mockListener, times(2)).onAvailableCommandsChanged(any()); + + player.addMediaSource(new FakeMediaSource()); + verify(mockListener, times(2)).onAvailableCommandsChanged(any()); } @Test public void addMediaSource_atTheStart_notifiesAvailableCommandsChanged() { - Player.Commands commandsWithSeekToPrevious = - createWithDefaultCommands(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); + Player.Commands defaultCommands = createWithDefaultCommands(); + Player.Commands commandsWithSeekToPreviousWindow = + createWithDefaultCommands(COMMAND_SEEK_TO_PREVIOUS_WINDOW); Player.Listener mockListener = mock(Player.Listener.class); ExoPlayer player = new TestExoPlayerBuilder(context).build(); player.addListener(mockListener); player.addMediaSource(new FakeMediaSource()); - verify(mockListener, never()).onAvailableCommandsChanged(any()); - - player.addMediaSource(/* index= */ 0, new FakeMediaSource()); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToPrevious); + verify(mockListener).onAvailableCommandsChanged(defaultCommands); // Check that there were no other calls to onAvailableCommandsChanged. verify(mockListener).onAvailableCommandsChanged(any()); player.addMediaSource(/* index= */ 0, new FakeMediaSource()); - verify(mockListener).onAvailableCommandsChanged(any()); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToPreviousWindow); + verify(mockListener, times(2)).onAvailableCommandsChanged(any()); + + player.addMediaSource(/* index= */ 0, new FakeMediaSource()); + verify(mockListener, times(2)).onAvailableCommandsChanged(any()); } @Test public void removeMediaItem_atTheEnd_notifiesAvailableCommandsChanged() { - Player.Commands commandsWithSeekToNext = - createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); - Player.Commands commandsWithoutSeek = createWithDefaultCommands(); + Player.Commands defaultCommands = createWithDefaultCommands(); + Player.Commands commandsWithSeekToNextWindow = + createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_WINDOW, COMMAND_SEEK_TO_NEXT); + Player.Commands emptyTimelineCommands = createWithDefaultCommands(/* isTimelineEmpty */ true); Player.Listener mockListener = mock(Player.Listener.class); ExoPlayer player = new TestExoPlayerBuilder(context).build(); player.addListener(mockListener); player.addMediaSources( ImmutableList.of(new FakeMediaSource(), new FakeMediaSource(), new FakeMediaSource())); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToNext); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToNextWindow); // Check that there were no other calls to onAvailableCommandsChanged. verify(mockListener).onAvailableCommandsChanged(any()); @@ -8334,18 +8547,20 @@ public void removeMediaItem_atTheEnd_notifiesAvailableCommandsChanged() { verify(mockListener).onAvailableCommandsChanged(any()); player.removeMediaItem(/* index= */ 1); - verify(mockListener).onAvailableCommandsChanged(commandsWithoutSeek); + verify(mockListener).onAvailableCommandsChanged(defaultCommands); verify(mockListener, times(2)).onAvailableCommandsChanged(any()); player.removeMediaItem(/* index= */ 0); - verify(mockListener, times(2)).onAvailableCommandsChanged(any()); + verify(mockListener).onAvailableCommandsChanged(emptyTimelineCommands); + verify(mockListener, times(3)).onAvailableCommandsChanged(any()); } @Test public void removeMediaItem_atTheStart_notifiesAvailableCommandsChanged() { - Player.Commands commandsWithSeekToPrevious = - createWithDefaultCommands(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); - Player.Commands commandsWithoutSeek = createWithDefaultCommands(); + Player.Commands defaultCommands = createWithDefaultCommands(); + Player.Commands commandsWithSeekToPreviousWindow = + createWithDefaultCommands(COMMAND_SEEK_TO_PREVIOUS_WINDOW); + Player.Commands emptyTimelineCommands = createWithDefaultCommands(/* isTimelineEmpty */ true); Player.Listener mockListener = mock(Player.Listener.class); ExoPlayer player = new TestExoPlayerBuilder(context).build(); player.addListener(mockListener); @@ -8353,7 +8568,7 @@ public void removeMediaItem_atTheStart_notifiesAvailableCommandsChanged() { player.seekTo(/* windowIndex= */ 2, /* positionMs= */ 0); player.addMediaSources( ImmutableList.of(new FakeMediaSource(), new FakeMediaSource(), new FakeMediaSource())); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToPrevious); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToPreviousWindow); // Check that there were no other calls to onAvailableCommandsChanged. verify(mockListener).onAvailableCommandsChanged(any()); @@ -8361,67 +8576,73 @@ public void removeMediaItem_atTheStart_notifiesAvailableCommandsChanged() { verify(mockListener).onAvailableCommandsChanged(any()); player.removeMediaItem(/* index= */ 0); - verify(mockListener).onAvailableCommandsChanged(commandsWithoutSeek); + verify(mockListener).onAvailableCommandsChanged(defaultCommands); verify(mockListener, times(2)).onAvailableCommandsChanged(any()); player.removeMediaItem(/* index= */ 0); - verify(mockListener, times(2)).onAvailableCommandsChanged(any()); + verify(mockListener).onAvailableCommandsChanged(emptyTimelineCommands); + verify(mockListener, times(3)).onAvailableCommandsChanged(any()); } @Test public void removeMediaItem_current_notifiesAvailableCommandsChanged() { - Player.Commands commandsWithSeekToNext = - createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); - Player.Commands commandsWithoutSeek = createWithDefaultCommands(); + Player.Commands defaultCommands = createWithDefaultCommands(); + Player.Commands commandsWithSeekToNextWindow = + createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_WINDOW, COMMAND_SEEK_TO_NEXT); Player.Listener mockListener = mock(Player.Listener.class); ExoPlayer player = new TestExoPlayerBuilder(context).build(); player.addListener(mockListener); player.addMediaSources(ImmutableList.of(new FakeMediaSource(), new FakeMediaSource())); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToNext); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToNextWindow); // Check that there were no other calls to onAvailableCommandsChanged. verify(mockListener).onAvailableCommandsChanged(any()); player.removeMediaItem(/* index= */ 0); - verify(mockListener).onAvailableCommandsChanged(commandsWithoutSeek); + verify(mockListener).onAvailableCommandsChanged(defaultCommands); verify(mockListener, times(2)).onAvailableCommandsChanged(any()); } @Test public void setRepeatMode_all_notifiesAvailableCommandsChanged() { - Player.Commands commandsWithSeekToNextAndPrevious = + Player.Commands defaultCommands = createWithDefaultCommands(); + Player.Commands commandsWithSeekToPreviousAndNextWindow = createWithDefaultCommands( - COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); + COMMAND_SEEK_TO_PREVIOUS_WINDOW, COMMAND_SEEK_TO_NEXT_WINDOW, COMMAND_SEEK_TO_NEXT); Player.Listener mockListener = mock(Player.Listener.class); ExoPlayer player = new TestExoPlayerBuilder(context).build(); player.addListener(mockListener); player.addMediaSource(new FakeMediaSource()); - verify(mockListener, never()).onAvailableCommandsChanged(any()); - - player.setRepeatMode(Player.REPEAT_MODE_ALL); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToNextAndPrevious); + verify(mockListener).onAvailableCommandsChanged(defaultCommands); // Check that there were no other calls to onAvailableCommandsChanged. verify(mockListener).onAvailableCommandsChanged(any()); + + player.setRepeatMode(Player.REPEAT_MODE_ALL); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToPreviousAndNextWindow); + verify(mockListener, times(2)).onAvailableCommandsChanged(any()); } @Test public void setRepeatMode_one_doesNotNotifyAvailableCommandsChanged() { + Player.Commands defaultCommands = createWithDefaultCommands(); Player.Listener mockListener = mock(Player.Listener.class); ExoPlayer player = new TestExoPlayerBuilder(context).build(); player.addListener(mockListener); player.addMediaSource(new FakeMediaSource()); + verify(mockListener).onAvailableCommandsChanged(defaultCommands); + player.setRepeatMode(Player.REPEAT_MODE_ONE); - verify(mockListener, never()).onAvailableCommandsChanged(any()); + verify(mockListener).onAvailableCommandsChanged(any()); } @Test public void setShuffleModeEnabled_notifiesAvailableCommandsChanged() { - Player.Commands commandsWithSeekToNext = - createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); - Player.Commands commandsWithSeekToPrevious = - createWithDefaultCommands(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); + Player.Commands commandsWithSeekToPreviousWindow = + createWithDefaultCommands(COMMAND_SEEK_TO_PREVIOUS_WINDOW); + Player.Commands commandsWithSeekToNextWindow = + createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_WINDOW, COMMAND_SEEK_TO_NEXT); Player.Listener mockListener = mock(Player.Listener.class); ExoPlayer player = new TestExoPlayerBuilder(context).build(); player.addListener(mockListener); @@ -8433,12 +8654,12 @@ public void setShuffleModeEnabled_notifiesAvailableCommandsChanged() { new FakeMediaSource()); player.addMediaSource(mediaSource); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToNext); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToNextWindow); // Check that there were no other calls to onAvailableCommandsChanged. verify(mockListener).onAvailableCommandsChanged(any()); player.setShuffleModeEnabled(true); - verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToPrevious); + verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToPreviousWindow); verify(mockListener, times(2)).onAvailableCommandsChanged(any()); } @@ -8595,7 +8816,9 @@ protected void onEnabled(boolean joining, boolean mayRenderStartOfStream) // Fail when enabling the renderer. This will happen during the period // transition while the reading and playing period are different. throw createRendererException( - new IllegalStateException(), ExoPlayerTestRunner.AUDIO_FORMAT); + new IllegalStateException(), + ExoPlayerTestRunner.AUDIO_FORMAT, + PlaybackException.ERROR_CODE_UNSPECIFIED); } } }; @@ -8715,72 +8938,6 @@ public void wakeupListenerWhileSleepingForOffload_isWokenUp_renderingResumes() t runUntilPlaybackState(player, Player.STATE_ENDED); } - @Test - public void staticMetadata_callbackIsCalledCorrectlyAndMatchesGetter() throws Exception { - Format videoFormat = - new Format.Builder() - .setSampleMimeType(MimeTypes.VIDEO_H264) - .setMetadata( - new Metadata( - new TextInformationFrame( - /* id= */ "TT2", - /* description= */ "Video", - /* value= */ "Video track name"))) - .build(); - Format audioFormat = - new Format.Builder() - .setSampleMimeType(MimeTypes.AUDIO_AAC) - .setMetadata( - new Metadata( - new TextInformationFrame( - /* id= */ "TT2", - /* description= */ "Audio", - /* value= */ "Audio track name"))) - .build(); - Player.Listener playerListener = mock(Player.Listener.class); - Timeline fakeTimeline = - new FakeTimeline( - new TimelineWindowDefinition( - /* isSeekable= */ true, /* isDynamic= */ false, /* durationUs= */ 100000)); - SimpleExoPlayer player = new TestExoPlayerBuilder(context).build(); - - player.setMediaSource(new FakeMediaSource(fakeTimeline, videoFormat, audioFormat)); - player.addListener(playerListener); - player.prepare(); - player.play(); - runUntilPlaybackState(player, Player.STATE_ENDED); - List metadata = player.getCurrentStaticMetadata(); - player.release(); - - assertThat(metadata).containsExactly(videoFormat.metadata, audioFormat.metadata).inOrder(); - verify(playerListener) - .onStaticMetadataChanged(ImmutableList.of(videoFormat.metadata, audioFormat.metadata)); - } - - @Test - public void staticMetadata_callbackIsNotCalledWhenMetadataEmptyAndGetterReturnsEmptyList() - throws Exception { - Format videoFormat = new Format.Builder().setSampleMimeType(MimeTypes.VIDEO_H264).build(); - Format audioFormat = new Format.Builder().setSampleMimeType(MimeTypes.AUDIO_AAC).build(); - Player.Listener playerListener = mock(Player.Listener.class); - Timeline fakeTimeline = - new FakeTimeline( - new TimelineWindowDefinition( - /* isSeekable= */ true, /* isDynamic= */ false, /* durationUs= */ 100000)); - SimpleExoPlayer player = new TestExoPlayerBuilder(context).build(); - - player.setMediaSource(new FakeMediaSource(fakeTimeline, videoFormat, audioFormat)); - player.addListener(playerListener); - player.prepare(); - player.play(); - runUntilPlaybackState(player, Player.STATE_ENDED); - List metadata = player.getCurrentStaticMetadata(); - player.release(); - - assertThat(metadata).isEmpty(); - verify(playerListener, never()).onStaticMetadataChanged(any()); - } - @Test public void targetLiveOffsetInMedia_adjustsLiveOffsetToTargetOffset() throws Exception { long windowStartUnixTimeMs = 987_654_321_000L; @@ -9119,7 +9276,7 @@ public void targetLiveOffsetInMedia_withSetPlaybackParameters_usesPlaybackParame TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY); // Seek to default position in second stream. - player.next(); + player.seekToNextWindow(); // Play until close to the end of the available live window. TestPlayerRunHelper.playUntilPosition(player, /* windowIndex= */ 1, /* positionMs= */ 999_000); long liveOffsetAtEnd = player.getCurrentLiveOffset(); @@ -9273,7 +9430,11 @@ public void onEvents_correspondToListenerCalls() throws Exception { Format formatWithStaticMetadata = new Format.Builder() .setSampleMimeType(MimeTypes.VIDEO_H264) - .setMetadata(new Metadata(new BinaryFrame(/* id= */ "", /* data= */ new byte[0]))) + .setMetadata( + new Metadata( + new BinaryFrame(/* id= */ "", /* data= */ new byte[0]), + new TextInformationFrame( + /* id= */ "TT2", /* description= */ null, /* value= */ "title"))) .build(); // Set multiple values together. @@ -9318,7 +9479,7 @@ public void onRepeatModeChanged(int repeatMode) { TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY); player.play(); player.setMediaItem(MediaItem.fromUri("http://this-will-throw-an-exception.mp4")); - TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_IDLE); + TestPlayerRunHelper.runUntilError(player); runUntilPendingCommandsAreFullyHandled(player); player.release(); @@ -9332,9 +9493,10 @@ public void onRepeatModeChanged(int repeatMode) { verify(listener, atLeastOnce()).onPlaybackStateChanged(anyInt()); verify(listener, atLeastOnce()).onIsLoadingChanged(anyBoolean()); verify(listener, atLeastOnce()).onTracksChanged(any(), any()); - verify(listener, atLeastOnce()).onStaticMetadataChanged(any()); + verify(listener, atLeastOnce()).onMediaMetadataChanged(any()); verify(listener, atLeastOnce()).onPlayWhenReadyChanged(anyBoolean(), anyInt()); verify(listener, atLeastOnce()).onIsPlayingChanged(anyBoolean()); + verify(listener, atLeastOnce()).onPlayerErrorChanged(any()); verify(listener, atLeastOnce()).onPlayerError(any()); // Verify all the same events have been recorded with onEvents. @@ -9349,7 +9511,7 @@ public void onRepeatModeChanged(int repeatMode) { assertThat(containsEvent(allEvents, Player.EVENT_PLAYBACK_STATE_CHANGED)).isTrue(); assertThat(containsEvent(allEvents, Player.EVENT_IS_LOADING_CHANGED)).isTrue(); assertThat(containsEvent(allEvents, Player.EVENT_TRACKS_CHANGED)).isTrue(); - assertThat(containsEvent(allEvents, Player.EVENT_STATIC_METADATA_CHANGED)).isTrue(); + assertThat(containsEvent(allEvents, Player.EVENT_MEDIA_METADATA_CHANGED)).isTrue(); assertThat(containsEvent(allEvents, Player.EVENT_PLAY_WHEN_READY_CHANGED)).isTrue(); assertThat(containsEvent(allEvents, Player.EVENT_IS_PLAYING_CHANGED)).isTrue(); assertThat(containsEvent(allEvents, Player.EVENT_PLAYER_ERROR)).isTrue(); @@ -10284,6 +10446,206 @@ public void seekTo_whenTimelineEmpty_callsOnPositionDiscontinuity() { player.release(); } + @Test + public void seekBack_callsOnPositionDiscontinuity() throws Exception { + ExoPlayer player = new TestExoPlayerBuilder(context).build(); + Player.Listener listener = mock(Player.Listener.class); + player.addListener(listener); + Timeline fakeTimeline = + new FakeTimeline( + new TimelineWindowDefinition( + /* isSeekable= */ true, + /* isDynamic= */ true, + /* durationUs= */ C.msToUs(3 * C.DEFAULT_SEEK_BACK_INCREMENT_MS))); + player.setMediaSource(new FakeMediaSource(fakeTimeline)); + + player.prepare(); + TestPlayerRunHelper.playUntilPosition( + player, /* windowIndex= */ 0, /* positionMs= */ 2 * C.DEFAULT_SEEK_BACK_INCREMENT_MS); + player.seekBack(); + + ArgumentCaptor oldPosition = + ArgumentCaptor.forClass(Player.PositionInfo.class); + ArgumentCaptor newPosition = + ArgumentCaptor.forClass(Player.PositionInfo.class); + verify(listener, never()) + .onPositionDiscontinuity(any(), any(), not(eq(Player.DISCONTINUITY_REASON_SEEK))); + verify(listener) + .onPositionDiscontinuity( + oldPosition.capture(), newPosition.capture(), eq(Player.DISCONTINUITY_REASON_SEEK)); + List oldPositions = oldPosition.getAllValues(); + List newPositions = newPosition.getAllValues(); + assertThat(oldPositions.get(0).windowIndex).isEqualTo(0); + assertThat(oldPositions.get(0).positionMs) + .isIn( + Range.closed( + 2 * C.DEFAULT_SEEK_BACK_INCREMENT_MS - 20, 2 * C.DEFAULT_SEEK_BACK_INCREMENT_MS)); + assertThat(oldPositions.get(0).contentPositionMs) + .isIn( + Range.closed( + 2 * C.DEFAULT_SEEK_BACK_INCREMENT_MS - 20, 2 * C.DEFAULT_SEEK_BACK_INCREMENT_MS)); + assertThat(newPositions.get(0).windowIndex).isEqualTo(0); + assertThat(newPositions.get(0).positionMs) + .isIn( + Range.closed(C.DEFAULT_SEEK_BACK_INCREMENT_MS - 20, C.DEFAULT_SEEK_BACK_INCREMENT_MS)); + assertThat(newPositions.get(0).contentPositionMs) + .isIn( + Range.closed(C.DEFAULT_SEEK_BACK_INCREMENT_MS - 20, C.DEFAULT_SEEK_BACK_INCREMENT_MS)); + + player.release(); + } + + @Test + public void seekBack_pastZero_seeksToZero() throws Exception { + ExoPlayer player = new TestExoPlayerBuilder(context).build(); + Timeline fakeTimeline = + new FakeTimeline( + new TimelineWindowDefinition( + /* isSeekable= */ true, + /* isDynamic= */ true, + /* durationUs= */ C.msToUs(C.DEFAULT_SEEK_BACK_INCREMENT_MS))); + player.setMediaSource(new FakeMediaSource(fakeTimeline)); + + player.prepare(); + TestPlayerRunHelper.playUntilPosition( + player, /* windowIndex= */ 0, /* positionMs= */ C.DEFAULT_SEEK_BACK_INCREMENT_MS / 2); + player.seekBack(); + + assertThat(player.getCurrentPosition()).isEqualTo(0); + + player.release(); + } + + @Test + public void seekForward_callsOnPositionDiscontinuity() throws Exception { + ExoPlayer player = new TestExoPlayerBuilder(context).build(); + Player.Listener listener = mock(Player.Listener.class); + player.addListener(listener); + Timeline fakeTimeline = + new FakeTimeline( + new TimelineWindowDefinition( + /* isSeekable= */ true, + /* isDynamic= */ true, + /* durationUs= */ C.msToUs(2 * C.DEFAULT_SEEK_FORWARD_INCREMENT_MS))); + player.setMediaSource(new FakeMediaSource(fakeTimeline)); + + player.prepare(); + TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY); + player.seekForward(); + + ArgumentCaptor oldPosition = + ArgumentCaptor.forClass(Player.PositionInfo.class); + ArgumentCaptor newPosition = + ArgumentCaptor.forClass(Player.PositionInfo.class); + verify(listener, never()) + .onPositionDiscontinuity(any(), any(), not(eq(Player.DISCONTINUITY_REASON_SEEK))); + verify(listener) + .onPositionDiscontinuity( + oldPosition.capture(), newPosition.capture(), eq(Player.DISCONTINUITY_REASON_SEEK)); + List oldPositions = oldPosition.getAllValues(); + List newPositions = newPosition.getAllValues(); + assertThat(oldPositions.get(0).windowIndex).isEqualTo(0); + assertThat(oldPositions.get(0).positionMs).isEqualTo(0); + assertThat(oldPositions.get(0).contentPositionMs).isEqualTo(0); + assertThat(newPositions.get(0).windowIndex).isEqualTo(0); + assertThat(newPositions.get(0).positionMs).isEqualTo(C.DEFAULT_SEEK_FORWARD_INCREMENT_MS); + assertThat(newPositions.get(0).contentPositionMs) + .isEqualTo(C.DEFAULT_SEEK_FORWARD_INCREMENT_MS); + + player.release(); + } + + @Test + public void seekForward_pastDuration_seeksToDuration() throws Exception { + ExoPlayer player = new TestExoPlayerBuilder(context).build(); + Timeline fakeTimeline = + new FakeTimeline( + new TimelineWindowDefinition( + /* isSeekable= */ true, + /* isDynamic= */ true, + /* durationUs= */ C.msToUs(C.DEFAULT_SEEK_FORWARD_INCREMENT_MS / 2))); + player.setMediaSource(new FakeMediaSource(fakeTimeline)); + + player.prepare(); + TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY); + player.seekForward(); + + assertThat(player.getCurrentPosition()).isEqualTo(C.DEFAULT_SEEK_FORWARD_INCREMENT_MS / 2); + + player.release(); + } + + @Test + public void seekToPrevious_withPreviousWindowAndCloseToStart_seeksToPreviousWindow() { + ExoPlayer player = new TestExoPlayerBuilder(context).build(); + player.addMediaSources(ImmutableList.of(new FakeMediaSource(), new FakeMediaSource())); + player.seekTo(/* windowIndex= */ 1, C.DEFAULT_MAX_SEEK_TO_PREVIOUS_POSITION_MS); + + player.seekToPrevious(); + + assertThat(player.getCurrentWindowIndex()).isEqualTo(0); + assertThat(player.getCurrentPosition()).isEqualTo(0); + + player.release(); + } + + @Test + public void seekToPrevious_notCloseToStart_seeksToZero() { + ExoPlayer player = new TestExoPlayerBuilder(context).build(); + player.addMediaSources(ImmutableList.of(new FakeMediaSource(), new FakeMediaSource())); + player.seekTo(/* windowIndex= */ 1, C.DEFAULT_MAX_SEEK_TO_PREVIOUS_POSITION_MS + 1); + + player.seekToPrevious(); + + assertThat(player.getCurrentWindowIndex()).isEqualTo(1); + assertThat(player.getCurrentPosition()).isEqualTo(0); + + player.release(); + } + + @Test + public void seekToNext_withNextWindow_seeksToNextWindow() { + ExoPlayer player = new TestExoPlayerBuilder(context).build(); + player.addMediaSources(ImmutableList.of(new FakeMediaSource(), new FakeMediaSource())); + + player.seekToNext(); + + assertThat(player.getCurrentWindowIndex()).isEqualTo(1); + assertThat(player.getCurrentPosition()).isEqualTo(0); + + player.release(); + } + + @Test + public void seekToNext_liveWindowWithoutNextWindow_seeksToLiveEdge() throws Exception { + ExoPlayer player = new TestExoPlayerBuilder(context).build(); + Timeline timeline = + new FakeTimeline( + new TimelineWindowDefinition( + /* periodCount= */ 1, + /* id= */ 0, + /* isSeekable= */ true, + /* isDynamic= */ true, + /* isLive= */ true, + /* isPlaceholder= */ false, + /* durationUs= */ 1_000_000, + /* defaultPositionUs= */ 500_000, + TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US, + AdPlaybackState.NONE)); + MediaSource mediaSource = new FakeMediaSource(timeline); + player.setMediaSource(mediaSource); + + player.prepare(); + TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY); + player.seekTo(/* positionMs = */ 0); + player.seekToNext(); + + assertThat(player.getCurrentWindowIndex()).isEqualTo(0); + assertThat(player.getCurrentPosition()).isEqualTo(500); + + player.release(); + } + @Test public void stop_doesNotCallOnPositionDiscontinuity() throws Exception { ExoPlayer player = new TestExoPlayerBuilder(context).build(); @@ -10397,6 +10759,74 @@ public void seekTo_cancelsSourceDiscontinuity_callsOnPositionDiscontinuity() thr player.release(); } + @Test + public void newServerSideInsertedAdAtPlaybackPosition_keepsRenderersEnabled() throws Exception { + // Injecting renderer to count number of renderer resets. + AtomicReference videoRenderer = new AtomicReference<>(); + SimpleExoPlayer player = + new TestExoPlayerBuilder(context) + .setRenderersFactory( + (handler, videoListener, audioListener, textOutput, metadataOutput) -> { + videoRenderer.set(new FakeVideoRenderer(handler, videoListener)); + return new Renderer[] {videoRenderer.get()}; + }) + .build(); + // Live stream timeline with unassigned next ad group. + AdPlaybackState initialAdPlaybackState = + new AdPlaybackState( + /* adsId= */ new Object(), /* adGroupTimesUs...= */ C.TIME_END_OF_SOURCE) + .withIsServerSideInserted(/* adGroupIndex= */ 0, /* isServerSideInserted= */ true) + .withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 1) + .withAdDurationsUs(new long[][] {new long[] {10 * C.MICROS_PER_SECOND}}); + // Updated timeline with ad group at 18 seconds. + long firstSampleTimeUs = TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US; + Timeline initialTimeline = + new FakeTimeline( + new TimelineWindowDefinition( + /* periodCount= */ 1, + /* id= */ 0, + /* isSeekable= */ true, + /* isDynamic= */ true, + /* durationUs= */ C.TIME_UNSET, + initialAdPlaybackState)); + AdPlaybackState updatedAdPlaybackState = + initialAdPlaybackState.withAdGroupTimeUs( + /* adGroupIndex= */ 0, + /* adGroupTimeUs= */ firstSampleTimeUs + 18 * C.MICROS_PER_SECOND); + Timeline updatedTimeline = + new FakeTimeline( + new TimelineWindowDefinition( + /* periodCount= */ 1, + /* id= */ 0, + /* isSeekable= */ true, + /* isDynamic= */ true, + /* durationUs= */ C.TIME_UNSET, + updatedAdPlaybackState)); + // Add samples to allow player to load and start playing (but no EOS as this is a live stream). + FakeMediaSource mediaSource = + new FakeMediaSource( + initialTimeline, + DrmSessionManager.DRM_UNSUPPORTED, + (format, mediaPeriodId) -> + ImmutableList.of( + oneByteSample(firstSampleTimeUs, C.BUFFER_FLAG_KEY_FRAME), + oneByteSample(firstSampleTimeUs + 40 * C.MICROS_PER_SECOND)), + ExoPlayerTestRunner.VIDEO_FORMAT); + + // Set updated ad group once we reach 20 seconds, and then continue playing until 40 seconds. + player + .createMessage((message, payload) -> mediaSource.setNewSourceInfo(updatedTimeline)) + .setPosition(20_000) + .send(); + player.setMediaSource(mediaSource); + player.prepare(); + playUntilPosition(player, /* windowIndex= */ 0, /* positionMs= */ 40_000); + player.release(); + + // Assert that the renderer hasn't been reset despite the inserted ad group. + assertThat(videoRenderer.get().positionResetCount).isEqualTo(1); + } + // Internal methods. private static ActionSchedule.Builder addSurfaceSwitch(ActionSchedule.Builder builder) { @@ -10424,8 +10854,7 @@ private static void deliverBroadcast(Intent intent) { shadowOf(Looper.getMainLooper()).idle(); } - private static boolean containsEvent( - List eventsList, @Player.EventFlags int event) { + private static boolean containsEvent(List eventsList, @Player.Event int event) { for (Player.Events events : eventsList) { if (events.contains(event)) { return true; @@ -10435,17 +10864,20 @@ private static boolean containsEvent( } private static Player.Commands createWithDefaultCommands( - @Player.Command int... additionalCommands) { + boolean isTimelineEmpty, @Player.Command int... additionalCommands) { Player.Commands.Builder builder = new Player.Commands.Builder(); builder.addAll( COMMAND_PLAY_PAUSE, COMMAND_PREPARE_STOP, + COMMAND_SEEK_TO_DEFAULT_POSITION, + COMMAND_SEEK_TO_WINDOW, COMMAND_SET_SPEED_AND_PITCH, COMMAND_SET_SHUFFLE_MODE, COMMAND_SET_REPEAT_MODE, COMMAND_GET_CURRENT_MEDIA_ITEM, - COMMAND_GET_MEDIA_ITEMS, + COMMAND_GET_TIMELINE, COMMAND_GET_MEDIA_ITEMS_METADATA, + COMMAND_SET_MEDIA_ITEMS_METADATA, COMMAND_CHANGE_MEDIA_ITEMS, COMMAND_GET_AUDIO_ATTRIBUTES, COMMAND_GET_VOLUME, @@ -10454,13 +10886,19 @@ private static Player.Commands createWithDefaultCommands( COMMAND_SET_DEVICE_VOLUME, COMMAND_ADJUST_DEVICE_VOLUME, COMMAND_SET_VIDEO_SURFACE, - COMMAND_GET_TEXT, - COMMAND_SEEK_TO_DEFAULT_POSITION, - COMMAND_SEEK_TO_MEDIA_ITEM); + COMMAND_GET_TEXT); + if (!isTimelineEmpty) { + builder.add(COMMAND_SEEK_TO_PREVIOUS); + } builder.addAll(additionalCommands); return builder.build(); } + private static Player.Commands createWithDefaultCommands( + @Player.Command int... additionalCommands) { + return createWithDefaultCommands(/* isTimelineEmpty= */ false, additionalCommands); + } + // Internal classes. /** {@link FakeRenderer} that can sleep and be woken-up. */ @@ -10488,12 +10926,13 @@ public FakeSleepRenderer sleepOnNextRender() { } @Override - public void handleMessage(int what, @Nullable Object object) throws ExoPlaybackException { - if (what == MSG_SET_WAKEUP_LISTENER) { - assertThat(object).isNotNull(); - wakeupListenerReceiver.set((WakeupListener) object); + public void handleMessage(int messageType, @Nullable Object message) + throws ExoPlaybackException { + if (messageType == MSG_SET_WAKEUP_LISTENER) { + assertThat(message).isNotNull(); + wakeupListenerReceiver.set((WakeupListener) message); } - super.handleMessage(what, object); + super.handleMessage(messageType, message); } @Override @@ -10510,7 +10949,7 @@ private static final class CountingMessageTarget implements PlayerMessage.Target public int messageCount; @Override - public void handleMessage(int x, @Nullable Object message) { + public void handleMessage(int messageType, @Nullable Object message) { messageCount++; } } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/MediaPeriodQueueTest.java b/library/core/src/test/java/com/google/android/exoplayer2/MediaPeriodQueueTest.java index 8eaf476328e..58d0d0c47b8 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/MediaPeriodQueueTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/MediaPeriodQueueTest.java @@ -93,6 +93,7 @@ public void getNextMediaPeriodInfo_withoutAds_returnsLastMediaPeriodInfo() { /* requestedContentPositionUs= */ C.TIME_UNSET, /* endPositionUs= */ C.TIME_UNSET, /* durationUs= */ CONTENT_DURATION_US, + /* isFollowedByTransitionToSameStream= */ false, /* isLastInPeriod= */ true, /* isLastInWindow= */ true, /* nextAdGroupIndex= */ C.INDEX_UNSET); @@ -103,7 +104,10 @@ public void getNextMediaPeriodInfo_withPrerollAd_returnsCorrectMediaPeriodInfos( setupAdTimeline(/* adGroupTimesUs...= */ 0); setAdGroupLoaded(/* adGroupIndex= */ 0); assertNextMediaPeriodInfoIsAd( - /* adGroupIndex= */ 0, AD_DURATION_US, /* contentPositionUs= */ C.TIME_UNSET); + /* adGroupIndex= */ 0, + AD_DURATION_US, + /* contentPositionUs= */ C.TIME_UNSET, + /* isFollowedByTransitionToSameStream= */ false); advance(); assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( /* periodUid= */ firstPeriodUid, @@ -111,6 +115,7 @@ public void getNextMediaPeriodInfo_withPrerollAd_returnsCorrectMediaPeriodInfos( /* requestedContentPositionUs= */ C.TIME_UNSET, /* endPositionUs= */ C.TIME_UNSET, /* durationUs= */ CONTENT_DURATION_US, + /* isFollowedByTransitionToSameStream= */ false, /* isLastInPeriod= */ true, /* isLastInWindow= */ true, /* nextAdGroupIndex= */ C.INDEX_UNSET); @@ -125,6 +130,7 @@ public void getNextMediaPeriodInfo_withMidrollAds_returnsCorrectMediaPeriodInfos /* requestedContentPositionUs= */ C.TIME_UNSET, /* endPositionUs= */ FIRST_AD_START_TIME_US, /* durationUs= */ FIRST_AD_START_TIME_US, + /* isFollowedByTransitionToSameStream= */ false, /* isLastInPeriod= */ false, /* isLastInWindow= */ false, /* nextAdGroupIndex= */ 0); @@ -132,10 +138,14 @@ public void getNextMediaPeriodInfo_withMidrollAds_returnsCorrectMediaPeriodInfos assertNextMediaPeriodInfoIsAd( /* adGroupIndex= */ 0, /* adDurationUs= */ C.TIME_UNSET, - /* contentPositionUs= */ FIRST_AD_START_TIME_US); + /* contentPositionUs= */ FIRST_AD_START_TIME_US, + /* isFollowedByTransitionToSameStream= */ false); setAdGroupLoaded(/* adGroupIndex= */ 0); assertNextMediaPeriodInfoIsAd( - /* adGroupIndex= */ 0, AD_DURATION_US, /* contentPositionUs= */ FIRST_AD_START_TIME_US); + /* adGroupIndex= */ 0, + AD_DURATION_US, + /* contentPositionUs= */ FIRST_AD_START_TIME_US, + /* isFollowedByTransitionToSameStream= */ false); advance(); assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( /* periodUid= */ firstPeriodUid, @@ -143,13 +153,17 @@ public void getNextMediaPeriodInfo_withMidrollAds_returnsCorrectMediaPeriodInfos /* requestedContentPositionUs= */ FIRST_AD_START_TIME_US, /* endPositionUs= */ SECOND_AD_START_TIME_US, /* durationUs= */ SECOND_AD_START_TIME_US, + /* isFollowedByTransitionToSameStream= */ false, /* isLastInPeriod= */ false, /* isLastInWindow= */ false, /* nextAdGroupIndex= */ 1); advance(); setAdGroupLoaded(/* adGroupIndex= */ 1); assertNextMediaPeriodInfoIsAd( - /* adGroupIndex= */ 1, AD_DURATION_US, /* contentPositionUs= */ SECOND_AD_START_TIME_US); + /* adGroupIndex= */ 1, + AD_DURATION_US, + /* contentPositionUs= */ SECOND_AD_START_TIME_US, + /* isFollowedByTransitionToSameStream= */ false); advance(); assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( /* periodUid= */ firstPeriodUid, @@ -157,6 +171,7 @@ public void getNextMediaPeriodInfo_withMidrollAds_returnsCorrectMediaPeriodInfos /* requestedContentPositionUs= */ SECOND_AD_START_TIME_US, /* endPositionUs= */ C.TIME_UNSET, /* durationUs= */ CONTENT_DURATION_US, + /* isFollowedByTransitionToSameStream= */ false, /* isLastInPeriod= */ true, /* isLastInWindow= */ true, /* nextAdGroupIndex= */ C.INDEX_UNSET); @@ -171,13 +186,17 @@ public void getNextMediaPeriodInfo_withMidrollAndPostroll_returnsCorrectMediaPer /* requestedContentPositionUs= */ C.TIME_UNSET, /* endPositionUs= */ FIRST_AD_START_TIME_US, /* durationUs= */ FIRST_AD_START_TIME_US, + /* isFollowedByTransitionToSameStream= */ false, /* isLastInPeriod= */ false, /* isLastInWindow= */ false, /* nextAdGroupIndex= */ 0); advance(); setAdGroupLoaded(/* adGroupIndex= */ 0); assertNextMediaPeriodInfoIsAd( - /* adGroupIndex= */ 0, AD_DURATION_US, /* contentPositionUs= */ FIRST_AD_START_TIME_US); + /* adGroupIndex= */ 0, + AD_DURATION_US, + /* contentPositionUs= */ FIRST_AD_START_TIME_US, + /* isFollowedByTransitionToSameStream= */ false); advance(); assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( /* periodUid= */ firstPeriodUid, @@ -185,13 +204,88 @@ public void getNextMediaPeriodInfo_withMidrollAndPostroll_returnsCorrectMediaPer /* requestedContentPositionUs= */ FIRST_AD_START_TIME_US, /* endPositionUs= */ C.TIME_END_OF_SOURCE, /* durationUs= */ CONTENT_DURATION_US, + /* isFollowedByTransitionToSameStream= */ false, + /* isLastInPeriod= */ false, + /* isLastInWindow= */ false, + /* nextAdGroupIndex= */ 1); + advance(); + setAdGroupLoaded(/* adGroupIndex= */ 1); + assertNextMediaPeriodInfoIsAd( + /* adGroupIndex= */ 1, + AD_DURATION_US, + /* contentPositionUs= */ CONTENT_DURATION_US, + /* isFollowedByTransitionToSameStream= */ false); + advance(); + assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( + /* periodUid= */ firstPeriodUid, + /* startPositionUs= */ CONTENT_DURATION_US - 1, + /* requestedContentPositionUs= */ CONTENT_DURATION_US, + /* endPositionUs= */ C.TIME_UNSET, + /* durationUs= */ CONTENT_DURATION_US, + /* isFollowedByTransitionToSameStream= */ false, + /* isLastInPeriod= */ true, + /* isLastInWindow= */ true, + /* nextAdGroupIndex= */ C.INDEX_UNSET); + } + + @Test + public void getNextMediaPeriodInfo_withAdGroupResumeOffsets_returnsCorrectMediaPeriodInfos() { + adPlaybackState = + new AdPlaybackState( + /* adsId= */ new Object(), + /* adGroupTimesUs...= */ 0, + FIRST_AD_START_TIME_US, + C.TIME_END_OF_SOURCE) + .withContentDurationUs(CONTENT_DURATION_US) + .withContentResumeOffsetUs(/* adGroupIndex= */ 0, /* contentResumeOffsetUs= */ 2000) + .withContentResumeOffsetUs(/* adGroupIndex= */ 1, /* contentResumeOffsetUs= */ 3000) + .withContentResumeOffsetUs(/* adGroupIndex= */ 2, /* contentResumeOffsetUs= */ 4000); + SinglePeriodAdTimeline adTimeline = + new SinglePeriodAdTimeline(CONTENT_TIMELINE, adPlaybackState); + setupTimeline(adTimeline); + + setAdGroupLoaded(/* adGroupIndex= */ 0); + assertNextMediaPeriodInfoIsAd( + /* adGroupIndex= */ 0, + AD_DURATION_US, + /* contentPositionUs= */ C.TIME_UNSET, + /* isFollowedByTransitionToSameStream= */ false); + advance(); + assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( + /* periodUid= */ firstPeriodUid, + /* startPositionUs= */ 2000, + /* requestedContentPositionUs= */ C.TIME_UNSET, + /* endPositionUs= */ FIRST_AD_START_TIME_US, + /* durationUs= */ FIRST_AD_START_TIME_US, + /* isFollowedByTransitionToSameStream= */ false, /* isLastInPeriod= */ false, /* isLastInWindow= */ false, /* nextAdGroupIndex= */ 1); advance(); setAdGroupLoaded(/* adGroupIndex= */ 1); assertNextMediaPeriodInfoIsAd( - /* adGroupIndex= */ 1, AD_DURATION_US, /* contentPositionUs= */ CONTENT_DURATION_US); + /* adGroupIndex= */ 1, + AD_DURATION_US, + /* contentPositionUs= */ FIRST_AD_START_TIME_US, + /* isFollowedByTransitionToSameStream= */ false); + advance(); + assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( + /* periodUid= */ firstPeriodUid, + /* startPositionUs= */ FIRST_AD_START_TIME_US + 3000, + /* requestedContentPositionUs= */ FIRST_AD_START_TIME_US, + /* endPositionUs= */ C.TIME_END_OF_SOURCE, + /* durationUs= */ CONTENT_DURATION_US, + /* isFollowedByTransitionToSameStream= */ false, + /* isLastInPeriod= */ false, + /* isLastInWindow= */ false, + /* nextAdGroupIndex= */ 2); + advance(); + setAdGroupLoaded(/* adGroupIndex= */ 2); + assertNextMediaPeriodInfoIsAd( + /* adGroupIndex= */ 2, + AD_DURATION_US, + /* contentPositionUs= */ CONTENT_DURATION_US, + /* isFollowedByTransitionToSameStream= */ false); advance(); assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( /* periodUid= */ firstPeriodUid, @@ -199,6 +293,78 @@ public void getNextMediaPeriodInfo_withMidrollAndPostroll_returnsCorrectMediaPer /* requestedContentPositionUs= */ CONTENT_DURATION_US, /* endPositionUs= */ C.TIME_UNSET, /* durationUs= */ CONTENT_DURATION_US, + /* isFollowedByTransitionToSameStream= */ false, + /* isLastInPeriod= */ true, + /* isLastInWindow= */ true, + /* nextAdGroupIndex= */ C.INDEX_UNSET); + } + + @Test + public void getNextMediaPeriodInfo_withServerSideInsertedAds_returnsCorrectMediaPeriodInfos() { + adPlaybackState = + new AdPlaybackState( + /* adsId= */ new Object(), + /* adGroupTimesUs...= */ 0, + FIRST_AD_START_TIME_US, + SECOND_AD_START_TIME_US) + .withContentDurationUs(CONTENT_DURATION_US) + .withIsServerSideInserted(/* adGroupIndex= */ 0, /* isServerSideInserted= */ true) + .withIsServerSideInserted(/* adGroupIndex= */ 1, /* isServerSideInserted= */ true) + .withIsServerSideInserted(/* adGroupIndex= */ 2, /* isServerSideInserted= */ true); + SinglePeriodAdTimeline adTimeline = + new SinglePeriodAdTimeline(CONTENT_TIMELINE, adPlaybackState); + setupTimeline(adTimeline); + + setAdGroupLoaded(/* adGroupIndex= */ 0); + assertNextMediaPeriodInfoIsAd( + /* adGroupIndex= */ 0, + AD_DURATION_US, + /* contentPositionUs= */ C.TIME_UNSET, + /* isFollowedByTransitionToSameStream= */ true); + advance(); + assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( + /* periodUid= */ firstPeriodUid, + /* startPositionUs= */ 0, + /* requestedContentPositionUs= */ C.TIME_UNSET, + /* endPositionUs= */ FIRST_AD_START_TIME_US, + /* durationUs= */ FIRST_AD_START_TIME_US, + /* isFollowedByTransitionToSameStream= */ true, + /* isLastInPeriod= */ false, + /* isLastInWindow= */ false, + /* nextAdGroupIndex= */ 1); + advance(); + setAdGroupLoaded(/* adGroupIndex= */ 1); + assertNextMediaPeriodInfoIsAd( + /* adGroupIndex= */ 1, + AD_DURATION_US, + /* contentPositionUs= */ FIRST_AD_START_TIME_US, + /* isFollowedByTransitionToSameStream= */ true); + advance(); + assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( + /* periodUid= */ firstPeriodUid, + /* startPositionUs= */ FIRST_AD_START_TIME_US, + /* requestedContentPositionUs= */ FIRST_AD_START_TIME_US, + /* endPositionUs= */ SECOND_AD_START_TIME_US, + /* durationUs= */ SECOND_AD_START_TIME_US, + /* isFollowedByTransitionToSameStream= */ true, + /* isLastInPeriod= */ false, + /* isLastInWindow= */ false, + /* nextAdGroupIndex= */ 2); + advance(); + setAdGroupLoaded(/* adGroupIndex= */ 2); + assertNextMediaPeriodInfoIsAd( + /* adGroupIndex= */ 2, + AD_DURATION_US, + /* contentPositionUs= */ SECOND_AD_START_TIME_US, + /* isFollowedByTransitionToSameStream= */ true); + advance(); + assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( + /* periodUid= */ firstPeriodUid, + /* startPositionUs= */ SECOND_AD_START_TIME_US, + /* requestedContentPositionUs= */ SECOND_AD_START_TIME_US, + /* endPositionUs= */ C.TIME_UNSET, + /* durationUs= */ CONTENT_DURATION_US, + /* isFollowedByTransitionToSameStream= */ false, /* isLastInPeriod= */ true, /* isLastInWindow= */ true, /* nextAdGroupIndex= */ C.INDEX_UNSET); @@ -213,6 +379,7 @@ public void getNextMediaPeriodInfo_withPostrollLoadError_returnsEmptyFinalMediaP /* requestedContentPositionUs= */ C.TIME_UNSET, /* endPositionUs= */ C.TIME_END_OF_SOURCE, /* durationUs= */ CONTENT_DURATION_US, + /* isFollowedByTransitionToSameStream= */ false, /* isLastInPeriod= */ false, /* isLastInWindow= */ false, /* nextAdGroupIndex= */ 0); @@ -224,6 +391,7 @@ public void getNextMediaPeriodInfo_withPostrollLoadError_returnsEmptyFinalMediaP /* requestedContentPositionUs= */ CONTENT_DURATION_US, /* endPositionUs= */ C.TIME_UNSET, /* durationUs= */ CONTENT_DURATION_US, + /* isFollowedByTransitionToSameStream= */ false, /* isLastInPeriod= */ true, /* isLastInWindow= */ true, /* nextAdGroupIndex= */ C.INDEX_UNSET); @@ -236,7 +404,10 @@ public void getNextMediaPeriodInfo_withPlayedAdGroups_returnsCorrectMediaPeriodI setAdGroupLoaded(/* adGroupIndex= */ 1); setAdGroupLoaded(/* adGroupIndex= */ 2); assertNextMediaPeriodInfoIsAd( - /* adGroupIndex= */ 0, AD_DURATION_US, /* contentPositionUs= */ C.TIME_UNSET); + /* adGroupIndex= */ 0, + AD_DURATION_US, + /* contentPositionUs= */ C.TIME_UNSET, + /* isFollowedByTransitionToSameStream= */ false); setAdGroupPlayed(/* adGroupIndex= */ 0); clear(); assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( @@ -245,6 +416,7 @@ public void getNextMediaPeriodInfo_withPlayedAdGroups_returnsCorrectMediaPeriodI /* requestedContentPositionUs= */ C.TIME_UNSET, /* endPositionUs= */ FIRST_AD_START_TIME_US, /* durationUs= */ FIRST_AD_START_TIME_US, + /* isFollowedByTransitionToSameStream= */ false, /* isLastInPeriod= */ false, /* isLastInWindow= */ false, /* nextAdGroupIndex= */ 1); @@ -256,6 +428,7 @@ public void getNextMediaPeriodInfo_withPlayedAdGroups_returnsCorrectMediaPeriodI /* requestedContentPositionUs= */ C.TIME_UNSET, /* endPositionUs= */ C.TIME_END_OF_SOURCE, /* durationUs= */ CONTENT_DURATION_US, + /* isFollowedByTransitionToSameStream= */ false, /* isLastInPeriod= */ false, /* isLastInWindow= */ false, /* nextAdGroupIndex= */ 2); @@ -267,6 +440,7 @@ public void getNextMediaPeriodInfo_withPlayedAdGroups_returnsCorrectMediaPeriodI /* requestedContentPositionUs= */ C.TIME_UNSET, /* endPositionUs= */ C.TIME_UNSET, /* durationUs= */ CONTENT_DURATION_US, + /* isFollowedByTransitionToSameStream= */ false, /* isLastInPeriod= */ true, /* isLastInWindow= */ true, /* nextAdGroupIndex= */ C.INDEX_UNSET); @@ -290,6 +464,7 @@ public void getNextMediaPeriodInfo_inMultiPeriodWindow_returnsCorrectMediaPeriod /* endPositionUs= */ C.TIME_UNSET, /* durationUs= */ CONTENT_DURATION_US + TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US, + /* isFollowedByTransitionToSameStream= */ false, /* isLastInPeriod= */ true, /* isLastInWindow= */ false, /* nextAdGroupIndex= */ C.INDEX_UNSET); @@ -300,11 +475,96 @@ public void getNextMediaPeriodInfo_inMultiPeriodWindow_returnsCorrectMediaPeriod /* requestedContentPositionUs= */ 0, /* endPositionUs= */ C.TIME_UNSET, /* durationUs= */ CONTENT_DURATION_US, + /* isFollowedByTransitionToSameStream= */ false, /* isLastInPeriod= */ true, /* isLastInWindow= */ true, /* nextAdGroupIndex= */ C.INDEX_UNSET); } + @Test + public void + updateQueuedPeriods_withDurationChangeInPlayingContent_handlesChangeAndRemovesPeriodsAfterChangedPeriod() { + setupAdTimeline(/* adGroupTimesUs...= */ FIRST_AD_START_TIME_US); + setAdGroupLoaded(/* adGroupIndex= */ 0); + enqueueNext(); // Content before ad. + enqueueNext(); // Ad. + enqueueNext(); // Content after ad. + + // Change position of first ad (= change duration of playing content before first ad). + updateAdPlaybackStateAndTimeline(/* adGroupTimesUs...= */ FIRST_AD_START_TIME_US - 2000); + setAdGroupLoaded(/* adGroupIndex= */ 0); + long maxRendererReadPositionUs = FIRST_AD_START_TIME_US - 3000; + boolean changeHandled = + mediaPeriodQueue.updateQueuedPeriods( + playbackInfo.timeline, /* rendererPositionUs= */ 0, maxRendererReadPositionUs); + + assertThat(changeHandled).isTrue(); + assertThat(getQueueLength()).isEqualTo(1); + assertThat(mediaPeriodQueue.getPlayingPeriod().info.endPositionUs) + .isEqualTo(FIRST_AD_START_TIME_US - 2000); + assertThat(mediaPeriodQueue.getPlayingPeriod().info.durationUs) + .isEqualTo(FIRST_AD_START_TIME_US - 2000); + } + + @Test + public void + updateQueuedPeriods_withDurationChangeInPlayingContentAfterReadingPosition_doesntHandleChangeAndRemovesPeriodsAfterChangedPeriod() { + setupAdTimeline(/* adGroupTimesUs...= */ FIRST_AD_START_TIME_US); + setAdGroupLoaded(/* adGroupIndex= */ 0); + enqueueNext(); // Content before ad. + enqueueNext(); // Ad. + enqueueNext(); // Content after ad. + + // Change position of first ad (= change duration of playing content before first ad). + updateAdPlaybackStateAndTimeline(/* adGroupTimesUs...= */ FIRST_AD_START_TIME_US - 2000); + setAdGroupLoaded(/* adGroupIndex= */ 0); + long maxRendererReadPositionUs = FIRST_AD_START_TIME_US - 1000; + boolean changeHandled = + mediaPeriodQueue.updateQueuedPeriods( + playbackInfo.timeline, /* rendererPositionUs= */ 0, maxRendererReadPositionUs); + + assertThat(changeHandled).isFalse(); + assertThat(getQueueLength()).isEqualTo(1); + assertThat(mediaPeriodQueue.getPlayingPeriod().info.endPositionUs) + .isEqualTo(FIRST_AD_START_TIME_US - 2000); + assertThat(mediaPeriodQueue.getPlayingPeriod().info.durationUs) + .isEqualTo(FIRST_AD_START_TIME_US - 2000); + } + + @Test + public void + updateQueuedPeriods_withDurationChangeInPlayingContentAfterReadingPositionInServerSideInsertedAd_handlesChangeAndRemovesPeriodsAfterChangedPeriod() { + adPlaybackState = + new AdPlaybackState(/* adsId= */ new Object(), /* adGroupTimes... */ FIRST_AD_START_TIME_US) + .withIsServerSideInserted(/* adGroupIndex= */ 0, /* isServerSideInserted= */ true); + SinglePeriodAdTimeline adTimeline = + new SinglePeriodAdTimeline(CONTENT_TIMELINE, adPlaybackState); + setupTimeline(adTimeline); + setAdGroupLoaded(/* adGroupIndex= */ 0); + enqueueNext(); // Content before ad. + enqueueNext(); // Ad. + enqueueNext(); // Content after ad. + + // Change position of first ad (= change duration of playing content before first ad). + adPlaybackState = + new AdPlaybackState( + /* adsId= */ new Object(), /* adGroupTimesUs...= */ FIRST_AD_START_TIME_US - 2000) + .withIsServerSideInserted(/* adGroupIndex= */ 0, /* isServerSideInserted= */ true); + updateTimeline(); + setAdGroupLoaded(/* adGroupIndex= */ 0); + long maxRendererReadPositionUs = FIRST_AD_START_TIME_US - 1000; + boolean changeHandled = + mediaPeriodQueue.updateQueuedPeriods( + playbackInfo.timeline, /* rendererPositionUs= */ 0, maxRendererReadPositionUs); + + assertThat(changeHandled).isTrue(); + assertThat(getQueueLength()).isEqualTo(1); + assertThat(mediaPeriodQueue.getPlayingPeriod().info.endPositionUs) + .isEqualTo(FIRST_AD_START_TIME_US - 2000); + assertThat(mediaPeriodQueue.getPlayingPeriod().info.durationUs) + .isEqualTo(FIRST_AD_START_TIME_US - 2000); + } + @Test public void updateQueuedPeriods_withDurationChangeAfterReadingPeriod_handlesChangeAndRemovesPeriodsAfterChangedPeriod() { @@ -537,7 +797,9 @@ private void setAdGroupLoaded(int adGroupIndex) { long[][] newDurations = new long[adPlaybackState.adGroupCount][]; for (int i = 0; i < adPlaybackState.adGroupCount; i++) { newDurations[i] = - i == adGroupIndex ? new long[] {AD_DURATION_US} : adPlaybackState.adGroups[i].durationsUs; + i == adGroupIndex + ? new long[] {AD_DURATION_US} + : adPlaybackState.getAdGroup(i).durationsUs; } adPlaybackState = adPlaybackState @@ -548,7 +810,7 @@ private void setAdGroupLoaded(int adGroupIndex) { } private void setAdGroupPlayed(int adGroupIndex) { - for (int i = 0; i < adPlaybackState.adGroups[adGroupIndex].count; i++) { + for (int i = 0; i < adPlaybackState.getAdGroup(adGroupIndex).count; i++) { adPlaybackState = adPlaybackState.withPlayedAd(adGroupIndex, /* adIndexInAdGroup= */ i); } updateTimeline(); @@ -584,6 +846,7 @@ private void assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( long requestedContentPositionUs, long endPositionUs, long durationUs, + boolean isFollowedByTransitionToSameStream, boolean isLastInPeriod, boolean isLastInWindow, int nextAdGroupIndex) { @@ -595,13 +858,17 @@ private void assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( requestedContentPositionUs, endPositionUs, durationUs, + isFollowedByTransitionToSameStream, isLastInPeriod, isLastInWindow, /* isFinal= */ isLastInWindow)); } private void assertNextMediaPeriodInfoIsAd( - int adGroupIndex, long adDurationUs, long contentPositionUs) { + int adGroupIndex, + long adDurationUs, + long contentPositionUs, + boolean isFollowedByTransitionToSameStream) { assertThat(getNextMediaPeriodInfo()) .isEqualTo( new MediaPeriodInfo( @@ -614,6 +881,7 @@ private void assertNextMediaPeriodInfoIsAd( contentPositionUs, /* endPositionUs= */ C.TIME_UNSET, adDurationUs, + isFollowedByTransitionToSameStream, /* isLastInTimelinePeriod= */ false, /* isLastInTimelineWindow= */ false, /* isFinal= */ false)); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/SimpleExoPlayerTest.java b/library/core/src/test/java/com/google/android/exoplayer2/SimpleExoPlayerTest.java index fb4ad4c648a..4fb49e8b796 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/SimpleExoPlayerTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/SimpleExoPlayerTest.java @@ -21,6 +21,7 @@ import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.mock; @@ -46,9 +47,8 @@ @RunWith(AndroidJUnit4.class) public class SimpleExoPlayerTest { - // TODO(b/143232359): Revert to @Config(sdk = Config.ALL_SDKS) once b/143232359 is resolved @Test - @Config(minSdk = Config.OLDEST_SDK, maxSdk = Config.TARGET_SDK) + @Config(sdk = Config.ALL_SDKS) public void builder_inBackgroundThread_doesNotThrow() throws Exception { Thread builderThread = new Thread( @@ -62,6 +62,22 @@ public void builder_inBackgroundThread_doesNotThrow() throws Exception { assertThat(builderThrow.get()).isNull(); } + @Test + public void onPlaylistMetadataChanged_calledWhenPlaylistMetadataSet() { + SimpleExoPlayer player = + new SimpleExoPlayer.Builder(ApplicationProvider.getApplicationContext()).build(); + Player.Listener playerListener = mock(Player.Listener.class); + player.addListener(playerListener); + AnalyticsListener analyticsListener = mock(AnalyticsListener.class); + player.addAnalyticsListener(analyticsListener); + + MediaMetadata mediaMetadata = new MediaMetadata.Builder().setTitle("test").build(); + player.setPlaylistMetadata(mediaMetadata); + + verify(playerListener).onPlaylistMetadataChanged(mediaMetadata); + verify(analyticsListener).onPlaylistMetadataChanged(any(), eq(mediaMetadata)); + } + @Test public void release_triggersAllPendingEventsInAnalyticsListeners() throws Exception { SimpleExoPlayer player = diff --git a/library/core/src/test/java/com/google/android/exoplayer2/analytics/AnalyticsCollectorTest.java b/library/core/src/test/java/com/google/android/exoplayer2/analytics/AnalyticsCollectorTest.java index 9545209805e..549fa0cd5b3 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/analytics/AnalyticsCollectorTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/analytics/AnalyticsCollectorTest.java @@ -71,6 +71,7 @@ import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Renderer; @@ -730,7 +731,9 @@ public void reprepareAfterError() throws Exception { new ActionSchedule.Builder(TAG) .pause() .waitForPlaybackState(Player.STATE_READY) - .throwPlaybackException(ExoPlaybackException.createForSource(new IOException())) + .throwPlaybackException( + ExoPlaybackException.createForSource( + new IOException(), PlaybackException.ERROR_CODE_IO_UNSPECIFIED)) .waitForPlaybackState(Player.STATE_IDLE) .seek(/* positionMs= */ 0) .prepare() @@ -1348,11 +1351,7 @@ public void seekAfterMidroll() throws Exception { assertThat(listener.getEvents(EVENT_SEEK_STARTED)).containsExactly(contentBeforeMidroll); assertThat(listener.getEvents(EVENT_SEEK_PROCESSED)).containsExactly(contentAfterMidroll); assertThat(listener.getEvents(EVENT_IS_LOADING_CHANGED)) - .containsExactly( - contentBeforeMidroll, - contentBeforeMidroll, - midrollAd, - midrollAd) + .containsExactly(contentBeforeMidroll, contentBeforeMidroll, midrollAd, midrollAd) .inOrder(); assertThat(listener.getEvents(EVENT_TRACKS_CHANGED)) .containsExactly(contentBeforeMidroll, midrollAd, contentAfterMidroll); @@ -1553,7 +1552,9 @@ protected void onEnabled(boolean joining, boolean mayRenderStartOfStream) throws ExoPlaybackException { // Fail when enabling the renderer. This will happen during the period transition. throw createRendererException( - new IllegalStateException(), ExoPlayerTestRunner.AUDIO_FORMAT); + new IllegalStateException(), + ExoPlayerTestRunner.AUDIO_FORMAT, + PlaybackException.ERROR_CODE_UNSPECIFIED); } } }; @@ -1585,7 +1586,9 @@ public void render(long positionUs, long realtimeUs) throws ExoPlaybackException // Fail when rendering the audio stream. This will happen during the period // transition. throw createRendererException( - new IllegalStateException(), ExoPlayerTestRunner.AUDIO_FORMAT); + new IllegalStateException(), + ExoPlayerTestRunner.AUDIO_FORMAT, + PlaybackException.ERROR_CODE_UNSPECIFIED); } } }; @@ -1620,7 +1623,9 @@ protected void onStreamChanged( // period transition (as the first time is when enabling the stream initially). if (++streamChangeCount == 2) { throw createRendererException( - new IllegalStateException(), ExoPlayerTestRunner.AUDIO_FORMAT); + new IllegalStateException(), + ExoPlayerTestRunner.AUDIO_FORMAT, + PlaybackException.ERROR_CODE_UNSPECIFIED); } } } @@ -1665,7 +1670,7 @@ public void onEvents_isReportedWithCorrectEventTimes() throws Exception { TestPlayerRunHelper.runUntilPositionDiscontinuity( player, Player.DISCONTINUITY_REASON_AUTO_TRANSITION); player.setMediaItem(MediaItem.fromUri("http://this-will-throw-an-exception.mp4")); - TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_IDLE); + TestPlayerRunHelper.runUntilError(player); ShadowLooper.runMainLooperToNextTask(); player.release(); surface.release(); @@ -1946,7 +1951,7 @@ public void recursiveListenerInvocation_arrivesInCorrectOrder() { spy( new AnalyticsListener() { @Override - public void onPlayerError(EventTime eventTime, ExoPlaybackException error) { + public void onPlayerError(EventTime eventTime, PlaybackException error) { analyticsCollector.onSurfaceSizeChanged(/* width= */ 0, /* height= */ 0); } }); @@ -1955,7 +1960,9 @@ public void onPlayerError(EventTime eventTime, ExoPlaybackException error) { analyticsCollector.addListener(listener2); analyticsCollector.addListener(listener3); - analyticsCollector.onPlayerError(ExoPlaybackException.createForSource(new IOException())); + analyticsCollector.onPlayerError( + ExoPlaybackException.createForSource( + new IOException(), PlaybackException.ERROR_CODE_IO_UNSPECIFIED)); InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); inOrder.verify(listener1).onPlayerError(any(), any()); @@ -2145,7 +2152,7 @@ public void onIsLoadingChanged(EventTime eventTime, boolean isLoading) { } @Override - public void onPlayerError(EventTime eventTime, ExoPlaybackException error) { + public void onPlayerError(EventTime eventTime, PlaybackException error) { reportedEvents.add(new ReportedEvent(EVENT_PLAYER_ERROR, eventTime)); } @@ -2237,7 +2244,7 @@ public void onDecoderDisabled( } @Override - public void onAudioEnabled(EventTime eventTime, DecoderCounters counters) { + public void onAudioEnabled(EventTime eventTime, DecoderCounters decoderCounters) { reportedEvents.add(new ReportedEvent(EVENT_AUDIO_ENABLED, eventTime)); } @@ -2256,7 +2263,7 @@ public void onAudioInputFormatChanged(EventTime eventTime, Format format) { } @Override - public void onAudioDisabled(EventTime eventTime, DecoderCounters counters) { + public void onAudioDisabled(EventTime eventTime, DecoderCounters decoderCounters) { reportedEvents.add(new ReportedEvent(EVENT_AUDIO_DISABLED, eventTime)); } @@ -2277,7 +2284,7 @@ public void onAudioUnderrun( } @Override - public void onVideoEnabled(EventTime eventTime, DecoderCounters counters) { + public void onVideoEnabled(EventTime eventTime, DecoderCounters decoderCounters) { reportedEvents.add(new ReportedEvent(EVENT_VIDEO_ENABLED, eventTime)); } @@ -2301,7 +2308,7 @@ public void onDroppedVideoFrames(EventTime eventTime, int droppedFrames, long el } @Override - public void onVideoDisabled(EventTime eventTime, DecoderCounters counters) { + public void onVideoDisabled(EventTime eventTime, DecoderCounters decoderCounters) { reportedEvents.add(new ReportedEvent(EVENT_VIDEO_DISABLED, eventTime)); } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/audio/DecoderAudioRendererTest.java b/library/core/src/test/java/com/google/android/exoplayer2/audio/DecoderAudioRendererTest.java index f24e09346f4..7a6fe531afe 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/audio/DecoderAudioRendererTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/audio/DecoderAudioRendererTest.java @@ -167,7 +167,5 @@ protected DecoderException decode( } return null; } - } - } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioSinkTest.java b/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioSinkTest.java index f1a4fb91f6e..ae36f7edad9 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioSinkTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioSinkTest.java @@ -19,8 +19,6 @@ import static com.google.android.exoplayer2.audio.AudioSink.SINK_FORMAT_SUPPORTED_DIRECTLY; import static com.google.android.exoplayer2.audio.AudioSink.SINK_FORMAT_SUPPORTED_WITH_TRANSCODING; import static com.google.common.truth.Truth.assertThat; -import static org.robolectric.annotation.Config.OLDEST_SDK; -import static org.robolectric.annotation.Config.TARGET_SDK; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.C; @@ -219,7 +217,7 @@ public void floatPcmNeedsTranscodingIfFloatOutputDisabled() { .isEqualTo(SINK_FORMAT_SUPPORTED_WITH_TRANSCODING); } - @Config(minSdk = OLDEST_SDK, maxSdk = 20) + @Config(maxSdk = 20) @Test public void floatPcmNeedsTranscodingIfFloatOutputEnabledBeforeApi21() { defaultAudioSink = @@ -237,7 +235,7 @@ public void floatPcmNeedsTranscodingIfFloatOutputEnabledBeforeApi21() { .isEqualTo(SINK_FORMAT_SUPPORTED_WITH_TRANSCODING); } - @Config(minSdk = 21, maxSdk = TARGET_SDK) + @Config(minSdk = 21) @Test public void floatOutputSupportedIfFloatOutputEnabledFromApi21() { defaultAudioSink = diff --git a/library/core/src/test/java/com/google/android/exoplayer2/audio/MediaCodecAudioRendererTest.java b/library/core/src/test/java/com/google/android/exoplayer2/audio/MediaCodecAudioRendererTest.java index c69deeaeef5..9a26fdde87b 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/audio/MediaCodecAudioRendererTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/audio/MediaCodecAudioRendererTest.java @@ -37,6 +37,7 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.RendererConfiguration; import com.google.android.exoplayer2.drm.DrmSessionEventListener; import com.google.android.exoplayer2.drm.DrmSessionManager; @@ -55,10 +56,8 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; -import org.robolectric.annotation.Config; /** Unit tests for {@link MediaCodecAudioRenderer} */ -@Config(sdk = 29) @RunWith(AndroidJUnit4.class) public class MediaCodecAudioRendererTest { @Rule public final MockitoRule mockito = MockitoJUnit.rule(); @@ -245,7 +244,9 @@ protected void onOutputFormatChanged(Format format, @Nullable MediaFormat mediaF "rendererName", /* rendererIndex= */ 0, format, - C.FORMAT_HANDLED)); + C.FORMAT_HANDLED, + /* isRecoverable= */ false, + PlaybackException.ERROR_CODE_UNSPECIFIED)); } } }; diff --git a/library/core/src/test/java/com/google/android/exoplayer2/audio/SilenceSkippingAudioProcessorTest.java b/library/core/src/test/java/com/google/android/exoplayer2/audio/SilenceSkippingAudioProcessorTest.java index 9c14c37587b..81768947029 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/audio/SilenceSkippingAudioProcessorTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/audio/SilenceSkippingAudioProcessorTest.java @@ -88,9 +88,7 @@ public void skipInSilentSignal_skipsEverything() throws Exception { // Given a signal with only noise. InputBufferProvider inputBufferProvider = getInputBufferProviderForAlternatingSilenceAndNoise( - TEST_SIGNAL_SILENCE_DURATION_MS, - /* noiseDurationMs= */ 0, - TEST_SIGNAL_FRAME_COUNT); + TEST_SIGNAL_SILENCE_DURATION_MS, /* noiseDurationMs= */ 0, TEST_SIGNAL_FRAME_COUNT); // When processing the entire signal. silenceSkippingAudioProcessor.setEnabled(true); @@ -110,9 +108,7 @@ public void skipInNoisySignal_skipsNothing() throws Exception { // Given a signal with only silence. InputBufferProvider inputBufferProvider = getInputBufferProviderForAlternatingSilenceAndNoise( - /* silenceDurationMs= */ 0, - TEST_SIGNAL_NOISE_DURATION_MS, - TEST_SIGNAL_FRAME_COUNT); + /* silenceDurationMs= */ 0, TEST_SIGNAL_NOISE_DURATION_MS, TEST_SIGNAL_FRAME_COUNT); // When processing the entire signal. SilenceSkippingAudioProcessor silenceSkippingAudioProcessor = @@ -287,9 +283,7 @@ private static long process( * between silence/noise of the specified durations to fill {@code totalFrameCount}. */ private static InputBufferProvider getInputBufferProviderForAlternatingSilenceAndNoise( - int silenceDurationMs, - int noiseDurationMs, - int totalFrameCount) { + int silenceDurationMs, int noiseDurationMs, int totalFrameCount) { int sampleRate = AUDIO_FORMAT.sampleRate; int channelCount = AUDIO_FORMAT.channelCount; Pcm16BitAudioBuilder audioBuilder = new Pcm16BitAudioBuilder(channelCount, totalFrameCount); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/audio/SonicAudioProcessorTest.java b/library/core/src/test/java/com/google/android/exoplayer2/audio/SonicAudioProcessorTest.java index 46e179456c9..5a2af2de848 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/audio/SonicAudioProcessorTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/audio/SonicAudioProcessorTest.java @@ -122,5 +122,4 @@ public void doesNotSupportNon16BitInput() throws Exception { // Expected. } } - } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/drm/ClearKeyUtilTest.java b/library/core/src/test/java/com/google/android/exoplayer2/drm/ClearKeyUtilTest.java index 57fab8bb65a..bed2e6f91f6 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/drm/ClearKeyUtilTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/drm/ClearKeyUtilTest.java @@ -134,5 +134,4 @@ public void adjustRequestDataV27() { // Request should be unchanged. assertThat(ClearKeyUtil.adjustRequestData(KEY_REQUEST)).isEqualTo(KEY_REQUEST); } - } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/EndToEndGaplessTest.java b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/EndToEndGaplessTest.java index d00d58c740a..b4574a6b7fb 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/EndToEndGaplessTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/EndToEndGaplessTest.java @@ -39,7 +39,6 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.robolectric.annotation.Config; import org.robolectric.shadows.MediaCodecInfoBuilder; import org.robolectric.shadows.ShadowAudioTrack; import org.robolectric.shadows.ShadowMediaCodec; @@ -47,7 +46,6 @@ /** End to end playback test for gapless audio playbacks. */ @RunWith(AndroidJUnit4.class) -@Config(sdk = 29) public class EndToEndGaplessTest { private static final int CODEC_INPUT_BUFFER_SIZE = 5120; private static final int CODEC_OUTPUT_BUFFER_SIZE = 5120; diff --git a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/FlacPlaybackTest.java b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/FlacPlaybackTest.java index c98bd52da73..200b071e755 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/FlacPlaybackTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/FlacPlaybackTest.java @@ -33,11 +33,8 @@ import org.robolectric.ParameterizedRobolectricTestRunner; import org.robolectric.ParameterizedRobolectricTestRunner.Parameter; import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; -import org.robolectric.annotation.Config; /** End-to-end tests using FLAC samples. */ -// TODO(b/143232359): Remove once https://issuetracker.google.com/143232359 is resolved. -@Config(sdk = 29) @RunWith(ParameterizedRobolectricTestRunner.class) public class FlacPlaybackTest { diff --git a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/FlvPlaybackTest.java b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/FlvPlaybackTest.java index 39055b573b3..8a414ced437 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/FlvPlaybackTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/FlvPlaybackTest.java @@ -34,11 +34,8 @@ import org.junit.runner.RunWith; import org.robolectric.ParameterizedRobolectricTestRunner; import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; -import org.robolectric.annotation.Config; /** End-to-end tests using FLV samples. */ -// TODO(b/143232359): Remove once https://issuetracker.google.com/143232359 is resolved. -@Config(sdk = 29) @RunWith(ParameterizedRobolectricTestRunner.class) public final class FlvPlaybackTest { @Parameters(name = "{0}") diff --git a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/MkaPlaybackTest.java b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/MkaPlaybackTest.java index fae8974c9d5..081a6a5658c 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/MkaPlaybackTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/MkaPlaybackTest.java @@ -32,11 +32,8 @@ import org.junit.runner.RunWith; import org.robolectric.ParameterizedRobolectricTestRunner; import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; -import org.robolectric.annotation.Config; /** End-to-end tests using MKA samples. */ -// TODO(b/143232359): Remove once https://issuetracker.google.com/143232359 is resolved. -@Config(sdk = 29) @RunWith(ParameterizedRobolectricTestRunner.class) public final class MkaPlaybackTest { @Parameters(name = "{0}") diff --git a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/MkvPlaybackTest.java b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/MkvPlaybackTest.java index 5e96ad24974..2d6bd31fdd5 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/MkvPlaybackTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/MkvPlaybackTest.java @@ -34,11 +34,8 @@ import org.junit.runner.RunWith; import org.robolectric.ParameterizedRobolectricTestRunner; import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; -import org.robolectric.annotation.Config; /** End-to-end tests using MKV samples. */ -// TODO(b/143232359): Remove once https://issuetracker.google.com/143232359 is resolved. -@Config(sdk = 29) @RunWith(ParameterizedRobolectricTestRunner.class) public final class MkvPlaybackTest { @Parameters(name = "{0}") diff --git a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/Mp3PlaybackTest.java b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/Mp3PlaybackTest.java index 6bd5f711fc3..773f2743886 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/Mp3PlaybackTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/Mp3PlaybackTest.java @@ -32,11 +32,8 @@ import org.junit.runner.RunWith; import org.robolectric.ParameterizedRobolectricTestRunner; import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; -import org.robolectric.annotation.Config; /** End-to-end tests using MP3 samples. */ -// TODO(b/143232359): Remove once https://issuetracker.google.com/143232359 is resolved. -@Config(sdk = 29) @RunWith(ParameterizedRobolectricTestRunner.class) public final class Mp3PlaybackTest { @Parameters(name = "{0}") diff --git a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/Mp4PlaybackTest.java b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/Mp4PlaybackTest.java index 32f9e3e1718..557f00f64d9 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/Mp4PlaybackTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/Mp4PlaybackTest.java @@ -35,11 +35,8 @@ import org.robolectric.ParameterizedRobolectricTestRunner; import org.robolectric.ParameterizedRobolectricTestRunner.Parameter; import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; -import org.robolectric.annotation.Config; /** End-to-end tests using MP4 samples. */ -// TODO(b/143232359): Remove once https://issuetracker.google.com/143232359 is resolved. -@Config(sdk = 29) @RunWith(ParameterizedRobolectricTestRunner.class) public class Mp4PlaybackTest { diff --git a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/OggPlaybackTest.java b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/OggPlaybackTest.java index 56d50da2908..88c2e14c61d 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/OggPlaybackTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/OggPlaybackTest.java @@ -31,11 +31,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.ParameterizedRobolectricTestRunner; -import org.robolectric.annotation.Config; /** End-to-end tests using OGG samples. */ -// TODO(b/143232359): Remove once https://issuetracker.google.com/143232359 is resolved. -@Config(sdk = 29) @RunWith(ParameterizedRobolectricTestRunner.class) public final class OggPlaybackTest { @ParameterizedRobolectricTestRunner.Parameters(name = "{0}") diff --git a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/PlaylistPlaybackTest.java b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/PlaylistPlaybackTest.java index e00857cc92e..9d2316e37fe 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/PlaylistPlaybackTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/PlaylistPlaybackTest.java @@ -30,11 +30,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.robolectric.annotation.Config; /** End-to-end tests for playlists. */ -// TODO(b/143232359): Remove once https://issuetracker.google.com/143232359 is resolved. -@Config(sdk = 29) @RunWith(AndroidJUnit4.class) public final class PlaylistPlaybackTest { diff --git a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/SilencePlaybackTest.java b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/SilencePlaybackTest.java index c6206b2fc87..f7f9da385aa 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/SilencePlaybackTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/SilencePlaybackTest.java @@ -30,11 +30,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.robolectric.annotation.Config; /** End-to-end tests using {@link SilenceMediaSource}. */ -// TODO(b/143232359): Remove once https://issuetracker.google.com/143232359 is resolved. -@Config(sdk = 29) @RunWith(AndroidJUnit4.class) public final class SilencePlaybackTest { diff --git a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/TsPlaybackTest.java b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/TsPlaybackTest.java index e0a6a326179..5ac951f51b3 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/TsPlaybackTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/TsPlaybackTest.java @@ -35,11 +35,8 @@ import org.robolectric.ParameterizedRobolectricTestRunner; import org.robolectric.ParameterizedRobolectricTestRunner.Parameter; import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; -import org.robolectric.annotation.Config; /** End-to-end tests using TS samples. */ -// TODO(b/143232359): Remove once https://issuetracker.google.com/143232359 is resolved. -@Config(sdk = 29) @RunWith(ParameterizedRobolectricTestRunner.class) public class TsPlaybackTest { diff --git a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/Vp9PlaybackTest.java b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/Vp9PlaybackTest.java index 90c6d16cb41..9c29e278089 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/Vp9PlaybackTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/Vp9PlaybackTest.java @@ -34,11 +34,8 @@ import org.junit.runner.RunWith; import org.robolectric.ParameterizedRobolectricTestRunner; import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; -import org.robolectric.annotation.Config; /** End-to-end tests using VP9 samples. */ -// TODO(b/143232359): Remove once https://issuetracker.google.com/143232359 is resolved. -@Config(sdk = 29) @RunWith(ParameterizedRobolectricTestRunner.class) public final class Vp9PlaybackTest { @Parameters(name = "{0}") diff --git a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/WavPlaybackTest.java b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/WavPlaybackTest.java index d1d9c38bf11..6391547433e 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/WavPlaybackTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/WavPlaybackTest.java @@ -31,11 +31,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.ParameterizedRobolectricTestRunner; -import org.robolectric.annotation.Config; /** End-to-end tests using WAV samples. */ -// TODO(b/143232359): Remove once https://issuetracker.google.com/143232359 is resolved. -@Config(sdk = 29) @RunWith(ParameterizedRobolectricTestRunner.class) public final class WavPlaybackTest { @ParameterizedRobolectricTestRunner.Parameters(name = "{0}") diff --git a/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapterTest.java b/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapterTest.java index 74a7d1c9872..5dfeb04ff1b 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapterTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapterTest.java @@ -30,9 +30,11 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit tests for {@link AsynchronousMediaCodecAdapter}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public class AsynchronousMediaCodecAdapterTest { private AsynchronousMediaCodecAdapter adapter; private HandlerThread callbackThread; @@ -60,8 +62,8 @@ public void setUp() throws Exception { /* synchronizeCodecInteractionsWithQueueing= */ false) .createAdapter(configuration); bufferInfo = new MediaCodec.BufferInfo(); - // After start(), the ShadowMediaCodec offers input buffer 0. We advance the looper to make sure - // and messages have been propagated to the adapter. + // After starting the MediaCodec, the ShadowMediaCodec offers input buffer 0. We advance the + // looper to make sure any messages have been propagated to the adapter. shadowOf(callbackThread.getLooper()).idle(); } @@ -75,7 +77,6 @@ public void dequeueInputBufferIndex_withInputBuffer_returnsInputBuffer() { assertThat(adapter.dequeueInputBufferIndex()).isEqualTo(0); } - @Test public void dequeueInputBufferIndex_withMediaCodecError_throwsException() throws Exception { // Set an error directly on the adapter (not through the looper). diff --git a/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/BatchBufferTest.java b/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/BatchBufferTest.java index b488403a68c..8a25a66262d 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/BatchBufferTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/BatchBufferTest.java @@ -262,5 +262,4 @@ private void initSampleBuffer(long timeUs) { sampleBuffer.data.putLong(timeUs); sampleBuffer.flip(); } - } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/metadata/scte35/SpliceInfoDecoderTest.java b/library/core/src/test/java/com/google/android/exoplayer2/metadata/scte35/SpliceInfoDecoderTest.java index dcb1f634c9b..b505ab62f65 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/metadata/scte35/SpliceInfoDecoderTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/metadata/scte35/SpliceInfoDecoderTest.java @@ -46,22 +46,33 @@ public void setUp() { @Test public void wrappedAroundTimeSignalCommand() { - byte[] rawTimeSignalSection = new byte[] { - 0, // table_id. - (byte) 0x80, // section_syntax_indicator, private_indicator, reserved, section_length(4). - 0x14, // section_length(8). - 0x00, // protocol_version. - 0x00, // encrypted_packet, encryption_algorithm, pts_adjustment(1). - 0x00, 0x00, 0x00, 0x00, // pts_adjustment(32). - 0x00, // cw_index. - 0x00, // tier(8). - 0x00, // tier(4), splice_command_length(4). - 0x05, // splice_command_length(8). - 0x06, // splice_command_type = time_signal. - // Start of splice_time(). - (byte) 0x80, // time_specified_flag, reserved, pts_time(1). - 0x52, 0x03, 0x02, (byte) 0x8f, // pts_time(32). PTS for a second after playback position. - 0x00, 0x00, 0x00, 0x00}; // CRC_32 (ignored, check happens at extraction). + byte[] rawTimeSignalSection = + new byte[] { + 0, // table_id. + (byte) 0x80, // section_syntax_indicator, private_indicator, reserved, section_length(4). + 0x14, // section_length(8). + 0x00, // protocol_version. + 0x00, // encrypted_packet, encryption_algorithm, pts_adjustment(1). + 0x00, + 0x00, + 0x00, + 0x00, // pts_adjustment(32). + 0x00, // cw_index. + 0x00, // tier(8). + 0x00, // tier(4), splice_command_length(4). + 0x05, // splice_command_length(8). + 0x06, // splice_command_type = time_signal. + // Start of splice_time(). + (byte) 0x80, // time_specified_flag, reserved, pts_time(1). + 0x52, + 0x03, + 0x02, + (byte) 0x8f, // pts_time(32). PTS for a second after playback position. + 0x00, + 0x00, + 0x00, + 0x00 + }; // CRC_32 (ignored, check happens at extraction). // The playback position is 57:15:58.43 approximately. // With this offset, the playback position pts before wrapping is 0x451ebf851. @@ -73,30 +84,45 @@ public void wrappedAroundTimeSignalCommand() { @Test public void test2SpliceInsertCommands() { - byte[] rawSpliceInsertCommand1 = new byte[] { - 0, // table_id. - (byte) 0x80, // section_syntax_indicator, private_indicator, reserved, section_length(4). - 0x19, // section_length(8). - 0x00, // protocol_version. - 0x00, // encrypted_packet, encryption_algorithm, pts_adjustment(1). - 0x00, 0x00, 0x00, 0x00, // pts_adjustment(32). - 0x00, // cw_index. - 0x00, // tier(8). - 0x00, // tier(4), splice_command_length(4). - 0x0e, // splice_command_length(8). - 0x05, // splice_command_type = splice_insert. - // Start of splice_insert(). - 0x00, 0x00, 0x00, 0x42, // splice_event_id. - 0x00, // splice_event_cancel_indicator, reserved. - 0x40, // out_of_network_indicator, program_splice_flag, duration_flag, - // splice_immediate_flag, reserved. - // start of splice_time(). - (byte) 0x80, // time_specified_flag, reserved, pts_time(1). - 0x00, 0x00, 0x00, 0x00, // PTS for playback position 3s. - 0x00, 0x10, // unique_program_id. - 0x01, // avail_num. - 0x02, // avails_expected. - 0x00, 0x00, 0x00, 0x00}; // CRC_32 (ignored, check happens at extraction). + byte[] rawSpliceInsertCommand1 = + new byte[] { + 0, // table_id. + (byte) 0x80, // section_syntax_indicator, private_indicator, reserved, section_length(4). + 0x19, // section_length(8). + 0x00, // protocol_version. + 0x00, // encrypted_packet, encryption_algorithm, pts_adjustment(1). + 0x00, + 0x00, + 0x00, + 0x00, // pts_adjustment(32). + 0x00, // cw_index. + 0x00, // tier(8). + 0x00, // tier(4), splice_command_length(4). + 0x0e, // splice_command_length(8). + 0x05, // splice_command_type = splice_insert. + // Start of splice_insert(). + 0x00, + 0x00, + 0x00, + 0x42, // splice_event_id. + 0x00, // splice_event_cancel_indicator, reserved. + 0x40, // out_of_network_indicator, program_splice_flag, duration_flag, + // splice_immediate_flag, reserved. + // start of splice_time(). + (byte) 0x80, // time_specified_flag, reserved, pts_time(1). + 0x00, + 0x00, + 0x00, + 0x00, // PTS for playback position 3s. + 0x00, + 0x10, // unique_program_id. + 0x01, // avail_num. + 0x02, // avails_expected. + 0x00, + 0x00, + 0x00, + 0x00 + }; // CRC_32 (ignored, check happens at extraction). Metadata metadata = feedInputBuffer(rawSpliceInsertCommand1, 2000000, 3000000); assertThat(metadata.length()).isEqualTo(1); @@ -112,35 +138,50 @@ public void test2SpliceInsertCommands() { assertThat(command.availNum).isEqualTo(1); assertThat(command.availsExpected).isEqualTo(2); - byte[] rawSpliceInsertCommand2 = new byte[] { - 0, // table_id. - (byte) 0x80, // section_syntax_indicator, private_indicator, reserved, section_length(4). - 0x22, // section_length(8). - 0x00, // protocol_version. - 0x00, // encrypted_packet, encryption_algorithm, pts_adjustment(1). - 0x00, 0x00, 0x00, 0x00, // pts_adjustment(32). - 0x00, // cw_index. - 0x00, // tier(8). - 0x00, // tier(4), splice_command_length(4). - 0x13, // splice_command_length(8). - 0x05, // splice_command_type = splice_insert. - // Start of splice_insert(). - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, // splice_event_id. - 0x00, // splice_event_cancel_indicator, reserved. - 0x00, // out_of_network_indicator, program_splice_flag, duration_flag, - // splice_immediate_flag, reserved. - 0x02, // component_count. - 0x10, // component_tag. - // start of splice_time(). - (byte) 0x81, // time_specified_flag, reserved, pts_time(1). - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, // PTS for playback position 10s. - // start of splice_time(). - 0x11, // component_tag. - 0x00, // time_specified_flag, reserved. - 0x00, 0x20, // unique_program_id. - 0x01, // avail_num. - 0x02, // avails_expected. - 0x00, 0x00, 0x00, 0x00}; // CRC_32 (ignored, check happens at extraction). + byte[] rawSpliceInsertCommand2 = + new byte[] { + 0, // table_id. + (byte) 0x80, // section_syntax_indicator, private_indicator, reserved, section_length(4). + 0x22, // section_length(8). + 0x00, // protocol_version. + 0x00, // encrypted_packet, encryption_algorithm, pts_adjustment(1). + 0x00, + 0x00, + 0x00, + 0x00, // pts_adjustment(32). + 0x00, // cw_index. + 0x00, // tier(8). + 0x00, // tier(4), splice_command_length(4). + 0x13, // splice_command_length(8). + 0x05, // splice_command_type = splice_insert. + // Start of splice_insert(). + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, // splice_event_id. + 0x00, // splice_event_cancel_indicator, reserved. + 0x00, // out_of_network_indicator, program_splice_flag, duration_flag, + // splice_immediate_flag, reserved. + 0x02, // component_count. + 0x10, // component_tag. + // start of splice_time(). + (byte) 0x81, // time_specified_flag, reserved, pts_time(1). + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, // PTS for playback position 10s. + // start of splice_time(). + 0x11, // component_tag. + 0x00, // time_specified_flag, reserved. + 0x00, + 0x20, // unique_program_id. + 0x01, // avail_num. + 0x02, // avails_expected. + 0x00, + 0x00, + 0x00, + 0x00 + }; // CRC_32 (ignored, check happens at extraction). // By changing the subsample offset we force adjuster reconstruction. long subsampleOffset = 1000011; @@ -203,5 +244,4 @@ private static long removePtsConversionPrecisionError(long timeUs, long offsetUs return TimestampAdjuster.ptsToUs(TimestampAdjuster.usToNonWrappedPts(timeUs - offsetUs)) + offsetUs; } - } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/source/CompositeSequenceableLoaderTest.java b/library/core/src/test/java/com/google/android/exoplayer2/source/CompositeSequenceableLoaderTest.java index c2f9ad07f71..a205496dd0d 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/source/CompositeSequenceableLoaderTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/source/CompositeSequenceableLoaderTest.java @@ -36,8 +36,8 @@ public void getBufferedPositionUsReturnsMinimumLoaderBufferedPosition() { new FakeSequenceableLoader(/* bufferedPositionUs */ 1000, /* nextLoadPositionUs */ 2000); FakeSequenceableLoader loader2 = new FakeSequenceableLoader(/* bufferedPositionUs */ 1001, /* nextLoadPositionUs */ 2001); - CompositeSequenceableLoader compositeSequenceableLoader = new CompositeSequenceableLoader( - new SequenceableLoader[] {loader1, loader2}); + CompositeSequenceableLoader compositeSequenceableLoader = + new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2}); assertThat(compositeSequenceableLoader.getBufferedPositionUs()).isEqualTo(1000); } @@ -55,8 +55,8 @@ public void getBufferedPositionUsReturnsMinimumNonEndOfSourceLoaderBufferedPosit new FakeSequenceableLoader( /* bufferedPositionUs */ C.TIME_END_OF_SOURCE, /* nextLoadPositionUs */ C.TIME_END_OF_SOURCE); - CompositeSequenceableLoader compositeSequenceableLoader = new CompositeSequenceableLoader( - new SequenceableLoader[] {loader1, loader2, loader3}); + CompositeSequenceableLoader compositeSequenceableLoader = + new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2, loader3}); assertThat(compositeSequenceableLoader.getBufferedPositionUs()).isEqualTo(1000); } @@ -74,8 +74,8 @@ public void getBufferedPositionUsReturnsEndOfSourceWhenAllLoaderBufferedTillEndO new FakeSequenceableLoader( /* bufferedPositionUs */ C.TIME_END_OF_SOURCE, /* nextLoadPositionUs */ C.TIME_END_OF_SOURCE); - CompositeSequenceableLoader compositeSequenceableLoader = new CompositeSequenceableLoader( - new SequenceableLoader[] {loader1, loader2}); + CompositeSequenceableLoader compositeSequenceableLoader = + new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2}); assertThat(compositeSequenceableLoader.getBufferedPositionUs()).isEqualTo(C.TIME_END_OF_SOURCE); } @@ -89,8 +89,8 @@ public void getNextLoadPositionUsReturnMinimumLoaderNextLoadPositionUs() { new FakeSequenceableLoader(/* bufferedPositionUs */ 1000, /* nextLoadPositionUs */ 2001); FakeSequenceableLoader loader2 = new FakeSequenceableLoader(/* bufferedPositionUs */ 1001, /* nextLoadPositionUs */ 2000); - CompositeSequenceableLoader compositeSequenceableLoader = new CompositeSequenceableLoader( - new SequenceableLoader[] {loader1, loader2}); + CompositeSequenceableLoader compositeSequenceableLoader = + new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2}); assertThat(compositeSequenceableLoader.getNextLoadPositionUs()).isEqualTo(2000); } @@ -107,8 +107,8 @@ public void getNextLoadPositionUsReturnMinimumNonEndOfSourceLoaderNextLoadPositi FakeSequenceableLoader loader3 = new FakeSequenceableLoader( /* bufferedPositionUs */ 1001, /* nextLoadPositionUs */ C.TIME_END_OF_SOURCE); - CompositeSequenceableLoader compositeSequenceableLoader = new CompositeSequenceableLoader( - new SequenceableLoader[] {loader1, loader2, loader3}); + CompositeSequenceableLoader compositeSequenceableLoader = + new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2, loader3}); assertThat(compositeSequenceableLoader.getNextLoadPositionUs()).isEqualTo(2000); } @@ -124,8 +124,8 @@ public void getNextLoadPositionUsReturnsEndOfSourceWhenAllLoaderLoadingLastChunk FakeSequenceableLoader loader2 = new FakeSequenceableLoader( /* bufferedPositionUs */ 1001, /* nextLoadPositionUs */ C.TIME_END_OF_SOURCE); - CompositeSequenceableLoader compositeSequenceableLoader = new CompositeSequenceableLoader( - new SequenceableLoader[] {loader1, loader2}); + CompositeSequenceableLoader compositeSequenceableLoader = + new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2}); assertThat(compositeSequenceableLoader.getNextLoadPositionUs()).isEqualTo(C.TIME_END_OF_SOURCE); } @@ -140,8 +140,8 @@ public void continueLoadingOnlyAllowFurthestBehindLoaderToLoadIfNotBehindPlaybac new FakeSequenceableLoader(/* bufferedPositionUs */ 1000, /* nextLoadPositionUs */ 2000); FakeSequenceableLoader loader2 = new FakeSequenceableLoader(/* bufferedPositionUs */ 1001, /* nextLoadPositionUs */ 2001); - CompositeSequenceableLoader compositeSequenceableLoader = new CompositeSequenceableLoader( - new SequenceableLoader[] {loader1, loader2}); + CompositeSequenceableLoader compositeSequenceableLoader = + new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2}); compositeSequenceableLoader.continueLoading(100); assertThat(loader1.numInvocations).isEqualTo(1); @@ -160,8 +160,8 @@ public void continueLoadingReturnAllowAllLoadersBehindPlaybackPositionToLoad() { new FakeSequenceableLoader(/* bufferedPositionUs */ 1001, /* nextLoadPositionUs */ 2001); FakeSequenceableLoader loader3 = new FakeSequenceableLoader(/* bufferedPositionUs */ 1002, /* nextLoadPositionUs */ 2002); - CompositeSequenceableLoader compositeSequenceableLoader = new CompositeSequenceableLoader( - new SequenceableLoader[] {loader1, loader2, loader3}); + CompositeSequenceableLoader compositeSequenceableLoader = + new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2, loader3}); compositeSequenceableLoader.continueLoading(3000); assertThat(loader1.numInvocations).isEqualTo(1); @@ -181,8 +181,8 @@ public void continueLoadingOnlyNotAllowEndOfSourceLoaderToLoad() { FakeSequenceableLoader loader2 = new FakeSequenceableLoader( /* bufferedPositionUs */ 1001, /* nextLoadPositionUs */ C.TIME_END_OF_SOURCE); - CompositeSequenceableLoader compositeSequenceableLoader = new CompositeSequenceableLoader( - new SequenceableLoader[] {loader1, loader2}); + CompositeSequenceableLoader compositeSequenceableLoader = + new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2}); compositeSequenceableLoader.continueLoading(3000); assertThat(loader1.numInvocations).isEqualTo(0); @@ -202,8 +202,8 @@ public void continueLoadingReturnTrueIfFurthestBehindLoaderCanMakeProgress() { new FakeSequenceableLoader(/* bufferedPositionUs */ 1001, /* nextLoadPositionUs */ 2001); loader1.setNextChunkDurationUs(1000); - CompositeSequenceableLoader compositeSequenceableLoader = new CompositeSequenceableLoader( - new SequenceableLoader[] {loader1, loader2}); + CompositeSequenceableLoader compositeSequenceableLoader = + new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2}); assertThat(compositeSequenceableLoader.continueLoading(100)).isTrue(); } @@ -222,8 +222,8 @@ public void continueLoadingReturnTrueIfLoaderBehindPlaybackPositionCanMakeProgre // loader2 is not the furthest behind, but it can make progress if allowed. loader2.setNextChunkDurationUs(1000); - CompositeSequenceableLoader compositeSequenceableLoader = new CompositeSequenceableLoader( - new SequenceableLoader[] {loader1, loader2}); + CompositeSequenceableLoader compositeSequenceableLoader = + new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2}); assertThat(compositeSequenceableLoader.continueLoading(3000)).isTrue(); } @@ -274,7 +274,5 @@ public void reevaluateBuffer(long positionUs) { private void setNextChunkDurationUs(int nextChunkDurationUs) { this.nextChunkDurationUs = nextChunkDurationUs; } - } - } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/source/DefaultMediaSourceFactoryTest.java b/library/core/src/test/java/com/google/android/exoplayer2/source/DefaultMediaSourceFactoryTest.java index 72a7c8c638a..9be9445f47f 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/source/DefaultMediaSourceFactoryTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/source/DefaultMediaSourceFactoryTest.java @@ -29,7 +29,6 @@ import com.google.android.exoplayer2.ui.AdViewProvider; import com.google.android.exoplayer2.util.MimeTypes; import java.util.Arrays; -import java.util.Collections; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; @@ -63,19 +62,6 @@ public void createMediaSource_withoutMimeType_progressiveSource() { assertThat(mediaSource).isInstanceOf(ProgressiveMediaSource.class); } - @Test - @SuppressWarnings("deprecation") // Testing deprecated MediaSource.getTag() still works. - public void createMediaSource_withTag_tagInSource_deprecated() { - Object tag = new Object(); - DefaultMediaSourceFactory defaultMediaSourceFactory = - new DefaultMediaSourceFactory((Context) ApplicationProvider.getApplicationContext()); - MediaItem mediaItem = new MediaItem.Builder().setUri(URI_MEDIA).setTag(tag).build(); - - MediaSource mediaSource = defaultMediaSourceFactory.createMediaSource(mediaItem); - - assertThat(mediaSource.getTag()).isEqualTo(tag); - } - @Test public void createMediaSource_withPath_progressiveSource() { DefaultMediaSourceFactory defaultMediaSourceFactory = @@ -119,26 +105,6 @@ public void createMediaSource_withSubtitle_isMergingMediaSource() { assertThat(mediaSource).isInstanceOf(MergingMediaSource.class); } - @Test - @SuppressWarnings("deprecation") // Testing deprecated MediaSource.getTag() still works. - public void createMediaSource_withSubtitle_hasTag_deprecated() { - DefaultMediaSourceFactory defaultMediaSourceFactory = - new DefaultMediaSourceFactory((Context) ApplicationProvider.getApplicationContext()); - Object tag = new Object(); - MediaItem mediaItem = - new MediaItem.Builder() - .setTag(tag) - .setUri(URI_MEDIA) - .setSubtitles( - Collections.singletonList( - new MediaItem.Subtitle(Uri.parse(URI_TEXT), MimeTypes.APPLICATION_TTML, "en"))) - .build(); - - MediaSource mediaSource = defaultMediaSourceFactory.createMediaSource(mediaItem); - - assertThat(mediaSource.getTag()).isEqualTo(tag); - } - @Test public void createMediaSource_withStartPosition_isClippingMediaSource() { DefaultMediaSourceFactory defaultMediaSourceFactory = diff --git a/library/core/src/test/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriodTest.java b/library/core/src/test/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriodTest.java index 2ca6ee63434..7c437a0e024 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriodTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriodTest.java @@ -33,7 +33,6 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.junit.Test; import org.junit.runner.RunWith; -import org.robolectric.annotation.Config; /** Unit test for {@link ProgressiveMediaPeriod}. */ @RunWith(AndroidJUnit4.class) @@ -47,7 +46,6 @@ public void prepareUsingBundledExtractors_updatesSourceInfoBeforeOnPreparedCallb } @Test - @Config(sdk = 30) public void prepareUsingMediaParser_updatesSourceInfoBeforeOnPreparedCallback() throws TimeoutException { testExtractorsUpdatesSourceInfoBeforeOnPreparedCallback(new MediaParserExtractorAdapter()); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java b/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java index 8ce5c999f70..0b812ba14f2 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java @@ -35,6 +35,7 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.FormatHolder; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.drm.DrmSession; @@ -554,7 +555,10 @@ public void readWithErrorSessionReadsNothingAndThrows() throws IOException { assertReadNothing(/* formatRequired= */ false); sampleQueue.maybeThrowError(); when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_ERROR); - when(mockDrmSession.getError()).thenReturn(new DrmSession.DrmSessionException(new Exception())); + when(mockDrmSession.getError()) + .thenReturn( + new DrmSession.DrmSessionException( + new Exception(), PlaybackException.ERROR_CODE_DRM_SYSTEM_ERROR)); assertReadNothing(/* formatRequired= */ false); try { sampleQueue.maybeThrowError(); @@ -1384,30 +1388,21 @@ public void setStartTime() {} // Internal methods. - /** - * Writes standard test data to {@code sampleQueue}. - */ + /** Writes standard test data to {@code sampleQueue}. */ private void writeTestData() { writeTestData( DATA, SAMPLE_SIZES, SAMPLE_OFFSETS, SAMPLE_TIMESTAMPS, SAMPLE_FORMATS, SAMPLE_FLAGS); } - private void writeTestDataWithEncryptedSections() { - writeTestData( - ENCRYPTED_SAMPLE_DATA, - ENCRYPTED_SAMPLE_SIZES, - ENCRYPTED_SAMPLE_OFFSETS, - ENCRYPTED_SAMPLE_TIMESTAMPS, - ENCRYPTED_SAMPLE_FORMATS, - ENCRYPTED_SAMPLES_FLAGS); - } - - /** - * Writes the specified test data to {@code sampleQueue}. - */ + /** Writes the specified test data to {@code sampleQueue}. */ @SuppressWarnings("ReferenceEquality") - private void writeTestData(byte[] data, int[] sampleSizes, int[] sampleOffsets, - long[] sampleTimestamps, Format[] sampleFormats, int[] sampleFlags) { + private void writeTestData( + byte[] data, + int[] sampleSizes, + int[] sampleOffsets, + long[] sampleTimestamps, + Format[] sampleFormats, + int[] sampleFlags) { sampleQueue.sampleData(new ParsableByteArray(data), data.length); Format format = null; for (int i = 0; i < sampleTimestamps.length; i++) { @@ -1424,6 +1419,16 @@ private void writeTestData(byte[] data, int[] sampleSizes, int[] sampleOffsets, } } + private void writeTestDataWithEncryptedSections() { + writeTestData( + ENCRYPTED_SAMPLE_DATA, + ENCRYPTED_SAMPLE_SIZES, + ENCRYPTED_SAMPLE_OFFSETS, + ENCRYPTED_SAMPLE_TIMESTAMPS, + ENCRYPTED_SAMPLE_FORMATS, + ENCRYPTED_SAMPLES_FLAGS); + } + /** Writes a {@link Format} to the {@code sampleQueue}. */ private void writeFormat(Format format) { sampleQueue.format(format); @@ -1440,9 +1445,7 @@ private void writeSample(byte[] data, long timestampUs, int sampleFlags) { (sampleFlags & C.BUFFER_FLAG_ENCRYPTED) != 0 ? CRYPTO_DATA : null); } - /** - * Asserts correct reading of standard test data from {@code sampleQueue}. - */ + /** Asserts correct reading of standard test data from {@code sampleQueue}. */ private void assertReadTestData() { assertReadTestData(/* startFormat= */ null, 0); } @@ -1724,9 +1727,7 @@ private void assertAllocationCount(int count) { assertThat(allocator.getTotalBytesAllocated()).isEqualTo(ALLOCATION_SIZE * count); } - /** - * Asserts {@code inputBuffer} does not contain any sample data. - */ + /** Asserts {@code inputBuffer} does not contain any sample data. */ private void assertInputBufferContainsNoSampleData() { if (inputBuffer.data == null) { return; diff --git a/library/core/src/test/java/com/google/android/exoplayer2/source/ShuffleOrderTest.java b/library/core/src/test/java/com/google/android/exoplayer2/source/ShuffleOrderTest.java index bfa4dbd0495..c301337651a 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/source/ShuffleOrderTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/source/ShuffleOrderTest.java @@ -167,5 +167,4 @@ private static void testCloneAndRemove( assertThat(newNextIndex).isEqualTo(expectedNextIndex); } } - } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/source/ads/ServerSideInsertedAdMediaSourceTest.java b/library/core/src/test/java/com/google/android/exoplayer2/source/ads/ServerSideInsertedAdMediaSourceTest.java new file mode 100644 index 00000000000..11695221039 --- /dev/null +++ b/library/core/src/test/java/com/google/android/exoplayer2/source/ads/ServerSideInsertedAdMediaSourceTest.java @@ -0,0 +1,385 @@ +/* + * 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 com.google.android.exoplayer2.source.ads; + +import static com.google.android.exoplayer2.robolectric.RobolectricUtil.runMainLooperUntil; +import static com.google.android.exoplayer2.robolectric.TestPlayerRunHelper.playUntilPosition; +import static com.google.android.exoplayer2.robolectric.TestPlayerRunHelper.runUntilPendingCommandsAreFullyHandled; +import static com.google.android.exoplayer2.robolectric.TestPlayerRunHelper.runUntilPlaybackState; +import static com.google.android.exoplayer2.source.ads.ServerSideInsertedAdsUtil.addAdGroupToAdPlaybackState; +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import android.content.Context; +import android.graphics.SurfaceTexture; +import android.view.Surface; +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.SimpleExoPlayer; +import com.google.android.exoplayer2.Timeline; +import com.google.android.exoplayer2.analytics.AnalyticsListener; +import com.google.android.exoplayer2.robolectric.PlaybackOutput; +import com.google.android.exoplayer2.robolectric.ShadowMediaCodecConfig; +import com.google.android.exoplayer2.source.DefaultMediaSourceFactory; +import com.google.android.exoplayer2.testutil.CapturingRenderersFactory; +import com.google.android.exoplayer2.testutil.DumpFileAsserts; +import com.google.android.exoplayer2.testutil.FakeClock; +import com.google.android.exoplayer2.testutil.FakeMediaSource; +import com.google.android.exoplayer2.testutil.FakeTimeline; +import java.util.concurrent.atomic.AtomicReference; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** Unit test for {@link ServerSideInsertedAdsMediaSource}. */ +@RunWith(AndroidJUnit4.class) +public final class ServerSideInsertedAdMediaSourceTest { + + @Rule + public ShadowMediaCodecConfig mediaCodecConfig = + ShadowMediaCodecConfig.forAllSupportedMimeTypes(); + + private static final String TEST_ASSET = "asset:///media/mp4/sample.mp4"; + private static final String TEST_ASSET_DUMP = "playbackdumps/mp4/sample.mp4.dump"; + + @Test + public void timeline_containsAdsDefinedInAdPlaybackState() throws Exception { + FakeTimeline wrappedTimeline = + new FakeTimeline( + new FakeTimeline.TimelineWindowDefinition( + /* periodCount= */ 1, + /* id= */ 0, + /* isSeekable= */ true, + /* isDynamic= */ true, + /* isLive= */ true, + /* isPlaceholder= */ false, + /* durationUs= */ 10_000_000, + /* defaultPositionUs= */ 3_000_000, + /* windowOffsetInFirstPeriodUs= */ 42_000_000L, + AdPlaybackState.NONE)); + ServerSideInsertedAdsMediaSource mediaSource = + new ServerSideInsertedAdsMediaSource(new FakeMediaSource(wrappedTimeline)); + // Test with one ad group before the window, and the window starting within the second ad group. + AdPlaybackState adPlaybackState = + new AdPlaybackState( + /* adsId= */ new Object(), /* adGroupTimesUs...= */ + 15_000_000, + 41_500_000, + 42_200_000) + .withIsServerSideInserted(/* adGroupIndex= */ 0, /* isServerSideInserted= */ true) + .withIsServerSideInserted(/* adGroupIndex= */ 1, /* isServerSideInserted= */ true) + .withIsServerSideInserted(/* adGroupIndex= */ 2, /* isServerSideInserted= */ true) + .withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 1) + .withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 2) + .withAdCount(/* adGroupIndex= */ 2, /* adCount= */ 1) + .withAdDurationsUs(/* adGroupIndex= */ 0, /* adDurationsUs...= */ 500_000) + .withAdDurationsUs(/* adGroupIndex= */ 1, /* adDurationsUs...= */ 300_000, 100_000) + .withAdDurationsUs(/* adGroupIndex= */ 2, /* adDurationsUs...= */ 400_000) + .withContentResumeOffsetUs(/* adGroupIndex= */ 0, /* contentResumeOffsetUs= */ 100_000) + .withContentResumeOffsetUs(/* adGroupIndex= */ 1, /* contentResumeOffsetUs= */ 400_000) + .withContentResumeOffsetUs(/* adGroupIndex= */ 2, /* contentResumeOffsetUs= */ 200_000); + AtomicReference timelineReference = new AtomicReference<>(); + + mediaSource.setAdPlaybackState(adPlaybackState); + mediaSource.prepareSource( + (source, timeline) -> timelineReference.set(timeline), /* mediaTransferListener= */ null); + runMainLooperUntil(() -> timelineReference.get() != null); + + Timeline timeline = timelineReference.get(); + assertThat(timeline.getPeriodCount()).isEqualTo(1); + Timeline.Period period = timeline.getPeriod(/* periodIndex= */ 0, new Timeline.Period()); + assertThat(period.getAdGroupCount()).isEqualTo(3); + assertThat(period.getAdCountInAdGroup(/* adGroupIndex= */ 0)).isEqualTo(1); + assertThat(period.getAdCountInAdGroup(/* adGroupIndex= */ 1)).isEqualTo(2); + assertThat(period.getAdCountInAdGroup(/* adGroupIndex= */ 2)).isEqualTo(1); + assertThat(period.getAdGroupTimeUs(/* adGroupIndex= */ 0)).isEqualTo(15_000_000); + assertThat(period.getAdGroupTimeUs(/* adGroupIndex= */ 1)).isEqualTo(41_500_000); + assertThat(period.getAdGroupTimeUs(/* adGroupIndex= */ 2)).isEqualTo(42_200_000); + assertThat(period.getAdDurationUs(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0)) + .isEqualTo(500_000); + assertThat(period.getAdDurationUs(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 0)) + .isEqualTo(300_000); + assertThat(period.getAdDurationUs(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 1)) + .isEqualTo(100_000); + assertThat(period.getAdDurationUs(/* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 0)) + .isEqualTo(400_000); + assertThat(period.getContentResumeOffsetUs(/* adGroupIndex= */ 0)).isEqualTo(100_000); + assertThat(period.getContentResumeOffsetUs(/* adGroupIndex= */ 1)).isEqualTo(400_000); + assertThat(period.getContentResumeOffsetUs(/* adGroupIndex= */ 2)).isEqualTo(200_000); + // windowDurationUs + windowOffsetInFirstPeriodUs - sum(adDurations) + sum(contentResumeOffsets) + assertThat(period.getDurationUs()).isEqualTo(51_400_000); + // positionInWindowUs + sum(adDurationsBeforeWindow) - sum(contentResumeOffsetsBeforeWindow) + assertThat(period.getPositionInWindowUs()).isEqualTo(-41_600_000); + Timeline.Window window = timeline.getWindow(/* windowIndex= */ 0, new Timeline.Window()); + assertThat(window.positionInFirstPeriodUs).isEqualTo(41_600_000); + // windowDurationUs - sum(adDurationsInWindow) + sum(applicableContentResumeOffsetUs) + assertThat(window.durationUs).isEqualTo(9_800_000); + } + + @Test + public void playbackWithPredefinedAds_playsSuccessfulWithoutRendererResets() throws Exception { + Context context = ApplicationProvider.getApplicationContext(); + CapturingRenderersFactory renderersFactory = new CapturingRenderersFactory(context); + SimpleExoPlayer player = + new SimpleExoPlayer.Builder(context, renderersFactory) + .setClock(new FakeClock(/* isAutoAdvancing= */ true)) + .build(); + player.setVideoSurface(new Surface(new SurfaceTexture(/* texName= */ 1))); + PlaybackOutput playbackOutput = PlaybackOutput.register(player, renderersFactory); + + ServerSideInsertedAdsMediaSource mediaSource = + new ServerSideInsertedAdsMediaSource( + new DefaultMediaSourceFactory(context) + .createMediaSource(MediaItem.fromUri(TEST_ASSET))); + AdPlaybackState adPlaybackState = new AdPlaybackState(/* adsId= */ new Object()); + adPlaybackState = + addAdGroupToAdPlaybackState( + adPlaybackState, + /* fromPositionUs= */ 0, + /* toPositionUs= */ 200_000, + /* contentResumeOffsetUs= */ 0); + adPlaybackState = + addAdGroupToAdPlaybackState( + adPlaybackState, + /* fromPositionUs= */ 400_000, + /* toPositionUs= */ 700_000, + /* contentResumeOffsetUs= */ 1_000_000); + adPlaybackState = + addAdGroupToAdPlaybackState( + adPlaybackState, + /* fromPositionUs= */ 900_000, + /* toPositionUs= */ 1_000_000, + /* contentResumeOffsetUs= */ 0); + mediaSource.setAdPlaybackState(adPlaybackState); + + AnalyticsListener listener = mock(AnalyticsListener.class); + player.addAnalyticsListener(listener); + player.setMediaSource(mediaSource); + player.prepare(); + player.play(); + runUntilPlaybackState(player, Player.STATE_ENDED); + player.release(); + + // Assert all samples have been played. + DumpFileAsserts.assertOutput(context, playbackOutput, TEST_ASSET_DUMP); + // Assert playback has been reported with ads: [ad0][content][ad1][content][ad2][content] + // 6*2(audio+video) format changes, 5 discontinuities between parts. + verify(listener, times(5)) + .onPositionDiscontinuity( + any(), any(), any(), eq(Player.DISCONTINUITY_REASON_AUTO_TRANSITION)); + verify(listener, times(12)).onDownstreamFormatChanged(any(), any()); + // Assert renderers played through without reset (=decoders have been enabled only once). + verify(listener).onVideoEnabled(any(), any()); + verify(listener).onAudioEnabled(any(), any()); + // Assert playback progression was smooth (=no unexpected delays that cause audio to underrun) + verify(listener, never()).onAudioUnderrun(any(), anyInt(), anyLong(), anyLong()); + } + + @Test + public void playbackWithNewlyInsertedAds_playsSuccessfulWithoutRendererResets() throws Exception { + Context context = ApplicationProvider.getApplicationContext(); + CapturingRenderersFactory renderersFactory = new CapturingRenderersFactory(context); + SimpleExoPlayer player = + new SimpleExoPlayer.Builder(context, renderersFactory) + .setClock(new FakeClock(/* isAutoAdvancing= */ true)) + .build(); + player.setVideoSurface(new Surface(new SurfaceTexture(/* texName= */ 1))); + PlaybackOutput playbackOutput = PlaybackOutput.register(player, renderersFactory); + + ServerSideInsertedAdsMediaSource mediaSource = + new ServerSideInsertedAdsMediaSource( + new DefaultMediaSourceFactory(context) + .createMediaSource(MediaItem.fromUri(TEST_ASSET))); + AdPlaybackState adPlaybackState = new AdPlaybackState(/* adsId= */ new Object()); + adPlaybackState = + addAdGroupToAdPlaybackState( + adPlaybackState, + /* fromPositionUs= */ 900_000, + /* toPositionUs= */ 1_000_000, + /* contentResumeOffsetUs= */ 0); + mediaSource.setAdPlaybackState(adPlaybackState); + + AnalyticsListener listener = mock(AnalyticsListener.class); + player.addAnalyticsListener(listener); + player.setMediaSource(mediaSource); + player.prepare(); + + // Add ad at the current playback position during playback. + runUntilPlaybackState(player, Player.STATE_READY); + adPlaybackState = + addAdGroupToAdPlaybackState( + adPlaybackState, + /* fromPositionUs= */ 0, + /* toPositionUs= */ 500_000, + /* contentResumeOffsetUs= */ 0); + mediaSource.setAdPlaybackState(adPlaybackState); + runUntilPendingCommandsAreFullyHandled(player); + + player.play(); + runUntilPlaybackState(player, Player.STATE_ENDED); + player.release(); + + // Assert all samples have been played. + DumpFileAsserts.assertOutput(context, playbackOutput, TEST_ASSET_DUMP); + // Assert playback has been reported with ads: [content][ad0][content][ad1][content] + // 5*2(audio+video) format changes, 4 discontinuities between parts. + verify(listener, times(4)) + .onPositionDiscontinuity( + any(), any(), any(), eq(Player.DISCONTINUITY_REASON_AUTO_TRANSITION)); + verify(listener, times(10)).onDownstreamFormatChanged(any(), any()); + // Assert renderers played through without reset (=decoders have been enabled only once). + verify(listener).onVideoEnabled(any(), any()); + verify(listener).onAudioEnabled(any(), any()); + // Assert playback progression was smooth (=no unexpected delays that cause audio to underrun) + verify(listener, never()).onAudioUnderrun(any(), anyInt(), anyLong(), anyLong()); + } + + @Test + public void playbackWithAdditionalAdsInAdGroup_playsSuccessfulWithoutRendererResets() + throws Exception { + Context context = ApplicationProvider.getApplicationContext(); + CapturingRenderersFactory renderersFactory = new CapturingRenderersFactory(context); + SimpleExoPlayer player = + new SimpleExoPlayer.Builder(context, renderersFactory) + .setClock(new FakeClock(/* isAutoAdvancing= */ true)) + .build(); + player.setVideoSurface(new Surface(new SurfaceTexture(/* texName= */ 1))); + PlaybackOutput playbackOutput = PlaybackOutput.register(player, renderersFactory); + + ServerSideInsertedAdsMediaSource mediaSource = + new ServerSideInsertedAdsMediaSource( + new DefaultMediaSourceFactory(context) + .createMediaSource(MediaItem.fromUri(TEST_ASSET))); + AdPlaybackState adPlaybackState = new AdPlaybackState(/* adsId= */ new Object()); + adPlaybackState = + addAdGroupToAdPlaybackState( + adPlaybackState, + /* fromPositionUs= */ 0, + /* toPositionUs= */ 500_000, + /* contentResumeOffsetUs= */ 0); + mediaSource.setAdPlaybackState(adPlaybackState); + + AnalyticsListener listener = mock(AnalyticsListener.class); + player.addAnalyticsListener(listener); + player.setMediaSource(mediaSource); + player.prepare(); + + // Wait until playback is ready with first ad and then replace by 3 ads. + runUntilPlaybackState(player, Player.STATE_READY); + adPlaybackState = + adPlaybackState + .withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 3) + .withAdDurationsUs( + /* adGroupIndex= */ 0, /* adDurationsUs...= */ 50_000, 250_000, 200_000); + mediaSource.setAdPlaybackState(adPlaybackState); + runUntilPendingCommandsAreFullyHandled(player); + + player.play(); + runUntilPlaybackState(player, Player.STATE_ENDED); + player.release(); + + // Assert all samples have been played. + DumpFileAsserts.assertOutput(context, playbackOutput, TEST_ASSET_DUMP); + // Assert playback has been reported with ads: [ad0][ad1][ad2][content] + // 4*2(audio+video) format changes, 3 discontinuities between parts. + verify(listener, times(3)) + .onPositionDiscontinuity( + any(), any(), any(), eq(Player.DISCONTINUITY_REASON_AUTO_TRANSITION)); + verify(listener, times(8)).onDownstreamFormatChanged(any(), any()); + // Assert renderers played through without reset (=decoders have been enabled only once). + verify(listener).onVideoEnabled(any(), any()); + verify(listener).onAudioEnabled(any(), any()); + // Assert playback progression was smooth (=no unexpected delays that cause audio to underrun) + verify(listener, never()).onAudioUnderrun(any(), anyInt(), anyLong(), anyLong()); + } + + @Test + public void playbackWithSeek_isHandledCorrectly() throws Exception { + Context context = ApplicationProvider.getApplicationContext(); + SimpleExoPlayer player = + new SimpleExoPlayer.Builder(context) + .setClock(new FakeClock(/* isAutoAdvancing= */ true)) + .build(); + player.setVideoSurface(new Surface(new SurfaceTexture(/* texName= */ 1))); + + ServerSideInsertedAdsMediaSource mediaSource = + new ServerSideInsertedAdsMediaSource( + new DefaultMediaSourceFactory(context) + .createMediaSource(MediaItem.fromUri(TEST_ASSET))); + AdPlaybackState adPlaybackState = new AdPlaybackState(/* adsId= */ new Object()); + adPlaybackState = + addAdGroupToAdPlaybackState( + adPlaybackState, + /* fromPositionUs= */ 0, + /* toPositionUs= */ 100_000, + /* contentResumeOffsetUs= */ 0); + adPlaybackState = + addAdGroupToAdPlaybackState( + adPlaybackState, + /* fromPositionUs= */ 600_000, + /* toPositionUs= */ 700_000, + /* contentResumeOffsetUs= */ 1_000_000); + adPlaybackState = + addAdGroupToAdPlaybackState( + adPlaybackState, + /* fromPositionUs= */ 900_000, + /* toPositionUs= */ 1_000_000, + /* contentResumeOffsetUs= */ 0); + mediaSource.setAdPlaybackState(adPlaybackState); + + AnalyticsListener listener = mock(AnalyticsListener.class); + player.addAnalyticsListener(listener); + player.setMediaSource(mediaSource); + player.prepare(); + // Play to the first content part, then seek past the midroll. + playUntilPosition(player, /* windowIndex= */ 0, /* positionMs= */ 100); + player.seekTo(/* positionMs= */ 1_600); + runUntilPendingCommandsAreFullyHandled(player); + long positionAfterSeekMs = player.getCurrentPosition(); + long contentPositionAfterSeekMs = player.getContentPosition(); + player.play(); + runUntilPlaybackState(player, Player.STATE_ENDED); + player.release(); + + // Assert playback has been reported with ads: [ad0][content] seek [ad1][content][ad2][content] + // 6*2(audio+video) format changes, 4 auto-transitions between parts, 1 seek with adjustment. + verify(listener, times(4)) + .onPositionDiscontinuity( + any(), any(), any(), eq(Player.DISCONTINUITY_REASON_AUTO_TRANSITION)); + verify(listener, times(1)) + .onPositionDiscontinuity(any(), any(), any(), eq(Player.DISCONTINUITY_REASON_SEEK)); + verify(listener, times(1)) + .onPositionDiscontinuity( + any(), any(), any(), eq(Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT)); + verify(listener, times(12)).onDownstreamFormatChanged(any(), any()); + assertThat(contentPositionAfterSeekMs).isEqualTo(1_600); + assertThat(positionAfterSeekMs).isEqualTo(0); // Beginning of second ad. + // Assert renderers played through without reset, except for the seek. + verify(listener, times(2)).onVideoEnabled(any(), any()); + verify(listener, times(2)).onAudioEnabled(any(), any()); + // Assert playback progression was smooth (=no unexpected delays that cause audio to underrun) + verify(listener, never()).onAudioUnderrun(any(), anyInt(), anyLong(), anyLong()); + } +} diff --git a/library/core/src/test/java/com/google/android/exoplayer2/source/ads/ServerSideInsertedAdsUtilTest.java b/library/core/src/test/java/com/google/android/exoplayer2/source/ads/ServerSideInsertedAdsUtilTest.java new file mode 100644 index 00000000000..25379a816bd --- /dev/null +++ b/library/core/src/test/java/com/google/android/exoplayer2/source/ads/ServerSideInsertedAdsUtilTest.java @@ -0,0 +1,585 @@ +/* + * 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 com.google.android.exoplayer2.source.ads; + +import static com.google.android.exoplayer2.source.ads.ServerSideInsertedAdsUtil.addAdGroupToAdPlaybackState; +import static com.google.android.exoplayer2.source.ads.ServerSideInsertedAdsUtil.getAdCountInGroup; +import static com.google.android.exoplayer2.source.ads.ServerSideInsertedAdsUtil.getMediaPeriodPositionUsForAd; +import static com.google.android.exoplayer2.source.ads.ServerSideInsertedAdsUtil.getMediaPeriodPositionUsForContent; +import static com.google.android.exoplayer2.source.ads.ServerSideInsertedAdsUtil.getStreamPositionUsForAd; +import static com.google.android.exoplayer2.source.ads.ServerSideInsertedAdsUtil.getStreamPositionUsForContent; +import static com.google.common.truth.Truth.assertThat; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.C; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** Unit tests for {@link ServerSideInsertedAdsUtil}. */ +@RunWith(AndroidJUnit4.class) +public final class ServerSideInsertedAdsUtilTest { + + private static final Object ADS_ID = new Object(); + + @Test + public void addAdGroupToAdPlaybackState_insertsCorrectAdGroupData() { + AdPlaybackState state = + new AdPlaybackState(ADS_ID, /* adGroupTimesUs...= */ 0, 1, C.TIME_END_OF_SOURCE) + .withRemovedAdGroupCount(2); + + // stream: 0-- content --4300-- ad1 --4500-- content + // content timeline: 0-4300 - [ad1] - 4700-end + state = + addAdGroupToAdPlaybackState( + state, + /* fromPositionUs= */ 4300, + /* toPositionUs= */ 4500, + /* contentResumeOffsetUs= */ 400); + + assertThat(state) + .isEqualTo( + new AdPlaybackState(ADS_ID, /* adGroupTimesUs...= */ 0, 0, 4300, C.TIME_END_OF_SOURCE) + .withRemovedAdGroupCount(2) + .withAdCount(/* adGroupIndex= */ 2, /* adCount= */ 1) + .withIsServerSideInserted(/* adGroupIndex= */ 2, /* isServerSideInserted= */ true) + .withContentResumeOffsetUs(/* adGroupIndex= */ 2, /* contentResumeOffsetUs= */ 400) + .withAdDurationsUs(/* adGroupIndex= */ 2, /* adDurationsUs...= */ 200)); + + // stream: 0-- content --2100-- ad1 --2400-- content --4300-- ad2 --4500-- content + // content timeline: 0-2100 - [ad1] - 2100-4000 - [ad2] - 4400-end + state = + addAdGroupToAdPlaybackState( + state, + /* fromPositionUs= */ 2100, + /* toPositionUs= */ 2400, + /* contentResumeOffsetUs= */ 0); + + assertThat(state) + .isEqualTo( + new AdPlaybackState( + ADS_ID, /* adGroupTimesUs...= */ 0, 0, 2100, 4000, C.TIME_END_OF_SOURCE) + .withRemovedAdGroupCount(2) + .withAdCount(/* adGroupIndex= */ 2, /* adCount= */ 1) + .withAdCount(/* adGroupIndex= */ 3, /* adCount= */ 1) + .withIsServerSideInserted(/* adGroupIndex= */ 2, /* isServerSideInserted= */ true) + .withIsServerSideInserted(/* adGroupIndex= */ 3, /* isServerSideInserted= */ true) + .withContentResumeOffsetUs(/* adGroupIndex= */ 3, /* contentResumeOffsetUs= */ 400) + .withAdDurationsUs(/* adGroupIndex= */ 2, /* adDurationsUs...= */ 300) + .withAdDurationsUs(/* adGroupIndex= */ 3, /* adDurationsUs...= */ 200)); + + // stream: 0-- ad1 --100-- content --2100-- ad2 --2400-- content --4300-- ad3 --4500-- content + // content timeline: 0 - [ad1] - 50-2050 -[ad2] - 2050-3950 - [ad3] - 4350-end + state = + addAdGroupToAdPlaybackState( + state, + /* fromPositionUs= */ 0, + /* toPositionUs= */ 100, + /* contentResumeOffsetUs= */ 50); + + assertThat(state) + .isEqualTo( + new AdPlaybackState( + ADS_ID, /* adGroupTimesUs...= */ 0, 0, 0, 2050, 3950, C.TIME_END_OF_SOURCE) + .withRemovedAdGroupCount(2) + .withAdCount(/* adGroupIndex= */ 2, /* adCount= */ 1) + .withAdCount(/* adGroupIndex= */ 3, /* adCount= */ 1) + .withAdCount(/* adGroupIndex= */ 4, /* adCount= */ 1) + .withIsServerSideInserted(/* adGroupIndex= */ 2, /* isServerSideInserted= */ true) + .withIsServerSideInserted(/* adGroupIndex= */ 3, /* isServerSideInserted= */ true) + .withIsServerSideInserted(/* adGroupIndex= */ 4, /* isServerSideInserted= */ true) + .withContentResumeOffsetUs(/* adGroupIndex= */ 2, /* contentResumeOffsetUs= */ 50) + .withContentResumeOffsetUs(/* adGroupIndex= */ 4, /* contentResumeOffsetUs= */ 400) + .withAdDurationsUs(/* adGroupIndex= */ 2, /* adDurationsUs...= */ 100) + .withAdDurationsUs(/* adGroupIndex= */ 3, /* adDurationsUs...= */ 300) + .withAdDurationsUs(/* adGroupIndex= */ 4, /* adDurationsUs...= */ 200)); + + // stream: 0-- ad1 --100-- c --2100-- ad2 --2400-- c --4300-- ad3 --4500-- c --5000-- ad4 --6000 + // content timeline: 0 - [ad1] - 50-2050 -[ad2] - 2050-3950 - [ad3] - 4350-4850 - [ad4] - 4850 + state = + addAdGroupToAdPlaybackState( + state, + /* fromPositionUs= */ 5000, + /* toPositionUs= */ 6000, + /* contentResumeOffsetUs= */ 0); + + assertThat(state) + .isEqualTo( + new AdPlaybackState( + ADS_ID, /* adGroupTimesUs...= */ + 0, + 0, + 0, + 2050, + 3950, + 4850, + C.TIME_END_OF_SOURCE) + .withRemovedAdGroupCount(2) + .withAdCount(/* adGroupIndex= */ 2, /* adCount= */ 1) + .withAdCount(/* adGroupIndex= */ 3, /* adCount= */ 1) + .withAdCount(/* adGroupIndex= */ 4, /* adCount= */ 1) + .withAdCount(/* adGroupIndex= */ 5, /* adCount= */ 1) + .withIsServerSideInserted(/* adGroupIndex= */ 2, /* isServerSideInserted= */ true) + .withIsServerSideInserted(/* adGroupIndex= */ 3, /* isServerSideInserted= */ true) + .withIsServerSideInserted(/* adGroupIndex= */ 4, /* isServerSideInserted= */ true) + .withIsServerSideInserted(/* adGroupIndex= */ 5, /* isServerSideInserted= */ true) + .withContentResumeOffsetUs(/* adGroupIndex= */ 2, /* contentResumeOffsetUs= */ 50) + .withContentResumeOffsetUs(/* adGroupIndex= */ 4, /* contentResumeOffsetUs= */ 400) + .withAdDurationsUs(/* adGroupIndex= */ 2, /* adDurationsUs...= */ 100) + .withAdDurationsUs(/* adGroupIndex= */ 3, /* adDurationsUs...= */ 300) + .withAdDurationsUs(/* adGroupIndex= */ 4, /* adDurationsUs...= */ 200) + .withAdDurationsUs(/* adGroupIndex= */ 5, /* adDurationsUs...= */ 1000)); + } + + @Test + public void getStreamPositionUsForAd_returnsCorrectPositions() { + // stream: 0-- ad1 --200-- content --2100-- ad2 --2300-- content --4300-- ad3 --4500-- content + // content timeline: 0 - [ad1] - 100-2000 -[ad2] - 2000-4000 - [ad3] - 4400-end + AdPlaybackState state = + new AdPlaybackState(ADS_ID, /* adGroupTimesUs...= */ 0, 0, 0, 2000, 4000) + .withRemovedAdGroupCount(2) + .withAdCount(/* adGroupIndex= */ 2, /* adCount= */ 2) + .withAdCount(/* adGroupIndex= */ 3, /* adCount= */ 1) + .withAdCount(/* adGroupIndex= */ 4, /* adCount= */ 3) + .withContentResumeOffsetUs(/* adGroupIndex= */ 2, /* contentResumeOffsetUs= */ 100) + .withContentResumeOffsetUs(/* adGroupIndex= */ 3, /* contentResumeOffsetUs= */ 0) + .withContentResumeOffsetUs(/* adGroupIndex= */ 4, /* contentResumeOffsetUs= */ 400) + .withAdDurationsUs(/* adGroupIndex= */ 2, /* adDurationsUs...= */ 150, 50) + .withAdDurationsUs(/* adGroupIndex= */ 3, /* adDurationsUs...= */ 200) + .withAdDurationsUs(/* adGroupIndex= */ 4, /* adDurationsUs...= */ 50, 50, 100); + + assertThat( + getStreamPositionUsForAd( + /* positionUs= */ 0, /* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 0, state)) + .isEqualTo(0); + assertThat( + getStreamPositionUsForAd( + /* positionUs= */ 100, /* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 0, state)) + .isEqualTo(100); + assertThat( + getStreamPositionUsForAd( + /* positionUs= */ 200, /* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 0, state)) + .isEqualTo(200); + + assertThat( + getStreamPositionUsForAd( + /* positionUs= */ -50, /* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 1, state)) + .isEqualTo(100); + assertThat( + getStreamPositionUsForAd( + /* positionUs= */ 0, /* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 1, state)) + .isEqualTo(150); + assertThat( + getStreamPositionUsForAd( + /* positionUs= */ 100, /* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 1, state)) + .isEqualTo(250); + + assertThat( + getStreamPositionUsForAd( + /* positionUs= */ -50, /* adGroupIndex= */ 3, /* adIndexInAdGroup= */ 0, state)) + .isEqualTo(2050); + assertThat( + getStreamPositionUsForAd( + /* positionUs= */ 0, /* adGroupIndex= */ 3, /* adIndexInAdGroup= */ 0, state)) + .isEqualTo(2100); + assertThat( + getStreamPositionUsForAd( + /* positionUs= */ 200, /* adGroupIndex= */ 3, /* adIndexInAdGroup= */ 0, state)) + .isEqualTo(2300); + assertThat( + getStreamPositionUsForAd( + /* positionUs= */ 300, /* adGroupIndex= */ 3, /* adIndexInAdGroup= */ 0, state)) + .isEqualTo(2400); + + assertThat( + getStreamPositionUsForAd( + /* positionUs= */ -50, /* adGroupIndex= */ 4, /* adIndexInAdGroup= */ 0, state)) + .isEqualTo(4250); + assertThat( + getStreamPositionUsForAd( + /* positionUs= */ 0, /* adGroupIndex= */ 4, /* adIndexInAdGroup= */ 0, state)) + .isEqualTo(4300); + assertThat( + getStreamPositionUsForAd( + /* positionUs= */ 100, /* adGroupIndex= */ 4, /* adIndexInAdGroup= */ 0, state)) + .isEqualTo(4400); + + assertThat( + getStreamPositionUsForAd( + /* positionUs= */ -50, /* adGroupIndex= */ 4, /* adIndexInAdGroup= */ 1, state)) + .isEqualTo(4300); + assertThat( + getStreamPositionUsForAd( + /* positionUs= */ 0, /* adGroupIndex= */ 4, /* adIndexInAdGroup= */ 1, state)) + .isEqualTo(4350); + assertThat( + getStreamPositionUsForAd( + /* positionUs= */ 100, /* adGroupIndex= */ 4, /* adIndexInAdGroup= */ 1, state)) + .isEqualTo(4450); + + assertThat( + getStreamPositionUsForAd( + /* positionUs= */ -50, /* adGroupIndex= */ 4, /* adIndexInAdGroup= */ 2, state)) + .isEqualTo(4350); + assertThat( + getStreamPositionUsForAd( + /* positionUs= */ 50, /* adGroupIndex= */ 4, /* adIndexInAdGroup= */ 2, state)) + .isEqualTo(4450); + assertThat( + getStreamPositionUsForAd( + /* positionUs= */ 150, /* adGroupIndex= */ 4, /* adIndexInAdGroup= */ 2, state)) + .isEqualTo(4550); + } + + @Test + public void getMediaPeriodPositionUsForAd_returnsCorrectPositions() { + // stream: 0-- ad1 --200-- content --2100-- ad2 --2300-- content --4300-- ad3 --4500-- content + // content timeline: 0 - [ad1] - 100-2000 -[ad2] - 2000-4000 - [ad3] - 4400-end + AdPlaybackState state = + new AdPlaybackState(ADS_ID, /* adGroupTimesUs...= */ 0, 0, 0, 2000, 4000) + .withRemovedAdGroupCount(2) + .withAdCount(/* adGroupIndex= */ 2, /* adCount= */ 2) + .withAdCount(/* adGroupIndex= */ 3, /* adCount= */ 1) + .withAdCount(/* adGroupIndex= */ 4, /* adCount= */ 3) + .withContentResumeOffsetUs(/* adGroupIndex= */ 2, /* contentResumeOffsetUs= */ 100) + .withContentResumeOffsetUs(/* adGroupIndex= */ 3, /* contentResumeOffsetUs= */ 0) + .withContentResumeOffsetUs(/* adGroupIndex= */ 4, /* contentResumeOffsetUs= */ 400) + .withAdDurationsUs(/* adGroupIndex= */ 2, /* adDurationsUs...= */ 150, 50) + .withAdDurationsUs(/* adGroupIndex= */ 3, /* adDurationsUs...= */ 200) + .withAdDurationsUs(/* adGroupIndex= */ 4, /* adDurationsUs...= */ 50, 50, 100); + + assertThat( + getMediaPeriodPositionUsForAd( + /* positionUs= */ 0, /* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 0, state)) + .isEqualTo(0); + + assertThat( + getMediaPeriodPositionUsForAd( + /* positionUs= */ 100, /* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 0, state)) + .isEqualTo(100); + assertThat( + getMediaPeriodPositionUsForAd( + /* positionUs= */ 100, /* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 1, state)) + .isEqualTo(-50); + + assertThat( + getMediaPeriodPositionUsForAd( + /* positionUs= */ 200, /* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 0, state)) + .isEqualTo(200); + assertThat( + getMediaPeriodPositionUsForAd( + /* positionUs= */ 200, /* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 1, state)) + .isEqualTo(50); + + assertThat( + getMediaPeriodPositionUsForAd( + /* positionUs= */ 300, /* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 1, state)) + .isEqualTo(150); + + assertThat( + getMediaPeriodPositionUsForAd( + /* positionUs= */ 2000, /* adGroupIndex= */ 3, /* adIndexInAdGroup= */ 0, state)) + .isEqualTo(-100); + + assertThat( + getMediaPeriodPositionUsForAd( + /* positionUs= */ 2100, /* adGroupIndex= */ 3, /* adIndexInAdGroup= */ 0, state)) + .isEqualTo(0); + + assertThat( + getMediaPeriodPositionUsForAd( + /* positionUs= */ 2300, /* adGroupIndex= */ 3, /* adIndexInAdGroup= */ 0, state)) + .isEqualTo(200); + + assertThat( + getMediaPeriodPositionUsForAd( + /* positionUs= */ 4300, /* adGroupIndex= */ 4, /* adIndexInAdGroup= */ 0, state)) + .isEqualTo(0); + assertThat( + getMediaPeriodPositionUsForAd( + /* positionUs= */ 4300, /* adGroupIndex= */ 4, /* adIndexInAdGroup= */ 1, state)) + .isEqualTo(-50); + assertThat( + getMediaPeriodPositionUsForAd( + /* positionUs= */ 4300, /* adGroupIndex= */ 4, /* adIndexInAdGroup= */ 2, state)) + .isEqualTo(-100); + + assertThat( + getMediaPeriodPositionUsForAd( + /* positionUs= */ 4400, /* adGroupIndex= */ 4, /* adIndexInAdGroup= */ 0, state)) + .isEqualTo(100); + assertThat( + getMediaPeriodPositionUsForAd( + /* positionUs= */ 4400, /* adGroupIndex= */ 4, /* adIndexInAdGroup= */ 1, state)) + .isEqualTo(50); + assertThat( + getMediaPeriodPositionUsForAd( + /* positionUs= */ 4400, /* adGroupIndex= */ 4, /* adIndexInAdGroup= */ 2, state)) + .isEqualTo(0); + + assertThat( + getMediaPeriodPositionUsForAd( + /* positionUs= */ 4500, /* adGroupIndex= */ 4, /* adIndexInAdGroup= */ 1, state)) + .isEqualTo(150); + assertThat( + getMediaPeriodPositionUsForAd( + /* positionUs= */ 4500, /* adGroupIndex= */ 4, /* adIndexInAdGroup= */ 2, state)) + .isEqualTo(100); + + assertThat( + getMediaPeriodPositionUsForAd( + /* positionUs= */ 4700, /* adGroupIndex= */ 4, /* adIndexInAdGroup= */ 1, state)) + .isEqualTo(350); + assertThat( + getMediaPeriodPositionUsForAd( + /* positionUs= */ 4700, /* adGroupIndex= */ 4, /* adIndexInAdGroup= */ 2, state)) + .isEqualTo(300); + } + + @Test + public void getStreamPositionUsForContent_returnsCorrectPositions() { + // stream: 0-- ad1 --200-- content --2100-- ad2 --2300-- content --4300-- ad3 --4500-- content + // content timeline: 0 - [ad1] - 100-2000 -[ad2] - 2000-4000 - [ad3] - 4400-end + AdPlaybackState state = + new AdPlaybackState(ADS_ID, /* adGroupTimesUs...= */ 0, 0, 0, 2000, 4000) + .withRemovedAdGroupCount(2) + .withAdCount(/* adGroupIndex= */ 2, /* adCount= */ 2) + .withAdCount(/* adGroupIndex= */ 3, /* adCount= */ 1) + .withAdCount(/* adGroupIndex= */ 4, /* adCount= */ 3) + .withContentResumeOffsetUs(/* adGroupIndex= */ 2, /* contentResumeOffsetUs= */ 100) + .withContentResumeOffsetUs(/* adGroupIndex= */ 3, /* contentResumeOffsetUs= */ 0) + .withContentResumeOffsetUs(/* adGroupIndex= */ 4, /* contentResumeOffsetUs= */ 400) + .withAdDurationsUs(/* adGroupIndex= */ 2, /* adDurationsUs...= */ 150, 50) + .withAdDurationsUs(/* adGroupIndex= */ 3, /* adDurationsUs...= */ 200) + .withAdDurationsUs(/* adGroupIndex= */ 4, /* adDurationsUs...= */ 50, 50, 100); + + assertThat(getStreamPositionUsForContent(/* positionUs= */ 0, /* nextAdGroupIndex= */ 2, state)) + .isEqualTo(0); + assertThat(getStreamPositionUsForContent(/* positionUs= */ 0, /* nextAdGroupIndex= */ 3, state)) + .isEqualTo(100); + assertThat( + getStreamPositionUsForContent( + /* positionUs= */ 0, /* nextAdGroupIndex= */ C.INDEX_UNSET, state)) + .isEqualTo(100); + + assertThat( + getStreamPositionUsForContent(/* positionUs= */ 50, /* nextAdGroupIndex= */ 2, state)) + .isEqualTo(50); + assertThat( + getStreamPositionUsForContent(/* positionUs= */ 50, /* nextAdGroupIndex= */ 3, state)) + .isEqualTo(150); + assertThat( + getStreamPositionUsForContent( + /* positionUs= */ 50, /* nextAdGroupIndex= */ C.INDEX_UNSET, state)) + .isEqualTo(150); + + assertThat( + getStreamPositionUsForContent(/* positionUs= */ 100, /* nextAdGroupIndex= */ 3, state)) + .isEqualTo(200); + assertThat( + getStreamPositionUsForContent( + /* positionUs= */ 100, /* nextAdGroupIndex= */ C.INDEX_UNSET, state)) + .isEqualTo(200); + + assertThat( + getStreamPositionUsForContent(/* positionUs= */ 1999, /* nextAdGroupIndex= */ 3, state)) + .isEqualTo(2099); + assertThat( + getStreamPositionUsForContent( + /* positionUs= */ 1999, /* nextAdGroupIndex= */ C.INDEX_UNSET, state)) + .isEqualTo(2099); + + assertThat( + getStreamPositionUsForContent(/* positionUs= */ 2000, /* nextAdGroupIndex= */ 3, state)) + .isEqualTo(2100); + assertThat( + getStreamPositionUsForContent(/* positionUs= */ 2000, /* nextAdGroupIndex= */ 4, state)) + .isEqualTo(2300); + assertThat( + getStreamPositionUsForContent( + /* positionUs= */ 2000, /* nextAdGroupIndex= */ C.INDEX_UNSET, state)) + .isEqualTo(2300); + + assertThat( + getStreamPositionUsForContent(/* positionUs= */ 3999, /* nextAdGroupIndex= */ 4, state)) + .isEqualTo(4299); + assertThat( + getStreamPositionUsForContent( + /* positionUs= */ 3999, /* nextAdGroupIndex= */ C.INDEX_UNSET, state)) + .isEqualTo(4299); + + assertThat( + getStreamPositionUsForContent(/* positionUs= */ 4000, /* nextAdGroupIndex= */ 4, state)) + .isEqualTo(4300); + assertThat( + getStreamPositionUsForContent( + /* positionUs= */ 4000, /* nextAdGroupIndex= */ C.INDEX_UNSET, state)) + .isEqualTo(4300); + + assertThat( + getStreamPositionUsForContent( + /* positionUs= */ 4200, /* nextAdGroupIndex= */ C.INDEX_UNSET, state)) + .isEqualTo(4300); + + assertThat( + getStreamPositionUsForContent( + /* positionUs= */ 4300, /* nextAdGroupIndex= */ C.INDEX_UNSET, state)) + .isEqualTo(4400); + + assertThat( + getStreamPositionUsForContent( + /* positionUs= */ 4400, /* nextAdGroupIndex= */ C.INDEX_UNSET, state)) + .isEqualTo(4500); + } + + @Test + public void getMediaPeriodPositionUsForContent_returnsCorrectPositions() { + // stream: 0-- ad1 --200-- content --2100-- ad2 --2300-- content --4300-- ad3 --4500-- content + // content timeline: 0 - [ad1] - 100-2000 -[ad2] - 2000-4000 - [ad3] - 4400-end + AdPlaybackState state = + new AdPlaybackState(ADS_ID, /* adGroupTimesUs...= */ 0, 0, 0, 2000, 4000) + .withRemovedAdGroupCount(2) + .withAdCount(/* adGroupIndex= */ 2, /* adCount= */ 2) + .withAdCount(/* adGroupIndex= */ 3, /* adCount= */ 1) + .withAdCount(/* adGroupIndex= */ 4, /* adCount= */ 3) + .withContentResumeOffsetUs(/* adGroupIndex= */ 2, /* contentResumeOffsetUs= */ 100) + .withContentResumeOffsetUs(/* adGroupIndex= */ 3, /* contentResumeOffsetUs= */ 0) + .withContentResumeOffsetUs(/* adGroupIndex= */ 4, /* contentResumeOffsetUs= */ 400) + .withAdDurationsUs(/* adGroupIndex= */ 2, /* adDurationsUs...= */ 150, 50) + .withAdDurationsUs(/* adGroupIndex= */ 3, /* adDurationsUs...= */ 200) + .withAdDurationsUs(/* adGroupIndex= */ 4, /* adDurationsUs...= */ 50, 50, 100); + + assertThat( + getMediaPeriodPositionUsForContent( + /* positionUs= */ 0, /* nextAdGroupIndex= */ 2, state)) + .isEqualTo(0); + assertThat( + getMediaPeriodPositionUsForContent( + /* positionUs= */ 0, /* nextAdGroupIndex= */ 3, state)) + .isEqualTo(0); + assertThat( + getMediaPeriodPositionUsForContent( + /* positionUs= */ 0, /* nextAdGroupIndex= */ C.INDEX_UNSET, state)) + .isEqualTo(0); + + assertThat( + getMediaPeriodPositionUsForContent( + /* positionUs= */ 100, /* nextAdGroupIndex= */ 2, state)) + .isEqualTo(100); + assertThat( + getMediaPeriodPositionUsForContent( + /* positionUs= */ 100, /* nextAdGroupIndex= */ 3, state)) + .isEqualTo(0); + assertThat( + getMediaPeriodPositionUsForContent( + /* positionUs= */ 100, /* nextAdGroupIndex= */ C.INDEX_UNSET, state)) + .isEqualTo(0); + + assertThat( + getMediaPeriodPositionUsForContent( + /* positionUs= */ 200, /* nextAdGroupIndex= */ 3, state)) + .isEqualTo(100); + assertThat( + getMediaPeriodPositionUsForContent( + /* positionUs= */ 200, /* nextAdGroupIndex= */ C.INDEX_UNSET, state)) + .isEqualTo(100); + + assertThat( + getMediaPeriodPositionUsForContent( + /* positionUs= */ 2099, /* nextAdGroupIndex= */ 3, state)) + .isEqualTo(1999); + assertThat( + getMediaPeriodPositionUsForContent( + /* positionUs= */ 2099, /* nextAdGroupIndex= */ C.INDEX_UNSET, state)) + .isEqualTo(1999); + + assertThat( + getMediaPeriodPositionUsForContent( + /* positionUs= */ 2100, /* nextAdGroupIndex= */ 3, state)) + .isEqualTo(2000); + assertThat( + getMediaPeriodPositionUsForContent( + /* positionUs= */ 2100, /* nextAdGroupIndex= */ 4, state)) + .isEqualTo(2000); + assertThat( + getMediaPeriodPositionUsForContent( + /* positionUs= */ 2100, /* nextAdGroupIndex= */ C.INDEX_UNSET, state)) + .isEqualTo(2000); + + assertThat( + getMediaPeriodPositionUsForContent( + /* positionUs= */ 2300, /* nextAdGroupIndex= */ 3, state)) + .isEqualTo(2200); + assertThat( + getMediaPeriodPositionUsForContent( + /* positionUs= */ 2300, /* nextAdGroupIndex= */ 4, state)) + .isEqualTo(2000); + assertThat( + getMediaPeriodPositionUsForContent( + /* positionUs= */ 2300, /* nextAdGroupIndex= */ C.INDEX_UNSET, state)) + .isEqualTo(2000); + + assertThat( + getMediaPeriodPositionUsForContent( + /* positionUs= */ 4299, /* nextAdGroupIndex= */ 4, state)) + .isEqualTo(3999); + assertThat( + getMediaPeriodPositionUsForContent( + /* positionUs= */ 4299, /* nextAdGroupIndex= */ C.INDEX_UNSET, state)) + .isEqualTo(3999); + + assertThat( + getMediaPeriodPositionUsForContent( + /* positionUs= */ 4300, /* nextAdGroupIndex= */ 4, state)) + .isEqualTo(4000); + assertThat( + getMediaPeriodPositionUsForContent( + /* positionUs= */ 4300, /* nextAdGroupIndex= */ C.INDEX_UNSET, state)) + .isEqualTo(4200); + + assertThat( + getMediaPeriodPositionUsForContent( + /* positionUs= */ 4500, /* nextAdGroupIndex= */ 4, state)) + .isEqualTo(4200); + assertThat( + getMediaPeriodPositionUsForContent( + /* positionUs= */ 4500, /* nextAdGroupIndex= */ C.INDEX_UNSET, state)) + .isEqualTo(4400); + + assertThat( + getMediaPeriodPositionUsForContent( + /* positionUs= */ 4700, /* nextAdGroupIndex= */ C.INDEX_UNSET, state)) + .isEqualTo(4600); + } + + @Test + public void getAdCountInGroup_withUnsetCount_returnsZero() { + AdPlaybackState state = new AdPlaybackState(ADS_ID, /* adGroupTimesUs...= */ 0, 2000); + + assertThat(getAdCountInGroup(state, /* adGroupIndex= */ 0)).isEqualTo(0); + assertThat(getAdCountInGroup(state, /* adGroupIndex= */ 1)).isEqualTo(0); + } + + @Test + public void getAdCountInGroup_withSetCount_returnsCount() { + AdPlaybackState state = + new AdPlaybackState(ADS_ID, /* adGroupTimesUs...= */ 0, 2000) + .withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 4) + .withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 6); + + assertThat(getAdCountInGroup(state, /* adGroupIndex= */ 0)).isEqualTo(4); + assertThat(getAdCountInGroup(state, /* adGroupIndex= */ 1)).isEqualTo(6); + } +} diff --git a/library/core/src/test/java/com/google/android/exoplayer2/text/CueTest.java b/library/core/src/test/java/com/google/android/exoplayer2/text/CueTest.java index 1d33c2834e6..1d9f6e836cf 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/text/CueTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/text/CueTest.java @@ -21,6 +21,8 @@ import android.graphics.Bitmap; import android.graphics.Color; +import android.os.Bundle; +import android.os.Parcel; import android.text.Layout; import android.text.SpannedString; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -105,4 +107,48 @@ public void buildWithBothTextAndBitmapFails() { .setBitmap(Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)) .build()); } + + @Test + public void roundTripViaBundle_yieldsEqualInstance() { + Cue cue = + new Cue.Builder() + .setText(SpannedString.valueOf("text")) + .setTextAlignment(Layout.Alignment.ALIGN_CENTER) + .setMultiRowAlignment(Layout.Alignment.ALIGN_NORMAL) + .setLine(5, Cue.LINE_TYPE_NUMBER) + .setLineAnchor(Cue.ANCHOR_TYPE_END) + .setPosition(0.4f) + .setPositionAnchor(Cue.ANCHOR_TYPE_MIDDLE) + .setTextSize(0.2f, Cue.TEXT_SIZE_TYPE_FRACTIONAL) + .setSize(0.8f) + .setWindowColor(Color.CYAN) + .setVerticalType(Cue.VERTICAL_TYPE_RL) + .setShearDegrees(-15f) + .build(); + Cue modifiedCue = parcelAndUnParcelCue(cue); + + assertThat(modifiedCue).isEqualTo(cue); + } + + @Test + public void roundTripViaBundle_withBitmap_yieldsEqualInstance() { + Cue cue = + new Cue.Builder().setBitmap(Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)).build(); + Cue modifiedCue = parcelAndUnParcelCue(cue); + + assertThat(modifiedCue).isEqualTo(cue); + } + + private static Cue parcelAndUnParcelCue(Cue cue) { + Parcel parcel = Parcel.obtain(); + try { + parcel.writeBundle(cue.toBundle()); + parcel.setDataPosition(0); + + Bundle bundle = parcel.readBundle(); + return Cue.CREATOR.fromBundle(bundle); + } finally { + parcel.recycle(); + } + } } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/text/ssa/SsaDecoderTest.java b/library/core/src/test/java/com/google/android/exoplayer2/text/ssa/SsaDecoderTest.java index 3a06360b86a..4b3b8cef64e 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/text/ssa/SsaDecoderTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/text/ssa/SsaDecoderTest.java @@ -38,6 +38,7 @@ public final class SsaDecoderTest { private static final String EMPTY = "media/ssa/empty"; + private static final String EMPTY_STYLE_LINE = "media/ssa/empty_style_line"; private static final String TYPICAL = "media/ssa/typical"; private static final String TYPICAL_HEADER_ONLY = "media/ssa/typical_header"; private static final String TYPICAL_DIALOGUE_ONLY = "media/ssa/typical_dialogue"; @@ -60,7 +61,27 @@ public void decodeEmpty() throws IOException { Subtitle subtitle = decoder.decode(bytes, bytes.length, false); assertThat(subtitle.getEventTimeCount()).isEqualTo(0); - assertThat(subtitle.getCues(0).isEmpty()).isTrue(); + } + + @Test + public void decodeEmptyStyleLine() throws IOException { + SsaDecoder decoder = new SsaDecoder(); + byte[] bytes = + TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), EMPTY_STYLE_LINE); + Subtitle subtitle = decoder.decode(bytes, bytes.length, /* reset= */ false); + + assertThat(subtitle.getEventTimeCount()).isEqualTo(2); + Cue cue = Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(0))); + SpannedSubject.assertThat((Spanned) cue.text).hasNoSpans(); + assertThat(cue.textSize).isEqualTo(Cue.DIMEN_UNSET); + assertThat(cue.textSizeType).isEqualTo(Cue.TYPE_UNSET); + assertThat(cue.textAlignment).isNull(); + assertThat(cue.positionAnchor).isEqualTo(Cue.TYPE_UNSET); + assertThat(cue.position).isEqualTo(Cue.DIMEN_UNSET); + assertThat(cue.size).isEqualTo(Cue.DIMEN_UNSET); + assertThat(cue.lineAnchor).isEqualTo(Cue.TYPE_UNSET); + assertThat(cue.line).isEqualTo(Cue.DIMEN_UNSET); + assertThat(cue.lineType).isEqualTo(Cue.LINE_TYPE_FRACTION); } @Test diff --git a/library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TtmlDecoderTest.java b/library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TtmlDecoderTest.java index d068ade74b1..67b4ec64b7b 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TtmlDecoderTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TtmlDecoderTest.java @@ -710,6 +710,18 @@ public void rubies() throws IOException, SubtitleDecoderException { Spanned sixthCue = getOnlyCueTextAtTimeUs(subtitle, 60_000_000); assertThat(sixthCue.toString()).isEqualTo("Cue with annotated text."); assertThat(sixthCue).hasNoRubySpanBetween(0, sixthCue.length()); + + Spanned seventhCue = getOnlyCueTextAtTimeUs(subtitle, 70_000_000); + assertThat(seventhCue.toString()).isEqualTo("Cue with annotated text."); + assertThat(seventhCue) + .hasRubySpanBetween("Cue with ".length(), "Cue with annotated".length()) + .withTextAndPosition("rubies", TextAnnotation.POSITION_BEFORE); + + Spanned eighthCue = getOnlyCueTextAtTimeUs(subtitle, 80_000_000); + assertThat(eighthCue.toString()).isEqualTo("Cue with annotated text."); + assertThat(eighthCue) + .hasRubySpanBetween("Cue with ".length(), "Cue with annotated".length()) + .withTextAndPosition("rubies", TextAnnotation.POSITION_AFTER); } @Test diff --git a/library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TtmlRenderUtilTest.java b/library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TtmlRenderUtilTest.java index f9d12aefd15..ce57d720de0 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TtmlRenderUtilTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TtmlRenderUtilTest.java @@ -122,5 +122,4 @@ private static Map getGlobalStyles() { return globalStyles; } - } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/text/webvtt/Mp4WebvttDecoderTest.java b/library/core/src/test/java/com/google/android/exoplayer2/text/webvtt/Mp4WebvttDecoderTest.java index 18a76c1a575..a81d1665e3a 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/text/webvtt/Mp4WebvttDecoderTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/text/webvtt/Mp4WebvttDecoderTest.java @@ -33,54 +33,127 @@ public final class Mp4WebvttDecoderTest { private static final byte[] SINGLE_CUE_SAMPLE = { - 0x00, 0x00, 0x00, 0x1C, // Size - 0x76, 0x74, 0x74, 0x63, // "vttc" Box type. VTT Cue box begins: - - 0x00, 0x00, 0x00, 0x14, // Contained payload box's size - 0x70, 0x61, 0x79, 0x6c, // Contained payload box's type (payl), Cue Payload Box begins: - - 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x0a // Hello World\n + 0x00, + 0x00, + 0x00, + 0x1C, // Size + 0x76, + 0x74, + 0x74, + 0x63, // "vttc" Box type. VTT Cue box begins: + 0x00, + 0x00, + 0x00, + 0x14, // Contained payload box's size + 0x70, + 0x61, + 0x79, + 0x6c, // Contained payload box's type (payl), Cue Payload Box begins: + 0x48, + 0x65, + 0x6c, + 0x6c, + 0x6f, + 0x20, + 0x57, + 0x6f, + 0x72, + 0x6c, + 0x64, + 0x0a // Hello World\n }; private static final byte[] DOUBLE_CUE_SAMPLE = { - 0x00, 0x00, 0x00, 0x1B, // Size - 0x76, 0x74, 0x74, 0x63, // "vttc" Box type. First VTT Cue box begins: - - 0x00, 0x00, 0x00, 0x13, // First contained payload box's size - 0x70, 0x61, 0x79, 0x6c, // First contained payload box's type (payl), Cue Payload Box begins: - - 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, // Hello World - - 0x00, 0x00, 0x00, 0x17, // Size - 0x76, 0x74, 0x74, 0x63, // "vttc" Box type. Second VTT Cue box begins: - - 0x00, 0x00, 0x00, 0x0F, // Contained payload box's size - 0x70, 0x61, 0x79, 0x6c, // Contained payload box's type (payl), Payload begins: - - 0x42, 0x79, 0x65, 0x20, 0x42, 0x79, 0x65 // Bye Bye + 0x00, + 0x00, + 0x00, + 0x1B, // Size + 0x76, + 0x74, + 0x74, + 0x63, // "vttc" Box type. First VTT Cue box begins: + 0x00, + 0x00, + 0x00, + 0x13, // First contained payload box's size + 0x70, + 0x61, + 0x79, + 0x6c, // First contained payload box's type (payl), Cue Payload Box begins: + 0x48, + 0x65, + 0x6c, + 0x6c, + 0x6f, + 0x20, + 0x57, + 0x6f, + 0x72, + 0x6c, + 0x64, // Hello World + 0x00, + 0x00, + 0x00, + 0x17, // Size + 0x76, + 0x74, + 0x74, + 0x63, // "vttc" Box type. Second VTT Cue box begins: + 0x00, + 0x00, + 0x00, + 0x0F, // Contained payload box's size + 0x70, + 0x61, + 0x79, + 0x6c, // Contained payload box's type (payl), Payload begins: + 0x42, + 0x79, + 0x65, + 0x20, + 0x42, + 0x79, + 0x65 // Bye Bye }; private static final byte[] NO_CUE_SAMPLE = { - 0x00, 0x00, 0x00, 0x1B, // Size - 0x74, 0x74, 0x74, 0x63, // "tttc" Box type, which is not a Cue. Should be skipped: - - 0x00, 0x00, 0x00, 0x13, // Contained payload box's size - 0x70, 0x61, 0x79, 0x6c, // Contained payload box's type (payl), Cue Payload Box begins: - - 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64 // Hello World + 0x00, + 0x00, + 0x00, + 0x1B, // Size + 0x74, + 0x74, + 0x74, + 0x63, // "tttc" Box type, which is not a Cue. Should be skipped: + 0x00, + 0x00, + 0x00, + 0x13, // Contained payload box's size + 0x70, + 0x61, + 0x79, + 0x6c, // Contained payload box's type (payl), Cue Payload Box begins: + 0x48, + 0x65, + 0x6c, + 0x6c, + 0x6f, + 0x20, + 0x57, + 0x6f, + 0x72, + 0x6c, + 0x64 // Hello World }; private static final byte[] INCOMPLETE_HEADER_SAMPLE = { - 0x00, 0x00, 0x00, 0x23, // Size - 0x76, 0x74, 0x74, 0x63, // "vttc" Box type. VTT Cue box begins: - - 0x00, 0x00, 0x00, 0x14, // Contained payload box's size - 0x70, 0x61, 0x79, 0x6c, // Contained payload box's type (payl), Cue Payload Box begins: - - 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x0a, // Hello World\n - - 0x00, 0x00, 0x00, 0x07, // Size of an incomplete header, which belongs to the first vttc box. - 0x76, 0x74, 0x74 + 0x00, 0x00, 0x00, 0x23, // Size + 0x76, 0x74, 0x74, 0x63, // "vttc" Box type. VTT Cue box begins: + 0x00, 0x00, 0x00, 0x14, // Contained payload box's size + 0x70, 0x61, 0x79, 0x6c, // Contained payload box's type (payl), Cue Payload Box begins: + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x0a, // Hello World\n + 0x00, 0x00, 0x00, 0x07, // Size of an incomplete header, which belongs to the first vttc box. + 0x76, 0x74, 0x74 }; @Rule public final Expect expect = Expect.create(); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/text/webvtt/CssParserTest.java b/library/core/src/test/java/com/google/android/exoplayer2/text/webvtt/WebvttCssParserTest.java similarity index 96% rename from library/core/src/test/java/com/google/android/exoplayer2/text/webvtt/CssParserTest.java rename to library/core/src/test/java/com/google/android/exoplayer2/text/webvtt/WebvttCssParserTest.java index 797a0b5d94c..095dd02b66d 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/text/webvtt/CssParserTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/text/webvtt/WebvttCssParserTest.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.text.webvtt; -import static com.google.android.exoplayer2.text.webvtt.CssParser.parseNextToken; +import static com.google.android.exoplayer2.text.webvtt.WebvttCssParser.parseNextToken; import static com.google.common.truth.Truth.assertThat; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -29,15 +29,15 @@ import org.junit.Test; import org.junit.runner.RunWith; -/** Unit test for {@link CssParser}. */ +/** Unit test for {@link WebvttCssParser}. */ @RunWith(AndroidJUnit4.class) -public final class CssParserTest { +public final class WebvttCssParserTest { - private CssParser parser; + private WebvttCssParser parser; @Before public void setUp() { - parser = new CssParser(); + parser = new WebvttCssParser(); } @Test @@ -180,7 +180,7 @@ public void styleScoreSystem() { // Universal selector. assertThat(style.getSpecificityScore("", "", Collections.emptySet(), "")).isEqualTo(1); // Class match without tag match. - style.setTargetClasses(new String[] { "class1", "class2"}); + style.setTargetClasses(new String[] {"class1", "class2"}); assertThat( style.getSpecificityScore( "", "", new HashSet<>(Arrays.asList("class1", "class2", "class3")), "")) @@ -232,13 +232,13 @@ public void styleScoreSystem() { private void assertSkipsToEndOfSkip(String expectedLine, String s) { ParsableByteArray input = new ParsableByteArray(Util.getUtf8Bytes(s)); - CssParser.skipWhitespaceAndComments(input); + WebvttCssParser.skipWhitespaceAndComments(input); assertThat(input.readLine()).isEqualTo(expectedLine); } private void assertInputLimit(String expectedLine, String s) { ParsableByteArray input = new ParsableByteArray(Util.getUtf8Bytes(s)); - CssParser.skipStyleBlock(input); + WebvttCssParser.skipStyleBlock(input); assertThat(input.readLine()).isEqualTo(expectedLine); } @@ -265,5 +265,4 @@ private void assertParserProduces(String styleBlock, WebvttCssStyle... expectedS assertThat(actualElem.isUnderline()).isEqualTo(expected.isUnderline()); } } - } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/text/webvtt/WebvttCueParserTest.java b/library/core/src/test/java/com/google/android/exoplayer2/text/webvtt/WebvttCueParserTest.java index 778820b451e..a576958b88e 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/text/webvtt/WebvttCueParserTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/text/webvtt/WebvttCueParserTest.java @@ -31,8 +31,10 @@ public final class WebvttCueParserTest { @Test public void parseStrictValidClassesAndTrailingTokens() throws Exception { - Spanned text = parseCueText("" - + "This is text with html tags"); + Spanned text = + parseCueText( + "This is text with" + + " html tags"); assertThat(text.toString()).isEqualTo("This is text with html tags"); assertThat(text).hasUnderlineSpanBetween("This ".length(), "This is".length()); @@ -42,8 +44,10 @@ public void parseStrictValidClassesAndTrailingTokens() throws Exception { @Test public void parseStrictValidUnsupportedTagsStrippedOut() throws Exception { - Spanned text = parseCueText("This is text with " - + "html tags"); + Spanned text = + parseCueText( + "This is text with " + + "html tags"); assertThat(text.toString()).isEqualTo("This is text with html tags"); assertThat(text).hasNoSpans(); @@ -92,8 +96,8 @@ public void parseUnsupportedDefaultBackgroundColor() throws Exception { @Test public void parseWellFormedUnclosedEndAtCueEnd() throws Exception { - Spanned text = parseCueText("An unclosed u tag with " - + "italic inside"); + Spanned text = + parseCueText("An unclosed u tag with " + "italic inside"); assertThat(text.toString()).isEqualTo("An unclosed u tag with italic inside"); assertThat(text) @@ -201,11 +205,13 @@ public void parseInvalidVoidSlash() { @Test public void parseMonkey() throws Exception { - Spanned text = parseCueText("< u>An unclosed u tag with <<<<< i>italic" - + " inside"); + Spanned text = + parseCueText( + "< u>An unclosed u tag with <<<<< i>italic" + " inside"); assertThat(text.toString()).isEqualTo("An unclosed u tag with italic inside"); - text = parseCueText(">>>>>>>>>An unclosed u tag with <<<<< italic" - + " inside"); + text = + parseCueText( + ">>>>>>>>>An unclosed u tag with <<<<< italic" + " inside"); assertThat(text.toString()).isEqualTo(">>>>>>>>>An unclosed u tag with inside"); } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/text/webvtt/WebvttDecoderTest.java b/library/core/src/test/java/com/google/android/exoplayer2/text/webvtt/WebvttDecoderTest.java index eb565b09f57..4044d3d3902 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/text/webvtt/WebvttDecoderTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/text/webvtt/WebvttDecoderTest.java @@ -54,6 +54,7 @@ public class WebvttDecoderTest { private static final String WITH_BAD_CUE_HEADER_FILE = "media/webvtt/with_bad_cue_header"; private static final String WITH_TAGS_FILE = "media/webvtt/with_tags"; private static final String WITH_CSS_STYLES = "media/webvtt/with_css_styles"; + private static final String WITH_FONT_SIZE = "media/webvtt/with_font_size"; private static final String WITH_CSS_COMPLEX_SELECTORS = "media/webvtt/with_css_complex_selectors"; private static final String WITH_CSS_TEXT_COMBINE_UPRIGHT = @@ -400,6 +401,58 @@ public void decodeWithBadCueHeader() throws Exception { assertThat(secondCue.text.toString()).isEqualTo("This is the third subtitle."); } + @Test + public void decodeWithCssFontSizeStyle() throws Exception { + WebvttSubtitle subtitle = getSubtitleForTestAsset(WITH_FONT_SIZE); + + assertThat(subtitle.getEventTimeCount()).isEqualTo(12); + + assertThat(subtitle.getEventTime(0)).isEqualTo(0L); + assertThat(subtitle.getEventTime(1)).isEqualTo(2_000_000L); + Cue firstCue = Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(0))); + assertThat(firstCue.text.toString()).isEqualTo("Sentence with font-size set to 4.4em."); + assertThat((Spanned) firstCue.text) + .hasRelativeSizeSpanBetween(0, "Sentence with font-size set to 4.4em.".length()) + .withSizeChange(4.4f); + + assertThat(subtitle.getEventTime(2)).isEqualTo(2_100_000L); + assertThat(subtitle.getEventTime(3)).isEqualTo(2_400_000L); + Cue secondCue = Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(2))); + assertThat(secondCue.text.toString()).isEqualTo("Sentence with bad font-size unit."); + assertThat((Spanned) secondCue.text).hasNoSpans(); + + assertThat(subtitle.getEventTime(4)).isEqualTo(2_500_000L); + assertThat(subtitle.getEventTime(5)).isEqualTo(4_000_000L); + Cue thirdCue = Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(4))); + assertThat(thirdCue.text.toString()).isEqualTo("Absolute font-size expressed in px unit!"); + assertThat((Spanned) thirdCue.text) + .hasAbsoluteSizeSpanBetween(0, "Absolute font-size expressed in px unit!".length()) + .withAbsoluteSize(2); + + assertThat(subtitle.getEventTime(6)).isEqualTo(4_500_000L); + assertThat(subtitle.getEventTime(7)).isEqualTo(6_000_000L); + Cue fourthCue = Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(6))); + assertThat(fourthCue.text.toString()).isEqualTo("Relative font-size expressed in % unit!"); + assertThat((Spanned) fourthCue.text) + .hasRelativeSizeSpanBetween(0, "Relative font-size expressed in % unit!".length()) + .withSizeChange(0.035f); + + assertThat(subtitle.getEventTime(8)).isEqualTo(6_100_000L); + assertThat(subtitle.getEventTime(9)).isEqualTo(6_400_000L); + Cue fifthCue = Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(8))); + assertThat(fifthCue.text.toString()).isEqualTo("Sentence with bad font-size value."); + assertThat((Spanned) secondCue.text).hasNoSpans(); + + assertThat(subtitle.getEventTime(10)).isEqualTo(6_500_000L); + assertThat(subtitle.getEventTime(11)).isEqualTo(8_000_000L); + Cue sixthCue = Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(10))); + assertThat(sixthCue.text.toString()) + .isEqualTo("Upper and lower case letters in font-size unit."); + assertThat((Spanned) sixthCue.text) + .hasAbsoluteSizeSpanBetween(0, "Upper and lower case letters in font-size unit.".length()) + .withAbsoluteSize(2); + } + @Test public void webvttWithCssStyle() throws Exception { WebvttSubtitle subtitle = getSubtitleForTestAsset(WITH_CSS_STYLES); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelectorTest.java b/library/core/src/test/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelectorTest.java index 29f3e690014..81959d35d8b 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelectorTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelectorTest.java @@ -30,8 +30,6 @@ import android.content.Context; import android.os.Parcel; -import android.util.SparseArray; -import android.util.SparseBooleanArray; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.C; @@ -51,7 +49,6 @@ import com.google.android.exoplayer2.upstream.BandwidthMeter; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.Util; -import com.google.common.collect.ImmutableList; import java.util.HashMap; import java.util.Map; import org.junit.Before; @@ -1725,55 +1722,50 @@ private static Format buildAudioFormatWithConfiguration( * variables. */ private static Parameters buildParametersForEqualsTest() { - SparseArray> selectionOverrides = new SparseArray<>(); - Map videoOverrides = new HashMap<>(); - videoOverrides.put(new TrackGroupArray(VIDEO_TRACK_GROUP), new SelectionOverride(0, 1)); - selectionOverrides.put(2, videoOverrides); - - SparseBooleanArray rendererDisabledFlags = new SparseBooleanArray(); - rendererDisabledFlags.put(3, true); - - return new Parameters( + return Parameters.DEFAULT_WITHOUT_CONTEXT + .buildUpon() // Video - /* maxVideoWidth= */ 0, - /* maxVideoHeight= */ 1, - /* maxVideoFrameRate= */ 2, - /* maxVideoBitrate= */ 3, - /* minVideoWidth= */ 4, - /* minVideoHeight= */ 5, - /* minVideoFrameRate= */ 6, - /* minVideoBitrate= */ 7, - /* exceedVideoConstraintsIfNecessary= */ false, - /* allowVideoMixedMimeTypeAdaptiveness= */ true, - /* allowVideoNonSeamlessAdaptiveness= */ false, - /* viewportWidth= */ 8, - /* viewportHeight= */ 9, - /* viewportOrientationMayChange= */ true, - /* preferredVideoMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_AV1, MimeTypes.VIDEO_H264), + .setMaxVideoSize(/* maxVideoWidth= */ 0, /* maxVideoHeight= */ 1) + .setMaxVideoFrameRate(2) + .setMaxVideoBitrate(3) + .setMinVideoSize(/* minVideoWidth= */ 4, /* minVideoHeight= */ 5) + .setMinVideoFrameRate(6) + .setMinVideoBitrate(7) + .setExceedVideoConstraintsIfNecessary(false) + .setAllowVideoMixedMimeTypeAdaptiveness(true) + .setAllowVideoNonSeamlessAdaptiveness(false) + .setViewportSize( + /* viewportWidth= */ 8, + /* viewportHeight= */ 9, + /* viewportOrientationMayChange= */ true) + .setPreferredVideoMimeTypes(MimeTypes.VIDEO_AV1, MimeTypes.VIDEO_H264) // Audio - /* preferredAudioLanguages= */ ImmutableList.of("zh", "jp"), - /* preferredAudioRoleFlags= */ C.ROLE_FLAG_COMMENTARY, - /* maxAudioChannelCount= */ 10, - /* maxAudioBitrate= */ 11, - /* exceedAudioConstraintsIfNecessary= */ false, - /* allowAudioMixedMimeTypeAdaptiveness= */ true, - /* allowAudioMixedSampleRateAdaptiveness= */ false, - /* allowAudioMixedChannelCountAdaptiveness= */ true, - /* preferredAudioMimeTypes= */ ImmutableList.of(MimeTypes.AUDIO_AC3, MimeTypes.AUDIO_E_AC3), + .setPreferredAudioLanguages("zh", "jp") + .setPreferredAudioRoleFlags(C.ROLE_FLAG_COMMENTARY) + .setMaxAudioChannelCount(10) + .setMaxAudioBitrate(11) + .setExceedAudioConstraintsIfNecessary(false) + .setAllowAudioMixedMimeTypeAdaptiveness(true) + .setAllowAudioMixedSampleRateAdaptiveness(false) + .setAllowAudioMixedChannelCountAdaptiveness(true) + .setPreferredAudioMimeTypes(MimeTypes.AUDIO_AC3, MimeTypes.AUDIO_E_AC3) // Text - /* preferredTextLanguages= */ ImmutableList.of("de", "en"), - /* preferredTextRoleFlags= */ C.ROLE_FLAG_CAPTION, - /* selectUndeterminedTextLanguage= */ true, - /* disabledTextTrackSelectionFlags= */ C.SELECTION_FLAG_AUTOSELECT, + .setPreferredTextLanguages("de", "en") + .setPreferredTextRoleFlags(C.ROLE_FLAG_CAPTION) + .setSelectUndeterminedTextLanguage(true) + .setDisabledTextTrackSelectionFlags(C.SELECTION_FLAG_AUTOSELECT) // General - /* forceLowestBitrate= */ false, - /* forceHighestSupportedBitrate= */ true, - /* exceedRendererCapabilitiesIfNecessary= */ false, - /* tunnelingEnabled= */ true, - /* allowMultipleAdaptiveSelections= */ true, - // Overrides - selectionOverrides, - rendererDisabledFlags); + .setForceLowestBitrate(false) + .setForceHighestSupportedBitrate(true) + .setExceedRendererCapabilitiesIfNecessary(false) + .setTunnelingEnabled(true) + .setAllowMultipleAdaptiveSelections(true) + .setSelectionOverride( + /* rendererIndex= */ 2, + new TrackGroupArray(VIDEO_TRACK_GROUP), + new SelectionOverride(0, 1)) + .setRendererDisabled(3, true) + .build(); } /** diff --git a/library/core/src/test/java/com/google/android/exoplayer2/upstream/ByteArrayDataSourceTest.java b/library/core/src/test/java/com/google/android/exoplayer2/upstream/ByteArrayDataSourceTest.java index 21c942974af..d770f279026 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/upstream/ByteArrayDataSourceTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/upstream/ByteArrayDataSourceTest.java @@ -98,8 +98,14 @@ public void readFromInvalidOffsets() { * @param maxReadLength The maximum length of each read. * @param expectFailOnOpen Whether it is expected that opening the source will fail. */ - private void readTestData(byte[] testData, int dataOffset, int dataLength, int outputBufferLength, - int writeOffset, int maxReadLength, boolean expectFailOnOpen) { + private void readTestData( + byte[] testData, + int dataOffset, + int dataLength, + int outputBufferLength, + int writeOffset, + int maxReadLength, + boolean expectFailOnOpen) { int expectedFinalBytesRead = testData.length - dataOffset; if (dataLength != C.LENGTH_UNSET) { expectedFinalBytesRead = min(expectedFinalBytesRead, dataLength); @@ -137,8 +143,10 @@ private void readTestData(byte[] testData, int dataOffset, int dataLength, int o accumulatedBytesRead += bytesRead; assertThat(accumulatedBytesRead).isAtMost(expectedFinalBytesRead); // If we haven't read all of the bytes the request should have been satisfied in full. - assertThat(accumulatedBytesRead == expectedFinalBytesRead - || bytesRead == requestedReadLength).isTrue(); + assertThat( + accumulatedBytesRead == expectedFinalBytesRead + || bytesRead == requestedReadLength) + .isTrue(); } else { // We're done. Check we read the expected number of bytes. assertThat(accumulatedBytesRead).isEqualTo(expectedFinalBytesRead); @@ -154,5 +162,4 @@ private void readTestData(byte[] testData, int dataOffset, int dataLength, int o fail(); } } - } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/upstream/DataSchemeDataSourceTest.java b/library/core/src/test/java/com/google/android/exoplayer2/upstream/DataSchemeDataSourceTest.java index 119d473e7d8..297ae69e0b7 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/upstream/DataSchemeDataSourceTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/upstream/DataSchemeDataSourceTest.java @@ -22,6 +22,7 @@ import android.net.Uri; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.util.Util; import java.io.IOException; import org.junit.Before; @@ -103,16 +104,16 @@ public void invalidStartPositionRequest() throws IOException { buildDataSpec(DATA_SCHEME_URI, /* position= */ 108, /* length= */ C.LENGTH_UNSET)); fail(); } catch (DataSourceException e) { - assertThat(e.reason).isEqualTo(DataSourceException.POSITION_OUT_OF_RANGE); + assertThat(e.reason).isEqualTo(PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE); } } @Test - public void incorrectScheme() { + public void incorrectScheme() throws IOException { try { schemeDataDataSource.open(buildDataSpec("http://www.google.com")); fail(); - } catch (IOException e) { + } catch (IllegalArgumentException e) { // Expected. } } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/upstream/DataSourceInputStreamTest.java b/library/core/src/test/java/com/google/android/exoplayer2/upstream/DataSourceInputStreamTest.java index 5bc3e4d04a1..212b2944552 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/upstream/DataSourceInputStreamTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/upstream/DataSourceInputStreamTest.java @@ -59,8 +59,8 @@ public void read() throws IOException { byte[] readBytes = new byte[TEST_DATA.length]; int totalBytesRead = 0; while (totalBytesRead < TEST_DATA.length) { - int bytesRead = inputStream.read(readBytes, totalBytesRead, - TEST_DATA.length - totalBytesRead); + int bytesRead = + inputStream.read(readBytes, totalBytesRead, TEST_DATA.length - totalBytesRead); assertThat(bytesRead).isGreaterThan(0); totalBytesRead += bytesRead; assertThat(inputStream.bytesRead()).isEqualTo(totalBytesRead); @@ -96,12 +96,13 @@ public void skip() throws IOException { private static DataSourceInputStream buildTestInputStream() { FakeDataSource fakeDataSource = new FakeDataSource(); - fakeDataSource.getDataSet().newDefaultData() + fakeDataSource + .getDataSet() + .newDefaultData() .appendReadData(Arrays.copyOfRange(TEST_DATA, 0, 5)) .appendReadData(Arrays.copyOfRange(TEST_DATA, 5, 10)) .appendReadData(Arrays.copyOfRange(TEST_DATA, 10, 15)) .appendReadData(Arrays.copyOfRange(TEST_DATA, 15, TEST_DATA.length)); return new DataSourceInputStream(fakeDataSource, new DataSpec(Uri.EMPTY)); } - } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/upstream/DefaultBandwidthMeterTest.java b/library/core/src/test/java/com/google/android/exoplayer2/upstream/DefaultBandwidthMeterTest.java index e4c5c315f1b..532be675213 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/upstream/DefaultBandwidthMeterTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/upstream/DefaultBandwidthMeterTest.java @@ -183,6 +183,7 @@ public void defaultInitialBitrateEstimate_forEthernet_isGreaterThanEstimateFor3G assertThat(initialEstimateEthernet).isGreaterThan(initialEstimate3g); } + @Config(sdk = 28) // TODO(b/190021699): Fix 4G tests to work on newer API levels @Test public void defaultInitialBitrateEstimate_for4G_isGreaterThanEstimateFor2G() { setActiveNetworkInfo(networkInfo4g); @@ -198,6 +199,7 @@ public void defaultInitialBitrateEstimate_for4G_isGreaterThanEstimateFor2G() { assertThat(initialEstimate4g).isGreaterThan(initialEstimate2g); } + @Config(sdk = 28) // TODO(b/190021699): Fix 4G tests to work on newer API levels @Test public void defaultInitialBitrateEstimate_for4G_isGreaterThanEstimateFor3G() { setActiveNetworkInfo(networkInfo4g); @@ -228,7 +230,6 @@ public void defaultInitialBitrateEstimate_for3G_isGreaterThanEstimateFor2G() { assertThat(initialEstimate3g).isGreaterThan(initialEstimate2g); } - @Config(sdk = Config.NEWEST_SDK) // TODO: Remove once targetSDK >= 29 @Test public void defaultInitialBitrateEstimate_for5gSa_isGreaterThanEstimateFor4g() { setActiveNetworkInfo(networkInfo4g); @@ -323,6 +324,7 @@ public void defaultInitialBitrateEstimate_forOffline_isReasonable() { assertThat(initialEstimateFast).isGreaterThan(initialEstimateSlow); } + @Config(sdk = 28) // TODO(b/190021699): Fix 4G tests to work on newer API levels @Test public void defaultInitialBitrateEstimate_for4g_forFastCountry_isGreaterThanEstimateForSlowCountry() { @@ -340,7 +342,6 @@ public void defaultInitialBitrateEstimate_forOffline_isReasonable() { assertThat(initialEstimateFast).isGreaterThan(initialEstimateSlow); } - @Config(sdk = Config.NEWEST_SDK) // TODO: Remove once targetSDK >= 29 @Test public void defaultInitialBitrateEstimate_for5gSa_forFastCountry_isGreaterThanEstimateForSlowCountry() { @@ -483,6 +484,7 @@ public void initialBitrateEstimateOverwrite_for3G_whileConnectedTo3G_setsInitial assertThat(initialEstimate).isNotEqualTo(123456789); } + @Config(sdk = 28) // TODO(b/190021699): Fix 4G tests to work on newer API levels @Test public void initialBitrateEstimateOverwrite_for4G_whileConnectedTo4G_setsInitialEstimate() { setActiveNetworkInfo(networkInfo4g); @@ -495,6 +497,7 @@ public void initialBitrateEstimateOverwrite_for4G_whileConnectedTo4G_setsInitial assertThat(initialEstimate).isEqualTo(123456789); } + @Config(sdk = 28) // TODO(b/190021699): Fix 4G tests to work on newer API levels @Test public void initialBitrateEstimateOverwrite_for4G_whileConnectedToOtherNetwork_doesNotSetInitialEstimate() { @@ -508,7 +511,6 @@ public void initialBitrateEstimateOverwrite_for4G_whileConnectedTo4G_setsInitial assertThat(initialEstimate).isNotEqualTo(123456789); } - @Config(sdk = Config.NEWEST_SDK) // TODO: Remove once targetSDK >= 29 @Test public void initialBitrateEstimateOverwrite_for5gSa_whileConnectedTo5gSa_setsInitialEstimate() { setActiveNetworkInfo(networkInfo5gSa); @@ -521,7 +523,6 @@ public void initialBitrateEstimateOverwrite_for5gSa_whileConnectedTo5gSa_setsIni assertThat(initialEstimate).isEqualTo(123456789); } - @Config(sdk = Config.NEWEST_SDK) // TODO: Remove once targetSDK >= 29 @Test public void initialBitrateEstimateOverwrite_for5gSa_whileConnectedToOtherNetwork_doesNotSetInitialEstimate() { diff --git a/library/core/src/test/java/com/google/android/exoplayer2/upstream/DefaultLoadErrorHandlingPolicyTest.java b/library/core/src/test/java/com/google/android/exoplayer2/upstream/DefaultLoadErrorHandlingPolicyTest.java index 02a72106831..16468d41558 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/upstream/DefaultLoadErrorHandlingPolicyTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/upstream/DefaultLoadErrorHandlingPolicyTest.java @@ -15,9 +15,14 @@ */ package com.google.android.exoplayer2.upstream; +import static com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy.DEFAULT_LOCATION_EXCLUSION_MS; +import static com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_EXCLUSION_MS; +import static com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.FALLBACK_TYPE_LOCATION; +import static com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK; import static com.google.common.truth.Truth.assertThat; import android.net.Uri; +import androidx.annotation.Nullable; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ParserException; @@ -48,57 +53,207 @@ public final class DefaultLoadErrorHandlingPolicyTest { new MediaLoadData(/* dataType= */ C.DATA_TYPE_UNKNOWN); @Test - public void getExclusionDurationMsFor_responseCode403() { + public void getFallbackSelectionFor_responseCode403() { InvalidResponseCodeException exception = buildInvalidResponseCodeException(403, "Forbidden"); - assertThat(getDefaultPolicyExclusionDurationMsFor(exception)) - .isEqualTo(DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_BLACKLIST_MS); + + @Nullable + LoadErrorHandlingPolicy.FallbackSelection defaultPolicyFallbackSelection = + getDefaultPolicyFallbackSelection( + exception, + /* numberOfLocations= */ 1, + /* numberOfExcludedLocations= */ 0, + /* numberOfTracks= */ 10, + /* numberOfExcludedTracks= */ 0); + assertThat(defaultPolicyFallbackSelection.type).isEqualTo(FALLBACK_TYPE_TRACK); + assertThat(defaultPolicyFallbackSelection.exclusionDurationMs) + .isEqualTo(DEFAULT_TRACK_EXCLUSION_MS); + + defaultPolicyFallbackSelection = + getDefaultPolicyFallbackSelection( + exception, + /* numberOfLocations= */ 2, + /* numberOfExcludedLocations= */ 0, + /* numberOfTracks= */ 4, + /* numberOfExcludedTracks= */ 1); + assertThat(defaultPolicyFallbackSelection.type).isEqualTo(FALLBACK_TYPE_LOCATION); + assertThat(defaultPolicyFallbackSelection.exclusionDurationMs) + .isEqualTo(DEFAULT_LOCATION_EXCLUSION_MS); } @Test - public void getExclusionDurationMsFor_responseCode404() { + public void getFallbackSelectionFor_responseCode404() { InvalidResponseCodeException exception = buildInvalidResponseCodeException(404, "Not found"); - assertThat(getDefaultPolicyExclusionDurationMsFor(exception)) - .isEqualTo(DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_BLACKLIST_MS); + + @Nullable + LoadErrorHandlingPolicy.FallbackSelection defaultPolicyFallbackSelection = + getDefaultPolicyFallbackSelection( + exception, + /* numberOfLocations= */ 1, + /* numberOfExcludedLocations= */ 0, + /* numberOfTracks= */ 10, + /* numberOfExcludedTracks= */ 0); + + assertThat(defaultPolicyFallbackSelection.type).isEqualTo(FALLBACK_TYPE_TRACK); + assertThat(defaultPolicyFallbackSelection.exclusionDurationMs) + .isEqualTo(DEFAULT_TRACK_EXCLUSION_MS); + + defaultPolicyFallbackSelection = + getDefaultPolicyFallbackSelection( + exception, + /* numberOfLocations= */ 2, + /* numberOfExcludedLocations= */ 0, + /* numberOfTracks= */ 4, + /* numberOfExcludedTracks= */ 1); + assertThat(defaultPolicyFallbackSelection.type).isEqualTo(FALLBACK_TYPE_LOCATION); + assertThat(defaultPolicyFallbackSelection.exclusionDurationMs) + .isEqualTo(DEFAULT_LOCATION_EXCLUSION_MS); } @Test - public void getExclusionDurationMsFor_responseCode410() { + public void getFallbackSelectionFor_responseCode410() { InvalidResponseCodeException exception = buildInvalidResponseCodeException(410, "Gone"); - assertThat(getDefaultPolicyExclusionDurationMsFor(exception)) - .isEqualTo(DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_BLACKLIST_MS); + + @Nullable + LoadErrorHandlingPolicy.FallbackSelection defaultPolicyFallbackSelection = + getDefaultPolicyFallbackSelection( + exception, + /* numberOfLocations= */ 1, + /* numberOfExcludedLocations= */ 0, + /* numberOfTracks= */ 10, + /* numberOfExcludedTracks= */ 0); + + assertThat(defaultPolicyFallbackSelection.type).isEqualTo(FALLBACK_TYPE_TRACK); + assertThat(defaultPolicyFallbackSelection.exclusionDurationMs) + .isEqualTo(DEFAULT_TRACK_EXCLUSION_MS); + + defaultPolicyFallbackSelection = + getDefaultPolicyFallbackSelection( + exception, + /* numberOfLocations= */ 2, + /* numberOfExcludedLocations= */ 0, + /* numberOfTracks= */ 4, + /* numberOfExcludedTracks= */ 1); + assertThat(defaultPolicyFallbackSelection.type).isEqualTo(FALLBACK_TYPE_LOCATION); + assertThat(defaultPolicyFallbackSelection.exclusionDurationMs) + .isEqualTo(DEFAULT_LOCATION_EXCLUSION_MS); } @Test - public void getExclusionDurationMsFor_responseCode500() { + public void getFallbackSelectionFor_responseCode500() { InvalidResponseCodeException exception = buildInvalidResponseCodeException(500, "Internal server error"); - assertThat(getDefaultPolicyExclusionDurationMsFor(exception)) - .isEqualTo(DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_BLACKLIST_MS); + + @Nullable + LoadErrorHandlingPolicy.FallbackSelection defaultPolicyFallbackSelection = + getDefaultPolicyFallbackSelection( + exception, + /* numberOfLocations= */ 1, + /* numberOfExcludedLocations= */ 0, + /* numberOfTracks= */ 10, + /* numberOfExcludedTracks= */ 0); + + assertThat(defaultPolicyFallbackSelection.type).isEqualTo(FALLBACK_TYPE_TRACK); + assertThat(defaultPolicyFallbackSelection.exclusionDurationMs) + .isEqualTo(DEFAULT_TRACK_EXCLUSION_MS); + + defaultPolicyFallbackSelection = + getDefaultPolicyFallbackSelection( + exception, + /* numberOfLocations= */ 2, + /* numberOfExcludedLocations= */ 0, + /* numberOfTracks= */ 4, + /* numberOfExcludedTracks= */ 1); + assertThat(defaultPolicyFallbackSelection.type).isEqualTo(FALLBACK_TYPE_LOCATION); + assertThat(defaultPolicyFallbackSelection.exclusionDurationMs) + .isEqualTo(DEFAULT_LOCATION_EXCLUSION_MS); } @Test - public void getExclusionDurationMsFor_responseCode503() { + public void getFallbackSelectionFor_responseCode503() { InvalidResponseCodeException exception = buildInvalidResponseCodeException(503, "Service unavailable"); - assertThat(getDefaultPolicyExclusionDurationMsFor(exception)) - .isEqualTo(DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_BLACKLIST_MS); + + @Nullable + LoadErrorHandlingPolicy.FallbackSelection defaultPolicyFallbackSelection = + getDefaultPolicyFallbackSelection( + exception, + /* numberOfLocations= */ 1, + /* numberOfExcludedLocations= */ 0, + /* numberOfTracks= */ 10, + /* numberOfExcludedTracks= */ 0); + + assertThat(defaultPolicyFallbackSelection.type).isEqualTo(FALLBACK_TYPE_TRACK); + assertThat(defaultPolicyFallbackSelection.exclusionDurationMs) + .isEqualTo(DEFAULT_TRACK_EXCLUSION_MS); + + defaultPolicyFallbackSelection = + getDefaultPolicyFallbackSelection( + exception, + /* numberOfLocations= */ 2, + /* numberOfExcludedLocations= */ 0, + /* numberOfTracks= */ 4, + /* numberOfExcludedTracks= */ 1); + assertThat(defaultPolicyFallbackSelection.type).isEqualTo(FALLBACK_TYPE_LOCATION); + assertThat(defaultPolicyFallbackSelection.exclusionDurationMs) + .isEqualTo(DEFAULT_LOCATION_EXCLUSION_MS); } @Test - public void getExclusionDurationMsFor_dontExcludeUnexpectedHttpCodes() { + public void getFallbackSelectionFor_dontExcludeUnexpectedHttpCodes() { InvalidResponseCodeException exception = buildInvalidResponseCodeException(418, "I'm a teapot"); - assertThat(getDefaultPolicyExclusionDurationMsFor(exception)).isEqualTo(C.TIME_UNSET); + + @Nullable + LoadErrorHandlingPolicy.FallbackSelection defaultPolicyFallbackSelection = + getDefaultPolicyFallbackSelection( + exception, + /* numberOfLocations= */ 1, + /* numberOfExcludedLocations= */ 0, + /* numberOfTracks= */ 10, + /* numberOfExcludedTracks= */ 0); + + assertThat(defaultPolicyFallbackSelection).isNull(); + + defaultPolicyFallbackSelection = + getDefaultPolicyFallbackSelection( + exception, + /* numberOfLocations= */ 2, + /* numberOfExcludedLocations= */ 0, + /* numberOfTracks= */ 4, + /* numberOfExcludedTracks= */ 1); + assertThat(defaultPolicyFallbackSelection).isNull(); } @Test - public void getExclusionDurationMsFor_dontExcludeUnexpectedExceptions() { + public void getFallbackSelectionFor_dontExcludeUnexpectedExceptions() { IOException exception = new IOException(); - assertThat(getDefaultPolicyExclusionDurationMsFor(exception)).isEqualTo(C.TIME_UNSET); + + @Nullable + LoadErrorHandlingPolicy.FallbackSelection defaultPolicyFallbackSelection = + getDefaultPolicyFallbackSelection( + exception, + /* numberOfLocations= */ 1, + /* numberOfExcludedLocations= */ 0, + /* numberOfTracks= */ 10, + /* numberOfExcludedTracks= */ 0); + + assertThat(defaultPolicyFallbackSelection).isNull(); + + defaultPolicyFallbackSelection = + getDefaultPolicyFallbackSelection( + exception, + /* numberOfLocations= */ 2, + /* numberOfExcludedLocations= */ 0, + /* numberOfTracks= */ 4, + /* numberOfExcludedTracks= */ 1); + assertThat(defaultPolicyFallbackSelection).isNull(); } @Test public void getRetryDelayMsFor_dontRetryParserException() { - assertThat(getDefaultPolicyRetryDelayOutputFor(new ParserException(), 1)) + assertThat( + getDefaultPolicyRetryDelayOutputFor( + ParserException.createForMalformedContainer(/* message= */ null, /* cause= */ null), + 1)) .isEqualTo(C.TIME_UNSET); } @@ -109,14 +264,24 @@ public void getRetryDelayMsFor_successiveRetryDelays() { assertThat(getDefaultPolicyRetryDelayOutputFor(new IOException(), 9)).isEqualTo(5000); } - private static long getDefaultPolicyExclusionDurationMsFor(IOException exception) { + @Nullable + private static LoadErrorHandlingPolicy.FallbackSelection getDefaultPolicyFallbackSelection( + IOException exception, + int numberOfLocations, + int numberOfExcludedLocations, + int numberOfTracks, + int numberOfExcludedTracks) { LoadErrorInfo loadErrorInfo = new LoadErrorInfo( PLACEHOLDER_LOAD_EVENT_INFO, PLACEHOLDER_MEDIA_LOAD_DATA, exception, /* errorCount= */ 1); - return new DefaultLoadErrorHandlingPolicy().getBlacklistDurationMsFor(loadErrorInfo); + LoadErrorHandlingPolicy.FallbackOptions fallbackOptions = + new LoadErrorHandlingPolicy.FallbackOptions( + numberOfLocations, numberOfExcludedLocations, numberOfTracks, numberOfExcludedTracks); + return new DefaultLoadErrorHandlingPolicy() + .getFallbackSelectionFor(fallbackOptions, loadErrorInfo); } private static long getDefaultPolicyRetryDelayOutputFor(IOException exception, int errorCount) { @@ -131,6 +296,7 @@ private static InvalidResponseCodeException buildInvalidResponseCodeException( return new InvalidResponseCodeException( statusCode, message, + /* cause= */ null, Collections.emptyMap(), new DataSpec(Uri.EMPTY), /* responseBody= */ Util.EMPTY_BYTE_ARRAY); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/upstream/CacheDataSourceContractTest.java b/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceContractTest.java similarity index 92% rename from library/core/src/test/java/com/google/android/exoplayer2/upstream/CacheDataSourceContractTest.java rename to library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceContractTest.java index 360bc37c594..e16ef980563 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/upstream/CacheDataSourceContractTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceContractTest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.google.android.exoplayer2.upstream; +package com.google.android.exoplayer2.upstream.cache; import android.net.Uri; import androidx.annotation.Nullable; @@ -23,9 +23,7 @@ import com.google.android.exoplayer2.testutil.FakeDataSet; import com.google.android.exoplayer2.testutil.FakeDataSource; import com.google.android.exoplayer2.testutil.TestUtil; -import com.google.android.exoplayer2.upstream.cache.CacheDataSource; -import com.google.android.exoplayer2.upstream.cache.NoOpCacheEvictor; -import com.google.android.exoplayer2.upstream.cache.SimpleCache; +import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.util.Util; import com.google.common.collect.ImmutableList; import java.io.File; diff --git a/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceTest2.java b/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceTest2.java index e6b44e9aa86..af43da82806 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceTest2.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceTest2.java @@ -136,9 +136,7 @@ private void assertSingleOpen(FakeDataSource upstreamSource, int start, int end) assertThat(openedDataSpecs[0].length).isEqualTo(end - start); } - /** - * Asserts that the upstream source was not opened. - */ + /** Asserts that the upstream source was not opened. */ private void assertNoOpen(FakeDataSource upstreamSource) { DataSpec[] openedDataSpecs = upstreamSource.getAndClearOpenedDataSpecs(); assertThat(openedDataSpecs).hasLength(0); @@ -150,8 +148,8 @@ private static FakeDataSource buildFakeUpstreamSource() { return fakeDataSource; } - private static CacheDataSource buildCacheDataSource(Context context, DataSource upstreamSource, - boolean useAesEncryption) throws CacheException { + private static CacheDataSource buildCacheDataSource( + Context context, DataSource upstreamSource, boolean useAesEncryption) throws CacheException { File cacheDir = context.getExternalCacheDir(); Cache cache = new SimpleCache( @@ -163,16 +161,19 @@ private static CacheDataSource buildCacheDataSource(Context context, DataSource // Source and cipher final String secretKey = "testKey:12345678"; DataSource file = new FileDataSource(); - DataSource cacheReadDataSource = useAesEncryption - ? new AesCipherDataSource(Util.getUtf8Bytes(secretKey), file) : file; + DataSource cacheReadDataSource = + useAesEncryption ? new AesCipherDataSource(Util.getUtf8Bytes(secretKey), file) : file; // Sink and cipher CacheDataSink cacheSink = new CacheDataSink(cache, EXO_CACHE_MAX_FILESIZE); byte[] scratch = new byte[3897]; - DataSink cacheWriteDataSink = useAesEncryption - ? new AesCipherDataSink(Util.getUtf8Bytes(secretKey), cacheSink, scratch) : cacheSink; + DataSink cacheWriteDataSink = + useAesEncryption + ? new AesCipherDataSink(Util.getUtf8Bytes(secretKey), cacheSink, scratch) + : cacheSink; - return new CacheDataSource(cache, + return new CacheDataSource( + cache, upstreamSource, cacheReadDataSource, cacheWriteDataSink, @@ -189,5 +190,4 @@ private static void emptyCache(Cache cache) { // Check that the cache really is empty now. assertThat(cache.getKeys().isEmpty()).isTrue(); } - } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheWriterTest.java b/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheWriterTest.java index b094f332ded..1ff7ea81d7a 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheWriterTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheWriterTest.java @@ -113,9 +113,12 @@ public void cacheSetOffsetAndLength() throws Exception { @Test public void cacheUnknownLength() throws Exception { - FakeDataSet fakeDataSet = new FakeDataSet().newData("test_data") - .setSimulateUnknownLength(true) - .appendReadData(TestUtil.buildTestData(100)).endData(); + FakeDataSet fakeDataSet = + new FakeDataSet() + .newData("test_data") + .setSimulateUnknownLength(true) + .appendReadData(TestUtil.buildTestData(100)) + .endData(); FakeDataSource dataSource = new FakeDataSource(fakeDataSet); DataSpec dataSpec = new DataSpec(Uri.parse("test_data")); @@ -135,9 +138,12 @@ public void cacheUnknownLength() throws Exception { @Test public void cacheUnknownLengthPartialCaching() throws Exception { - FakeDataSet fakeDataSet = new FakeDataSet().newData("test_data") - .setSimulateUnknownLength(true) - .appendReadData(TestUtil.buildTestData(100)).endData(); + FakeDataSet fakeDataSet = + new FakeDataSet() + .newData("test_data") + .setSimulateUnknownLength(true) + .appendReadData(TestUtil.buildTestData(100)) + .endData(); FakeDataSource dataSource = new FakeDataSource(fakeDataSet); Uri testUri = Uri.parse("test_data"); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CachedContentIndexTest.java b/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CachedContentIndexTest.java index 1237d3a3127..33e6576b73f 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CachedContentIndexTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CachedContentIndexTest.java @@ -42,38 +42,171 @@ public class CachedContentIndexTest { private final byte[] testIndexV1File = { - 0, 0, 0, 1, // version - 0, 0, 0, 0, // flags - 0, 0, 0, 2, // number_of_CachedContent - 0, 0, 0, 5, // cache_id 5 - 0, 5, 65, 66, 67, 68, 69, // cache_key "ABCDE" - 0, 0, 0, 0, 0, 0, 0, 10, // original_content_length - 0, 0, 0, 2, // cache_id 2 - 0, 5, 75, 76, 77, 78, 79, // cache_key "KLMNO" - 0, 0, 0, 0, 0, 0, 10, 0, // original_content_length - (byte) 0xF6, (byte) 0xFB, 0x50, 0x41 // hashcode_of_CachedContent_array + 0, + 0, + 0, + 1, // version + 0, + 0, + 0, + 0, // flags + 0, + 0, + 0, + 2, // number_of_CachedContent + 0, + 0, + 0, + 5, // cache_id 5 + 0, + 5, + 65, + 66, + 67, + 68, + 69, // cache_key "ABCDE" + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 10, // original_content_length + 0, + 0, + 0, + 2, // cache_id 2 + 0, + 5, + 75, + 76, + 77, + 78, + 79, // cache_key "KLMNO" + 0, + 0, + 0, + 0, + 0, + 0, + 10, + 0, // original_content_length + (byte) 0xF6, + (byte) 0xFB, + 0x50, + 0x41 // hashcode_of_CachedContent_array }; private final byte[] testIndexV2File = { - 0, 0, 0, 2, // version - 0, 0, 0, 0, // flags - 0, 0, 0, 2, // number_of_CachedContent - 0, 0, 0, 5, // cache_id 5 - 0, 5, 65, 66, 67, 68, 69, // cache_key "ABCDE" - 0, 0, 0, 2, // metadata count - 0, 9, 101, 120, 111, 95, 114, 101, 100, 105, 114, // "exo_redir" - 0, 0, 0, 5, // value length - 97, 98, 99, 100, 101, // Redirected Uri "abcde" - 0, 7, 101, 120, 111, 95, 108, 101, 110, // "exo_len" - 0, 0, 0, 8, // value length - 0, 0, 0, 0, 0, 0, 0, 10, // original_content_length - 0, 0, 0, 2, // cache_id 2 - 0, 5, 75, 76, 77, 78, 79, // cache_key "KLMNO" - 0, 0, 0, 1, // metadata count - 0, 7, 101, 120, 111, 95, 108, 101, 110, // "exo_len" - 0, 0, 0, 8, // value length - 0, 0, 0, 0, 0, 0, 10, 0, // original_content_length - 0x12, 0x15, 0x66, (byte) 0x8A // hashcode_of_CachedContent_array + 0, + 0, + 0, + 2, // version + 0, + 0, + 0, + 0, // flags + 0, + 0, + 0, + 2, // number_of_CachedContent + 0, + 0, + 0, + 5, // cache_id 5 + 0, + 5, + 65, + 66, + 67, + 68, + 69, // cache_key "ABCDE" + 0, + 0, + 0, + 2, // metadata count + 0, + 9, + 101, + 120, + 111, + 95, + 114, + 101, + 100, + 105, + 114, // "exo_redir" + 0, + 0, + 0, + 5, // value length + 97, + 98, + 99, + 100, + 101, // Redirected Uri "abcde" + 0, + 7, + 101, + 120, + 111, + 95, + 108, + 101, + 110, // "exo_len" + 0, + 0, + 0, + 8, // value length + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 10, // original_content_length + 0, + 0, + 0, + 2, // cache_id 2 + 0, + 5, + 75, + 76, + 77, + 78, + 79, // cache_key "KLMNO" + 0, + 0, + 0, + 1, // metadata count + 0, + 7, + 101, + 120, + 111, + 95, + 108, + 101, + 110, // "exo_len" + 0, + 0, + 0, + 8, // value length + 0, + 0, + 0, + 0, + 0, + 0, + 10, + 0, // original_content_length + 0x12, + 0x15, + 0x66, + (byte) 0x8A // hashcode_of_CachedContent_array }; private File cacheDir; diff --git a/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/LeastRecentlyUsedCacheEvictorTest.java b/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/LeastRecentlyUsedCacheEvictorTest.java index 4984e71a3ed..ffe5dbdb879 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/LeastRecentlyUsedCacheEvictorTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/LeastRecentlyUsedCacheEvictorTest.java @@ -38,5 +38,4 @@ public void contentBiggerThanMaxSizeDoesNotThrowException() throws Exception { evictor.onCacheInitialized(); evictor.onStartFile(Mockito.mock(Cache.class), "key", 0, maxBytes + 1); } - } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheSpanTest.java b/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheSpanTest.java index fa56c31a895..b0641a705c8 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheSpanTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheSpanTest.java @@ -68,7 +68,9 @@ public void cacheFile() throws Exception { + "A standalone carriage-return character \r" + "A next-line character \u0085" + "A line-separator character \u2028" - + "A paragraph-separator character \u2029", 1, 2); + + "A paragraph-separator character \u2029", + 1, + 2); } @Test @@ -142,5 +144,4 @@ private void assertNullCacheSpan(File parent, String key, long offset, long last CacheSpan cacheSpan = SimpleCacheSpan.createCacheEntry(cacheFile, cacheFileLength, index); assertWithMessage(cacheFile.toString()).that(cacheSpan).isNull(); } - } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/upstream/crypto/AesFlushingCipherTest.java b/library/core/src/test/java/com/google/android/exoplayer2/upstream/crypto/AesFlushingCipherTest.java index 9af0710e9ba..2811b0eadab 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/upstream/crypto/AesFlushingCipherTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/upstream/crypto/AesFlushingCipherTest.java @@ -196,5 +196,4 @@ public void midJoin() { int differingByteCount = getDifferingByteCount(reference, data, originalOffset); assertThat(differingByteCount).isEqualTo(0); } - } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/util/AtomicFileTest.java b/library/core/src/test/java/com/google/android/exoplayer2/util/AtomicFileTest.java index cab14c2c313..dd5ccac8cdb 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/util/AtomicFileTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/util/AtomicFileTest.java @@ -90,5 +90,4 @@ private void assertRead() throws IOException { assertThat(input.read()).isEqualTo(-1); input.close(); } - } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/util/ColorParserTest.java b/library/core/src/test/java/com/google/android/exoplayer2/util/ColorParserTest.java index c2f165dec1b..da9ddbe4910 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/util/ColorParserTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/util/ColorParserTest.java @@ -84,16 +84,11 @@ public void rgbColorParsingRgbValuesOutOfBounds() { @Test public void rgbaColorParsing() { assertThat(parseTtmlColor("rgba(255,255,255,255)")).isEqualTo(WHITE); - assertThat(parseTtmlColor("rgba(255,255,255,255)")) - .isEqualTo(argb(255, 255, 255, 255)); + assertThat(parseTtmlColor("rgba(255,255,255,255)")).isEqualTo(argb(255, 255, 255, 255)); assertThat(parseTtmlColor("rgba(0, 0, 0, 255)")).isEqualTo(BLACK); - assertThat(parseTtmlColor("rgba(0, 0, 255, 0)")) - .isEqualTo(argb(0, 0, 0, 255)); + assertThat(parseTtmlColor("rgba(0, 0, 255, 0)")).isEqualTo(argb(0, 0, 0, 255)); assertThat(parseTtmlColor("rgba(255, 0, 0, 255)")).isEqualTo(RED); - assertThat(parseTtmlColor("rgba(255, 0, 255, 0)")) - .isEqualTo(argb(0, 255, 0, 255)); - assertThat(parseTtmlColor("rgba(255, 0, 0, 205)")) - .isEqualTo(argb(205, 255, 0, 0)); + assertThat(parseTtmlColor("rgba(255, 0, 255, 0)")).isEqualTo(argb(0, 255, 0, 255)); + assertThat(parseTtmlColor("rgba(255, 0, 0, 205)")).isEqualTo(argb(205, 255, 0, 0)); } - } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/util/ReusableBufferedOutputStreamTest.java b/library/core/src/test/java/com/google/android/exoplayer2/util/ReusableBufferedOutputStreamTest.java index 6ab273bf5ba..bc1cc8a5cba 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/util/ReusableBufferedOutputStreamTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/util/ReusableBufferedOutputStreamTest.java @@ -32,8 +32,8 @@ public final class ReusableBufferedOutputStreamTest { @Test public void reset() throws Exception { ByteArrayOutputStream byteArrayOutputStream1 = new ByteArrayOutputStream(1000); - ReusableBufferedOutputStream outputStream = new ReusableBufferedOutputStream( - byteArrayOutputStream1, 1000); + ReusableBufferedOutputStream outputStream = + new ReusableBufferedOutputStream(byteArrayOutputStream1, 1000); outputStream.write(TEST_DATA_1); outputStream.close(); @@ -45,5 +45,4 @@ public void reset() throws Exception { assertThat(byteArrayOutputStream1.toByteArray()).isEqualTo(TEST_DATA_1); assertThat(byteArrayOutputStream2.toByteArray()).isEqualTo(TEST_DATA_2); } - } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/util/UriUtilTest.java b/library/core/src/test/java/com/google/android/exoplayer2/util/UriUtilTest.java index 6d1c27c518c..02741eb16ff 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/util/UriUtilTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/util/UriUtilTest.java @@ -42,6 +42,7 @@ public void resolveNormal() { assertThat(resolve(base, "g/")).isEqualTo("http://a/b/c/g/"); assertThat(resolve(base, "/g")).isEqualTo("http://a/g"); assertThat(resolve(base, "//g")).isEqualTo("http://g"); + assertThat(resolve(base, "//g:80")).isEqualTo("http://g:80"); assertThat(resolve(base, "?y")).isEqualTo("http://a/b/c/d;p?y"); assertThat(resolve(base, "g?y")).isEqualTo("http://a/b/c/g?y"); assertThat(resolve(base, "#s")).isEqualTo("http://a/b/c/d;p?q#s"); @@ -134,4 +135,24 @@ public void removeNonExistentQueryParameter() { uri = Uri.parse("http://uri?query=value"); assertThat(removeQueryParameter(uri, "foo").toString()).isEqualTo("http://uri?query=value"); } + + @Test + public void isAbsolute_absoluteUri_returnsTrue() { + assertThat(UriUtil.isAbsolute("fo://bar")).isTrue(); + } + + @Test + public void isAbsolute_emptyString_returnsFalse() { + assertThat(UriUtil.isAbsolute("")).isFalse(); + assertThat(UriUtil.isAbsolute(" ")).isFalse(); + assertThat(UriUtil.isAbsolute(null)).isFalse(); + } + + @Test + public void isAbsolute_relativeUri_returnsFalse() { + assertThat(UriUtil.isAbsolute("//www.google.com")).isFalse(); + assertThat(UriUtil.isAbsolute("//www.google.com:80")).isFalse(); + assertThat(UriUtil.isAbsolute("/path/to/file")).isFalse(); + assertThat(UriUtil.isAbsolute("path/to/file")).isFalse(); + } } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/BaseUrlExclusionList.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/BaseUrlExclusionList.java new file mode 100644 index 00000000000..7971085933a --- /dev/null +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/BaseUrlExclusionList.java @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.exoplayer2.source.dash; + +import static com.google.android.exoplayer2.util.Util.castNonNull; +import static java.lang.Math.max; + +import android.os.SystemClock; +import android.util.Pair; +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; +import com.google.android.exoplayer2.source.dash.manifest.BaseUrl; +import com.google.common.collect.Iterables; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; + +/** + * Holds the state of {@link #exclude(BaseUrl, long) excluded} base URLs to be used {@link + * #selectBaseUrl(List) to select} a base URL based on these exclusions. + */ +public final class BaseUrlExclusionList { + + private final Map excludedServiceLocations; + private final Map excludedPriorities; + private final Map>, BaseUrl> selectionsTaken = new HashMap<>(); + private final Random random; + + /** Creates an instance. */ + public BaseUrlExclusionList() { + this(new Random()); + } + + /** Creates an instance with the given {@link Random}. */ + @VisibleForTesting + /* package */ BaseUrlExclusionList(Random random) { + this.random = random; + excludedServiceLocations = new HashMap<>(); + excludedPriorities = new HashMap<>(); + } + + /** + * Excludes the given base URL. + * + * @param baseUrlToExclude The base URL to exclude. + * @param exclusionDurationMs The duration of exclusion, in milliseconds. + */ + public void exclude(BaseUrl baseUrlToExclude, long exclusionDurationMs) { + long excludeUntilMs = SystemClock.elapsedRealtime() + exclusionDurationMs; + addExclusion(baseUrlToExclude.serviceLocation, excludeUntilMs, excludedServiceLocations); + addExclusion(baseUrlToExclude.priority, excludeUntilMs, excludedPriorities); + } + + /** + * Selects the base URL to use from the given list. + * + *

      The list is reduced by service location and priority of base URLs that have been passed to + * {@link #exclude(BaseUrl, long)}. The base URL to use is then selected from the remaining base + * URLs by priority and weight. + * + * @param baseUrls The list of {@link BaseUrl base URLs} to select from. + * @return The selected base URL after exclusion or null if all elements have been excluded. + */ + @Nullable + public BaseUrl selectBaseUrl(List baseUrls) { + List includedBaseUrls = applyExclusions(baseUrls); + if (includedBaseUrls.size() < 2) { + return Iterables.getFirst(includedBaseUrls, /* defaultValue= */ null); + } + // Sort by priority and service location to make the sort order of the candidates deterministic. + Collections.sort(includedBaseUrls, BaseUrlExclusionList::compareBaseUrl); + // Get candidates of the lowest priority from the head of the sorted list. + List> candidateKeys = new ArrayList<>(); + int lowestPriority = includedBaseUrls.get(0).priority; + for (int i = 0; i < includedBaseUrls.size(); i++) { + BaseUrl baseUrl = includedBaseUrls.get(i); + if (lowestPriority != baseUrl.priority) { + if (candidateKeys.size() == 1) { + // Only a single candidate of lowest priority; no choice. + return includedBaseUrls.get(0); + } + break; + } + candidateKeys.add(new Pair<>(baseUrl.serviceLocation, baseUrl.weight)); + } + // Check whether selection has already been taken. + @Nullable BaseUrl baseUrl = selectionsTaken.get(candidateKeys); + if (baseUrl == null) { + // Weighted random selection from multiple candidates of the same priority. + baseUrl = selectWeighted(includedBaseUrls.subList(0, candidateKeys.size())); + // Remember the selection taken for later. + selectionsTaken.put(candidateKeys, baseUrl); + } + return baseUrl; + } + + /** + * Returns the number of priority levels for the given list of base URLs after exclusion. + * + * @param baseUrls The list of base URLs. + * @return The number of priority levels after exclusion. + */ + public int getPriorityCountAfterExclusion(List baseUrls) { + Set priorities = new HashSet<>(); + List includedBaseUrls = applyExclusions(baseUrls); + for (int i = 0; i < includedBaseUrls.size(); i++) { + priorities.add(includedBaseUrls.get(i).priority); + } + return priorities.size(); + } + + /** + * Returns the number of priority levels of the given list of base URLs. + * + * @param baseUrls The list of base URLs. + * @return The number of priority levels before exclusion. + */ + public static int getPriorityCount(List baseUrls) { + Set priorities = new HashSet<>(); + for (int i = 0; i < baseUrls.size(); i++) { + priorities.add(baseUrls.get(i).priority); + } + return priorities.size(); + } + + /** Resets the state. */ + public void reset() { + excludedServiceLocations.clear(); + excludedPriorities.clear(); + selectionsTaken.clear(); + } + + // Internal methods. + + private List applyExclusions(List baseUrls) { + long nowMs = SystemClock.elapsedRealtime(); + removeExpiredExclusions(nowMs, excludedServiceLocations); + removeExpiredExclusions(nowMs, excludedPriorities); + List includedBaseUrls = new ArrayList<>(); + for (int i = 0; i < baseUrls.size(); i++) { + BaseUrl baseUrl = baseUrls.get(i); + if (!excludedServiceLocations.containsKey(baseUrl.serviceLocation) + && !excludedPriorities.containsKey(baseUrl.priority)) { + includedBaseUrls.add(baseUrl); + } + } + return includedBaseUrls; + } + + private BaseUrl selectWeighted(List candidates) { + int totalWeight = 0; + for (int i = 0; i < candidates.size(); i++) { + totalWeight += candidates.get(i).weight; + } + int randomChoice = random.nextInt(/* bound= */ totalWeight); + totalWeight = 0; + for (int i = 0; i < candidates.size(); i++) { + BaseUrl baseUrl = candidates.get(i); + totalWeight += baseUrl.weight; + if (randomChoice < totalWeight) { + return baseUrl; + } + } + return Iterables.getLast(candidates); + } + + private static void addExclusion( + T toExclude, long excludeUntilMs, Map currentExclusions) { + if (currentExclusions.containsKey(toExclude)) { + excludeUntilMs = max(excludeUntilMs, castNonNull(currentExclusions.get(toExclude))); + } + currentExclusions.put(toExclude, excludeUntilMs); + } + + private static void removeExpiredExclusions(long nowMs, Map exclusions) { + List expiredExclusions = new ArrayList<>(); + for (Map.Entry entries : exclusions.entrySet()) { + if (entries.getValue() <= nowMs) { + expiredExclusions.add(entries.getKey()); + } + } + for (int i = 0; i < expiredExclusions.size(); i++) { + exclusions.remove(expiredExclusions.get(i)); + } + } + + /** Compare by priority and service location. */ + private static int compareBaseUrl(BaseUrl a, BaseUrl b) { + int compare = Integer.compare(a.priority, b.priority); + return compare != 0 ? compare : a.serviceLocation.compareTo(b.serviceLocation); + } +} diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashChunkSource.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashChunkSource.java index d93915f761c..128334ced28 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashChunkSource.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashChunkSource.java @@ -35,6 +35,7 @@ interface Factory { /** * @param manifestLoaderErrorThrower Throws errors affecting loading of manifests. * @param manifest The initial manifest. + * @param baseUrlExclusionList The base URL exclusion list. * @param periodIndex The index of the corresponding period in the manifest. * @param adaptationSetIndices The indices of the corresponding adaptation sets in the period. * @param trackSelection The track selection. @@ -51,6 +52,7 @@ interface Factory { DashChunkSource createDashChunkSource( LoaderErrorThrower manifestLoaderErrorThrower, DashManifest manifest, + BaseUrlExclusionList baseUrlExclusionList, int periodIndex, int[] adaptationSetIndices, ExoTrackSelection trackSelection, diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java index 6cf10b35787..38205a46218 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java @@ -84,6 +84,7 @@ @Nullable private final TransferListener transferListener; private final DrmSessionManager drmSessionManager; private final LoadErrorHandlingPolicy loadErrorHandlingPolicy; + private final BaseUrlExclusionList baseUrlExclusionList; private final long elapsedRealtimeOffsetMs; private final LoaderErrorThrower manifestLoaderErrorThrower; private final Allocator allocator; @@ -107,6 +108,7 @@ public DashMediaPeriod( int id, DashManifest manifest, + BaseUrlExclusionList baseUrlExclusionList, int periodIndex, DashChunkSource.Factory chunkSourceFactory, @Nullable TransferListener transferListener, @@ -121,6 +123,7 @@ public DashMediaPeriod( PlayerEmsgCallback playerEmsgCallback) { this.id = id; this.manifest = manifest; + this.baseUrlExclusionList = baseUrlExclusionList; this.periodIndex = periodIndex; this.chunkSourceFactory = chunkSourceFactory; this.transferListener = transferListener; @@ -766,6 +769,7 @@ private ChunkSampleStream buildSampleStream( chunkSourceFactory.createDashChunkSource( manifestLoaderErrorThrower, manifest, + baseUrlExclusionList, periodIndex, trackGroupInfo.adaptationSetIndices, selection, diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java index 4136fab1bfa..b4ac7383726 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java @@ -17,7 +17,6 @@ import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static com.google.android.exoplayer2.util.Assertions.checkState; -import static com.google.android.exoplayer2.util.Util.castNonNull; import static java.lang.Math.max; import static java.lang.Math.min; @@ -449,6 +448,7 @@ public int[] getSupportedTypes() { private final CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory; private final DrmSessionManager drmSessionManager; private final LoadErrorHandlingPolicy loadErrorHandlingPolicy; + private final BaseUrlExclusionList baseUrlExclusionList; private final long fallbackTargetLiveOffsetMs; private final EventDispatcher manifestEventDispatcher; private final ParsingLoadable.Parser manifestParser; @@ -503,6 +503,7 @@ private DashMediaSource( this.loadErrorHandlingPolicy = loadErrorHandlingPolicy; this.fallbackTargetLiveOffsetMs = fallbackTargetLiveOffsetMs; this.compositeSequenceableLoaderFactory = compositeSequenceableLoaderFactory; + baseUrlExclusionList = new BaseUrlExclusionList(); sideloadedManifest = manifest != null; manifestEventDispatcher = createEventDispatcher(/* mediaPeriodId= */ null); manifestUriLock = new Object(); @@ -538,17 +539,6 @@ public void replaceManifestUri(Uri manifestUri) { // MediaSource implementation. - /** - * @deprecated Use {@link #getMediaItem()} and {@link MediaItem.PlaybackProperties#tag} instead. - */ - @SuppressWarnings("deprecation") - @Deprecated - @Override - @Nullable - public Object getTag() { - return castNonNull(mediaItem.playbackProperties).tag; - } - @Override public MediaItem getMediaItem() { return mediaItem; @@ -574,16 +564,16 @@ public void maybeThrowSourceInfoRefreshError() throws IOException { } @Override - public MediaPeriod createPeriod( - MediaPeriodId periodId, Allocator allocator, long startPositionUs) { - int periodIndex = (Integer) periodId.periodUid - firstPeriodId; + public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) { + int periodIndex = (Integer) id.periodUid - firstPeriodId; MediaSourceEventListener.EventDispatcher periodEventDispatcher = - createEventDispatcher(periodId, manifest.getPeriod(periodIndex).startMs); - DrmSessionEventListener.EventDispatcher drmEventDispatcher = createDrmEventDispatcher(periodId); + createEventDispatcher(id, manifest.getPeriod(periodIndex).startMs); + DrmSessionEventListener.EventDispatcher drmEventDispatcher = createDrmEventDispatcher(id); DashMediaPeriod mediaPeriod = new DashMediaPeriod( firstPeriodId + periodIndex, manifest, + baseUrlExclusionList, periodIndex, chunkSourceFactory, mediaTransferListener, @@ -629,6 +619,7 @@ protected void releaseSourceInternal() { expiredManifestPublishTimeUs = C.TIME_UNSET; firstPeriodId = 0; periodsById.clear(); + baseUrlExclusionList.reset(); drmSessionManager.release(); } @@ -648,8 +639,8 @@ protected void releaseSourceInternal() { // Loadable callbacks. - /* package */ void onManifestLoadCompleted(ParsingLoadable loadable, - long elapsedRealtimeMs, long loadDurationMs) { + /* package */ void onManifestLoadCompleted( + ParsingLoadable loadable, long elapsedRealtimeMs, long loadDurationMs) { LoadEventInfo loadEventInfo = new LoadEventInfo( loadable.loadTaskId, @@ -773,8 +764,8 @@ protected void releaseSourceInternal() { return loadErrorAction; } - /* package */ void onUtcTimestampLoadCompleted(ParsingLoadable loadable, - long elapsedRealtimeMs, long loadDurationMs) { + /* package */ void onUtcTimestampLoadCompleted( + ParsingLoadable loadable, long elapsedRealtimeMs, long loadDurationMs) { LoadEventInfo loadEventInfo = new LoadEventInfo( loadable.loadTaskId, @@ -811,8 +802,8 @@ protected void releaseSourceInternal() { return Loader.DONT_RETRY; } - /* package */ void onLoadCanceled(ParsingLoadable loadable, long elapsedRealtimeMs, - long loadDurationMs) { + /* package */ void onLoadCanceled( + ParsingLoadable loadable, long elapsedRealtimeMs, long loadDurationMs) { LoadEventInfo loadEventInfo = new LoadEventInfo( loadable.loadTaskId, @@ -857,10 +848,13 @@ private void resolveUtcTimingElementDirect(UtcTimingElement timingElement) { } } - private void resolveUtcTimingElementHttp(UtcTimingElement timingElement, - ParsingLoadable.Parser parser) { - startLoading(new ParsingLoadable<>(dataSource, Uri.parse(timingElement.value), - C.DATA_TYPE_TIME_SYNCHRONIZATION, parser), new UtcTimestampCallback(), 1); + private void resolveUtcTimingElementHttp( + UtcTimingElement timingElement, ParsingLoadable.Parser parser) { + startLoading( + new ParsingLoadable<>( + dataSource, Uri.parse(timingElement.value), C.DATA_TYPE_TIME_SYNCHRONIZATION, parser), + new UtcTimestampCallback(), + 1); } private void loadNtpTimeOffset() { @@ -1081,8 +1075,10 @@ private long getManifestLoadRetryDelayMillis() { return min((staleManifestReloadAttempt - 1) * 1000, 5000); } - private void startLoading(ParsingLoadable loadable, - Loader.Callback> callback, int minRetryCount) { + private void startLoading( + ParsingLoadable loadable, + Loader.Callback> callback, + int minRetryCount) { long elapsedRealtimeMs = loader.startLoading(loadable, callback, minRetryCount); manifestEventDispatcher.loadStarted( new LoadEventInfo(loadable.loadTaskId, loadable.dataSpec, elapsedRealtimeMs), @@ -1253,11 +1249,15 @@ public int getPeriodCount() { } @Override - public Period getPeriod(int periodIndex, Period period, boolean setIdentifiers) { + public Period getPeriod(int periodIndex, Period period, boolean setIds) { Assertions.checkIndex(periodIndex, 0, getPeriodCount()); - Object id = setIdentifiers ? manifest.getPeriod(periodIndex).id : null; - Object uid = setIdentifiers ? (firstPeriodId + periodIndex) : null; - return period.set(id, uid, 0, manifest.getPeriodDurationUs(periodIndex), + Object id = setIds ? manifest.getPeriod(periodIndex).id : null; + Object uid = setIds ? (firstPeriodId + periodIndex) : null; + return period.set( + id, + uid, + 0, + manifest.getPeriodDurationUs(periodIndex), C.msToUs(manifest.getPeriod(periodIndex).startMs - manifest.getPeriod(0).startMs) - offsetInFirstPeriodUs); } @@ -1270,8 +1270,8 @@ public int getWindowCount() { @Override public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) { Assertions.checkIndex(windowIndex, 0, 1); - long windowDefaultStartPositionUs = getAdjustedWindowDefaultStartPositionUs( - defaultPositionProjectionUs); + long windowDefaultStartPositionUs = + getAdjustedWindowDefaultStartPositionUs(defaultPositionProjectionUs); return window.set( Window.SINGLE_WINDOW_UID, mediaItem, @@ -1338,7 +1338,8 @@ private long getAdjustedWindowDefaultStartPositionUs(long defaultPositionProject return windowDefaultStartPositionUs; } long segmentNum = snapIndex.getSegmentNum(defaultStartPositionInPeriodUs, periodDurationUs); - return windowDefaultStartPositionUs + snapIndex.getTimeUs(segmentNum) + return windowDefaultStartPositionUs + + snapIndex.getTimeUs(segmentNum) - defaultStartPositionInPeriodUs; } @@ -1394,7 +1395,6 @@ public LoadErrorAction onLoadError( int errorCount) { return onManifestLoadError(loadable, elapsedRealtimeMs, loadDurationMs, error, errorCount); } - } private final class UtcTimestampCallback implements Loader.Callback> { @@ -1423,7 +1423,6 @@ public LoadErrorAction onLoadError( int errorCount) { return onUtcTimestampLoadError(loadable, elapsedRealtimeMs, loadDurationMs, error); } - } private static final class XsDateTimeParser implements ParsingLoadable.Parser { @@ -1433,7 +1432,6 @@ public Long parse(Uri uri, InputStream inputStream) throws IOException { String firstLine = new BufferedReader(new InputStreamReader(inputStream)).readLine(); return Util.parseXsDateTime(firstLine); } - } /* package */ static final class Iso8601Parser implements ParsingLoadable.Parser { @@ -1448,7 +1446,8 @@ public Long parse(Uri uri, InputStream inputStream) throws IOException { try { Matcher matcher = TIMESTAMP_WITH_TIMEZONE_PATTERN.matcher(firstLine); if (!matcher.matches()) { - throw new ParserException("Couldn't parse timestamp: " + firstLine); + throw ParserException.createForMalformedManifest( + "Couldn't parse timestamp: " + firstLine, /* cause= */ null); } // Parse the timestamp. String timestampWithoutTimezone = matcher.group(1); @@ -1469,10 +1468,9 @@ public Long parse(Uri uri, InputStream inputStream) throws IOException { } return timestampMs; } catch (ParseException e) { - throw new ParserException(e); + throw ParserException.createForMalformedManifest(/* message= */ null, /* cause= */ e); } } - } /** diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashUtil.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashUtil.java index 17ee580036e..9ca1c176fe8 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashUtil.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashUtil.java @@ -46,23 +46,41 @@ public final class DashUtil { /** * Builds a {@link DataSpec} for a given {@link RangedUri} belonging to {@link Representation}. * - * @param representation The {@link Representation} to which the request belongs. + * @param baseUrl The base url with which to resolve the request URI. * @param requestUri The {@link RangedUri} of the data to request. + * @param cacheKey An optional cache key. * @param flags Flags to be set on the returned {@link DataSpec}. See {@link * DataSpec.Builder#setFlags(int)}. * @return The {@link DataSpec}. */ public static DataSpec buildDataSpec( - Representation representation, RangedUri requestUri, int flags) { + String baseUrl, RangedUri requestUri, @Nullable String cacheKey, int flags) { return new DataSpec.Builder() - .setUri(requestUri.resolveUri(representation.baseUrl)) + .setUri(requestUri.resolveUri(baseUrl)) .setPosition(requestUri.start) .setLength(requestUri.length) - .setKey(representation.getCacheKey()) + .setKey(cacheKey) .setFlags(flags) .build(); } + /** + * Builds a {@link DataSpec} for a given {@link RangedUri} belonging to {@link Representation}. + * + *

      Uses the first base URL of the representation to build the data spec. + * + * @param representation The {@link Representation} to which the request belongs. + * @param requestUri The {@link RangedUri} of the data to request. + * @param flags Flags to be set on the returned {@link DataSpec}. See {@link + * DataSpec.Builder#setFlags(int)}. + * @return The {@link DataSpec}. + */ + public static DataSpec buildDataSpec( + Representation representation, RangedUri requestUri, int flags) { + return buildDataSpec( + representation.baseUrls.get(0).url, requestUri, representation.getCacheKey(), flags); + } + /** * Loads a DASH manifest. * @@ -96,6 +114,7 @@ public static Format loadFormatWithDrmInitData(DataSource dataSource, Period per } } Format manifestFormat = representation.format; + @Nullable Format sampleFormat = DashUtil.loadSampleFormat(dataSource, primaryTrackType, representation); return sampleFormat == null ? manifestFormat @@ -109,24 +128,46 @@ public static Format loadFormatWithDrmInitData(DataSource dataSource, Period per * @param trackType The type of the representation. Typically one of the {@link * com.google.android.exoplayer2.C} {@code TRACK_TYPE_*} constants. * @param representation The representation which initialization chunk belongs to. + * @param baseUrlIndex The index of the base URL to be picked from the {@link + * Representation#baseUrls list of base URLs}. * @return the sample {@link Format} of the given representation. * @throws IOException Thrown when there is an error while loading. */ @Nullable public static Format loadSampleFormat( - DataSource dataSource, int trackType, Representation representation) throws IOException { + DataSource dataSource, int trackType, Representation representation, int baseUrlIndex) + throws IOException { if (representation.getInitializationUri() == null) { return null; } ChunkExtractor chunkExtractor = newChunkExtractor(trackType, representation.format); try { - loadInitializationData(chunkExtractor, dataSource, representation, /* loadIndex= */ false); + loadInitializationData( + chunkExtractor, dataSource, representation, baseUrlIndex, /* loadIndex= */ false); } finally { chunkExtractor.release(); } return Assertions.checkStateNotNull(chunkExtractor.getSampleFormats())[0]; } + /** + * Loads initialization data for the {@code representation} and returns the sample {@link Format}. + * + *

      Uses the first base URL for loading the format. + * + * @param dataSource The source from which the data should be loaded. + * @param trackType The type of the representation. Typically one of the {@link + * com.google.android.exoplayer2.C} {@code TRACK_TYPE_*} constants. + * @param representation The representation which initialization chunk belongs to. + * @return the sample {@link Format} of the given representation. + * @throws IOException Thrown when there is an error while loading. + */ + @Nullable + public static Format loadSampleFormat( + DataSource dataSource, int trackType, Representation representation) throws IOException { + return loadSampleFormat(dataSource, trackType, representation, /* baseUrlIndex= */ 0); + } + /** * Loads initialization and index data for the {@code representation} and returns the {@link * ChunkIndex}. @@ -135,25 +176,48 @@ public static Format loadSampleFormat( * @param trackType The type of the representation. Typically one of the {@link * com.google.android.exoplayer2.C} {@code TRACK_TYPE_*} constants. * @param representation The representation which initialization chunk belongs to. + * @param baseUrlIndex The index of the base URL with which to resolve the request URI. * @return The {@link ChunkIndex} of the given representation, or null if no initialization or * index data exists. * @throws IOException Thrown when there is an error while loading. */ @Nullable public static ChunkIndex loadChunkIndex( - DataSource dataSource, int trackType, Representation representation) throws IOException { + DataSource dataSource, int trackType, Representation representation, int baseUrlIndex) + throws IOException { if (representation.getInitializationUri() == null) { return null; } ChunkExtractor chunkExtractor = newChunkExtractor(trackType, representation.format); try { - loadInitializationData(chunkExtractor, dataSource, representation, /* loadIndex= */ true); + loadInitializationData( + chunkExtractor, dataSource, representation, baseUrlIndex, /* loadIndex= */ true); } finally { chunkExtractor.release(); } return chunkExtractor.getChunkIndex(); } + /** + * Loads initialization and index data for the {@code representation} and returns the {@link + * ChunkIndex}. + * + *

      Uses the first base URL for loading the index. + * + * @param dataSource The source from which the data should be loaded. + * @param trackType The type of the representation. Typically one of the {@link + * com.google.android.exoplayer2.C} {@code TRACK_TYPE_*} constants. + * @param representation The representation which initialization chunk belongs to. + * @return The {@link ChunkIndex} of the given representation, or null if no initialization or + * index data exists. + * @throws IOException Thrown when there is an error while loading. + */ + @Nullable + public static ChunkIndex loadChunkIndex( + DataSource dataSource, int trackType, Representation representation) throws IOException { + return loadChunkIndex(dataSource, trackType, representation, /* baseUrlIndex= */ 0); + } + /** * Loads initialization data for the {@code representation} and optionally index data then returns * a {@link BundledChunkExtractor} which contains the output. @@ -161,6 +225,7 @@ public static ChunkIndex loadChunkIndex( * @param chunkExtractor The {@link ChunkExtractor} to use. * @param dataSource The source from which the data should be loaded. * @param representation The representation which initialization chunk belongs to. + * @param baseUrlIndex The index of the base URL with which to resolve the request URI. * @param loadIndex Whether to load index data too. * @throws IOException Thrown when there is an error while loading. */ @@ -168,35 +233,66 @@ private static void loadInitializationData( ChunkExtractor chunkExtractor, DataSource dataSource, Representation representation, + int baseUrlIndex, boolean loadIndex) throws IOException { RangedUri initializationUri = Assertions.checkNotNull(representation.getInitializationUri()); - RangedUri requestUri; + @Nullable RangedUri requestUri; if (loadIndex) { - RangedUri indexUri = representation.getIndexUri(); + @Nullable RangedUri indexUri = representation.getIndexUri(); if (indexUri == null) { return; } // It's common for initialization and index data to be stored adjacently. Attempt to merge // the two requests together to request both at once. - requestUri = initializationUri.attemptMerge(indexUri, representation.baseUrl); + requestUri = + initializationUri.attemptMerge(indexUri, representation.baseUrls.get(baseUrlIndex).url); if (requestUri == null) { - loadInitializationData(dataSource, representation, chunkExtractor, initializationUri); + loadInitializationData( + dataSource, representation, baseUrlIndex, chunkExtractor, initializationUri); requestUri = indexUri; } } else { requestUri = initializationUri; } - loadInitializationData(dataSource, representation, chunkExtractor, requestUri); + loadInitializationData(dataSource, representation, baseUrlIndex, chunkExtractor, requestUri); + } + + /** + * Loads initialization data for the {@code representation} and optionally index data then returns + * a {@link BundledChunkExtractor} which contains the output. + * + *

      Uses the first base URL for loading the initialization data. + * + * @param chunkExtractor The {@link ChunkExtractor} to use. + * @param dataSource The source from which the data should be loaded. + * @param representation The representation which initialization chunk belongs to. + * @param loadIndex Whether to load index data too. + * @throws IOException Thrown when there is an error while loading. + */ + public static void loadInitializationData( + ChunkExtractor chunkExtractor, + DataSource dataSource, + Representation representation, + boolean loadIndex) + throws IOException { + loadInitializationData( + chunkExtractor, dataSource, representation, /* baseUrlIndex= */ 0, loadIndex); } private static void loadInitializationData( DataSource dataSource, Representation representation, + int baseUrlIndex, ChunkExtractor chunkExtractor, RangedUri requestUri) throws IOException { - DataSpec dataSpec = DashUtil.buildDataSpec(representation, requestUri, /* flags= */ 0); + DataSpec dataSpec = + DashUtil.buildDataSpec( + representation.baseUrls.get(baseUrlIndex).url, + requestUri, + representation.getCacheKey(), + /* flags= */ 0); InitializationChunk initializationChunk = new InitializationChunk( dataSource, diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashWrappingSegmentIndex.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashWrappingSegmentIndex.java index 1d46d08422c..e894e07c3df 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashWrappingSegmentIndex.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashWrappingSegmentIndex.java @@ -87,5 +87,4 @@ public long getSegmentNum(long timeUs, long periodDurationUs) { public boolean isExplicit() { return true; } - } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java index 45806d390a8..e5fd60a2b0d 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java @@ -39,6 +39,7 @@ import com.google.android.exoplayer2.source.chunk.SingleSampleMediaChunk; import com.google.android.exoplayer2.source.dash.PlayerEmsgHandler.PlayerTrackEmsgHandler; import com.google.android.exoplayer2.source.dash.manifest.AdaptationSet; +import com.google.android.exoplayer2.source.dash.manifest.BaseUrl; import com.google.android.exoplayer2.source.dash.manifest.DashManifest; import com.google.android.exoplayer2.source.dash.manifest.RangedUri; import com.google.android.exoplayer2.source.dash.manifest.Representation; @@ -46,6 +47,7 @@ import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.HttpDataSource.InvalidResponseCodeException; +import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy; import com.google.android.exoplayer2.upstream.LoaderErrorThrower; import com.google.android.exoplayer2.upstream.TransferListener; import com.google.android.exoplayer2.util.Util; @@ -99,6 +101,7 @@ public Factory( public DashChunkSource createDashChunkSource( LoaderErrorThrower manifestLoaderErrorThrower, DashManifest manifest, + BaseUrlExclusionList baseUrlExclusionList, int periodIndex, int[] adaptationSetIndices, ExoTrackSelection trackSelection, @@ -116,6 +119,7 @@ public DashChunkSource createDashChunkSource( chunkExtractorFactory, manifestLoaderErrorThrower, manifest, + baseUrlExclusionList, periodIndex, adaptationSetIndices, trackSelection, @@ -127,10 +131,10 @@ public DashChunkSource createDashChunkSource( closedCaptionFormats, playerEmsgHandler); } - } private final LoaderErrorThrower manifestLoaderErrorThrower; + private final BaseUrlExclusionList baseUrlExclusionList; private final int[] adaptationSetIndices; private final int trackType; private final DataSource dataSource; @@ -151,6 +155,7 @@ public DashChunkSource createDashChunkSource( * chunks. * @param manifestLoaderErrorThrower Throws errors affecting loading of manifests. * @param manifest The initial manifest. + * @param baseUrlExclusionList The base URL exclusion list. * @param periodIndex The index of the period in the manifest. * @param adaptationSetIndices The indices of the adaptation sets in the period. * @param trackSelection The track selection. @@ -171,6 +176,7 @@ public DefaultDashChunkSource( ChunkExtractor.Factory chunkExtractorFactory, LoaderErrorThrower manifestLoaderErrorThrower, DashManifest manifest, + BaseUrlExclusionList baseUrlExclusionList, int periodIndex, int[] adaptationSetIndices, ExoTrackSelection trackSelection, @@ -183,6 +189,7 @@ public DefaultDashChunkSource( @Nullable PlayerTrackEmsgHandler playerTrackEmsgHandler) { this.manifestLoaderErrorThrower = manifestLoaderErrorThrower; this.manifest = manifest; + this.baseUrlExclusionList = baseUrlExclusionList; this.adaptationSetIndices = adaptationSetIndices; this.trackSelection = trackSelection; this.trackType = trackType; @@ -198,10 +205,13 @@ public DefaultDashChunkSource( representationHolders = new RepresentationHolder[trackSelection.length()]; for (int i = 0; i < representationHolders.length; i++) { Representation representation = representations.get(trackSelection.getIndexInTrackGroup(i)); + @Nullable + BaseUrl selectedBaseUrl = baseUrlExclusionList.selectBaseUrl(representation.baseUrls); representationHolders[i] = new RepresentationHolder( periodDurationUs, representation, + selectedBaseUrl != null ? selectedBaseUrl : representation.baseUrls.get(0), BundledChunkExtractor.FACTORY.createProgressiveMediaExtractor( trackType, representation.format, @@ -354,9 +364,15 @@ public void getNextChunk( } if (pendingInitializationUri != null || pendingIndexUri != null) { // We have initialization and/or index requests to make. - out.chunk = newInitializationChunk(representationHolder, dataSource, - trackSelection.getSelectedFormat(), trackSelection.getSelectionReason(), - trackSelection.getSelectionData(), pendingInitializationUri, pendingIndexUri); + out.chunk = + newInitializationChunk( + representationHolder, + dataSource, + trackSelection.getSelectedFormat(), + trackSelection.getSelectionReason(), + trackSelection.getSelectionData(), + pendingInitializationUri, + pendingIndexUri); return; } } @@ -450,7 +466,10 @@ public void onChunkLoadCompleted(Chunk chunk) { @Override public boolean onChunkLoadError( - Chunk chunk, boolean cancelable, Exception e, long exclusionDurationMs) { + Chunk chunk, + boolean cancelable, + LoadErrorHandlingPolicy.LoadErrorInfo loadErrorInfo, + LoadErrorHandlingPolicy loadErrorHandlingPolicy) { if (!cancelable) { return false; } @@ -458,9 +477,10 @@ public boolean onChunkLoadError( return true; } // Workaround for missing segment at the end of the period - if (!manifest.dynamic && chunk instanceof MediaChunk - && e instanceof InvalidResponseCodeException - && ((InvalidResponseCodeException) e).responseCode == 404) { + if (!manifest.dynamic + && chunk instanceof MediaChunk + && loadErrorInfo.exception instanceof InvalidResponseCodeException + && ((InvalidResponseCodeException) loadErrorInfo.exception).responseCode == 404) { RepresentationHolder representationHolder = representationHolders[trackSelection.indexOf(chunk.trackFormat)]; long segmentCount = representationHolder.getSegmentCount(); @@ -472,8 +492,45 @@ public boolean onChunkLoadError( } } } - return exclusionDurationMs != C.TIME_UNSET - && trackSelection.blacklist(trackSelection.indexOf(chunk.trackFormat), exclusionDurationMs); + + int trackIndex = trackSelection.indexOf(chunk.trackFormat); + RepresentationHolder representationHolder = representationHolders[trackIndex]; + LoadErrorHandlingPolicy.FallbackOptions fallbackOptions = + createFallbackOptions(trackSelection, representationHolder.representation.baseUrls); + if (!fallbackOptions.isFallbackAvailable(LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK) + && !fallbackOptions.isFallbackAvailable(LoadErrorHandlingPolicy.FALLBACK_TYPE_LOCATION)) { + // No more alternatives remaining. + return false; + } + @Nullable + LoadErrorHandlingPolicy.FallbackSelection fallbackSelection = + loadErrorHandlingPolicy.getFallbackSelectionFor(fallbackOptions, loadErrorInfo); + if (fallbackSelection == null) { + // Policy indicated to not use any fallback. + return false; + } + + boolean cancelLoad = false; + if (fallbackSelection.type == LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK) { + cancelLoad = + trackSelection.blacklist( + trackSelection.indexOf(chunk.trackFormat), fallbackSelection.exclusionDurationMs); + } else if (fallbackSelection.type == LoadErrorHandlingPolicy.FALLBACK_TYPE_LOCATION) { + baseUrlExclusionList.exclude( + representationHolder.selectedBaseUrl, fallbackSelection.exclusionDurationMs); + for (int i = 0; i < representationHolders.length; i++) { + @Nullable + BaseUrl baseUrl = + baseUrlExclusionList.selectBaseUrl(representationHolders[i].representation.baseUrls); + if (baseUrl != null) { + if (i == trackIndex) { + cancelLoad = true; + } + representationHolders[i] = representationHolders[i].copyWithNewSelectedBaseUrl(baseUrl); + } + } + } + return cancelLoad; } @Override @@ -488,6 +545,25 @@ public void release() { // Internal methods. + private LoadErrorHandlingPolicy.FallbackOptions createFallbackOptions( + ExoTrackSelection trackSelection, List baseUrls) { + long nowMs = SystemClock.elapsedRealtime(); + int numberOfTracks = trackSelection.length(); + int numberOfExcludedTracks = 0; + for (int i = 0; i < numberOfTracks; i++) { + if (trackSelection.isBlacklisted(i, nowMs)) { + numberOfExcludedTracks++; + } + } + int priorityCount = BaseUrlExclusionList.getPriorityCount(baseUrls); + return new LoadErrorHandlingPolicy.FallbackOptions( + /* numberOfLocations= */ priorityCount, + /* numberOfExcludedLocations= */ priorityCount + - baseUrlExclusionList.getPriorityCountAfterExclusion(baseUrls), + numberOfTracks, + numberOfExcludedTracks); + } + private long getSegmentNum( RepresentationHolder representationHolder, @Nullable MediaChunk previousChunk, @@ -535,21 +611,27 @@ protected Chunk newInitializationChunk( Format trackFormat, int trackSelectionReason, Object trackSelectionData, - RangedUri initializationUri, + @Nullable RangedUri initializationUri, RangedUri indexUri) { Representation representation = representationHolder.representation; - RangedUri requestUri; + @Nullable RangedUri requestUri; if (initializationUri != null) { // It's common for initialization and index data to be stored adjacently. Attempt to merge // the two requests together to request both at once. - requestUri = initializationUri.attemptMerge(indexUri, representation.baseUrl); + requestUri = + initializationUri.attemptMerge(indexUri, representationHolder.selectedBaseUrl.url); if (requestUri == null) { requestUri = initializationUri; } } else { requestUri = indexUri; } - DataSpec dataSpec = DashUtil.buildDataSpec(representation, requestUri, /* flags= */ 0); + DataSpec dataSpec = + DashUtil.buildDataSpec( + representationHolder.selectedBaseUrl.url, + requestUri, + representation.getCacheKey(), + /* flags= */ 0); return new InitializationChunk( dataSource, dataSpec, @@ -573,7 +655,6 @@ protected Chunk newMediaChunk( Representation representation = representationHolder.representation; long startTimeUs = representationHolder.getSegmentStartTimeUs(firstSegmentNum); RangedUri segmentUri = representationHolder.getSegmentUrl(firstSegmentNum); - String baseUrl = representation.baseUrl; if (representationHolder.chunkExtractor == null) { long endTimeUs = representationHolder.getSegmentEndTimeUs(firstSegmentNum); int flags = @@ -581,14 +662,30 @@ protected Chunk newMediaChunk( firstSegmentNum, nowPeriodTimeUs) ? 0 : DataSpec.FLAG_MIGHT_NOT_USE_FULL_NETWORK_SPEED; - DataSpec dataSpec = DashUtil.buildDataSpec(representation, segmentUri, flags); - return new SingleSampleMediaChunk(dataSource, dataSpec, trackFormat, trackSelectionReason, - trackSelectionData, startTimeUs, endTimeUs, firstSegmentNum, trackType, trackFormat); + DataSpec dataSpec = + DashUtil.buildDataSpec( + representationHolder.selectedBaseUrl.url, + segmentUri, + representation.getCacheKey(), + flags); + return new SingleSampleMediaChunk( + dataSource, + dataSpec, + trackFormat, + trackSelectionReason, + trackSelectionData, + startTimeUs, + endTimeUs, + firstSegmentNum, + trackType, + trackFormat); } else { int segmentCount = 1; for (int i = 1; i < maxSegmentCount; i++) { RangedUri nextSegmentUri = representationHolder.getSegmentUrl(firstSegmentNum + i); - @Nullable RangedUri mergedSegmentUri = segmentUri.attemptMerge(nextSegmentUri, baseUrl); + @Nullable + RangedUri mergedSegmentUri = + segmentUri.attemptMerge(nextSegmentUri, representationHolder.selectedBaseUrl.url); if (mergedSegmentUri == null) { // Unable to merge segment fetches because the URIs do not merge. break; @@ -607,7 +704,12 @@ protected Chunk newMediaChunk( representationHolder.isSegmentAvailableAtFullNetworkSpeed(segmentNum, nowPeriodTimeUs) ? 0 : DataSpec.FLAG_MIGHT_NOT_USE_FULL_NETWORK_SPEED; - DataSpec dataSpec = DashUtil.buildDataSpec(representation, segmentUri, flags); + DataSpec dataSpec = + DashUtil.buildDataSpec( + representationHolder.selectedBaseUrl.url, + segmentUri, + representation.getCacheKey(), + flags); long sampleOffsetUs = -representation.presentationTimeOffsetUs; return new ContainerMediaChunk( dataSource, @@ -662,7 +764,11 @@ public DataSpec getDataSpec() { representationHolder.isSegmentAvailableAtFullNetworkSpeed(currentIndex, nowPeriodTimeUs) ? 0 : DataSpec.FLAG_MIGHT_NOT_USE_FULL_NETWORK_SPEED; - return DashUtil.buildDataSpec(representationHolder.representation, segmentUri, flags); + return DashUtil.buildDataSpec( + representationHolder.selectedBaseUrl.url, + segmentUri, + representationHolder.representation.getCacheKey(), + flags); } @Override @@ -684,6 +790,7 @@ protected static final class RepresentationHolder { @Nullable /* package */ final ChunkExtractor chunkExtractor; public final Representation representation; + public final BaseUrl selectedBaseUrl; @Nullable public final DashSegmentIndex segmentIndex; private final long periodDurationUs; @@ -692,11 +799,13 @@ protected static final class RepresentationHolder { /* package */ RepresentationHolder( long periodDurationUs, Representation representation, + BaseUrl selectedBaseUrl, @Nullable ChunkExtractor chunkExtractor, long segmentNumShift, @Nullable DashSegmentIndex segmentIndex) { this.periodDurationUs = periodDurationUs; this.representation = representation; + this.selectedBaseUrl = selectedBaseUrl; this.segmentNumShift = segmentNumShift; this.chunkExtractor = chunkExtractor; this.segmentIndex = segmentIndex; @@ -706,26 +815,41 @@ protected static final class RepresentationHolder { /* package */ RepresentationHolder copyWithNewRepresentation( long newPeriodDurationUs, Representation newRepresentation) throws BehindLiveWindowException { - DashSegmentIndex oldIndex = representation.getIndex(); - DashSegmentIndex newIndex = newRepresentation.getIndex(); + @Nullable DashSegmentIndex oldIndex = representation.getIndex(); + @Nullable DashSegmentIndex newIndex = newRepresentation.getIndex(); if (oldIndex == null) { // Segment numbers cannot shift if the index isn't defined by the manifest. return new RepresentationHolder( - newPeriodDurationUs, newRepresentation, chunkExtractor, segmentNumShift, oldIndex); + newPeriodDurationUs, + newRepresentation, + selectedBaseUrl, + chunkExtractor, + segmentNumShift, + oldIndex); } if (!oldIndex.isExplicit()) { // Segment numbers cannot shift if the index isn't explicit. return new RepresentationHolder( - newPeriodDurationUs, newRepresentation, chunkExtractor, segmentNumShift, newIndex); + newPeriodDurationUs, + newRepresentation, + selectedBaseUrl, + chunkExtractor, + segmentNumShift, + newIndex); } long oldIndexSegmentCount = oldIndex.getSegmentCount(newPeriodDurationUs); if (oldIndexSegmentCount == 0) { // Segment numbers cannot shift if the old index was empty. return new RepresentationHolder( - newPeriodDurationUs, newRepresentation, chunkExtractor, segmentNumShift, newIndex); + newPeriodDurationUs, + newRepresentation, + selectedBaseUrl, + chunkExtractor, + segmentNumShift, + newIndex); } long oldIndexFirstSegmentNum = oldIndex.getFirstSegmentNum(); @@ -757,13 +881,34 @@ protected static final class RepresentationHolder { - newIndexFirstSegmentNum; } return new RepresentationHolder( - newPeriodDurationUs, newRepresentation, chunkExtractor, newSegmentNumShift, newIndex); + newPeriodDurationUs, + newRepresentation, + selectedBaseUrl, + chunkExtractor, + newSegmentNumShift, + newIndex); } @CheckResult /* package */ RepresentationHolder copyWithNewSegmentIndex(DashSegmentIndex segmentIndex) { return new RepresentationHolder( - periodDurationUs, representation, chunkExtractor, segmentNumShift, segmentIndex); + periodDurationUs, + representation, + selectedBaseUrl, + chunkExtractor, + segmentNumShift, + segmentIndex); + } + + @CheckResult + /* package */ RepresentationHolder copyWithNewSelectedBaseUrl(BaseUrl selectedBaseUrl) { + return new RepresentationHolder( + periodDurationUs, + representation, + selectedBaseUrl, + chunkExtractor, + segmentNumShift, + segmentIndex); } public long getFirstSegmentNum() { diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/EventSampleStream.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/EventSampleStream.java index 1abe48a0477..19816a44961 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/EventSampleStream.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/EventSampleStream.java @@ -29,8 +29,8 @@ import java.io.IOException; /** - * A {@link SampleStream} consisting of serialized {@link EventMessage}s read from an - * {@link EventStream}. + * A {@link SampleStream} consisting of serialized {@link EventMessage}s read from an {@link + * EventStream}. */ /* package */ final class EventSampleStream implements SampleStream { @@ -100,18 +100,19 @@ public void maybeThrowError() throws IOException { @Override public int readData( FormatHolder formatHolder, DecoderInputBuffer buffer, @ReadFlags int readFlags) { + boolean noMoreEventsInStream = currentIndex == eventTimesUs.length; + if (noMoreEventsInStream && !eventStreamAppendable) { + buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM); + return C.RESULT_BUFFER_READ; + } if ((readFlags & FLAG_REQUIRE_FORMAT) != 0 || !isFormatSentDownstream) { formatHolder.format = upstreamFormat; isFormatSentDownstream = true; return C.RESULT_FORMAT_READ; } - if (currentIndex == eventTimesUs.length) { - if (!eventStreamAppendable) { - buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM); - return C.RESULT_BUFFER_READ; - } else { - return C.RESULT_NOTHING_READ; - } + if (noMoreEventsInStream) { + // More events may be appended later. + return C.RESULT_NOTHING_READ; } int sampleIndex = currentIndex++; byte[] serializedEvent = eventMessageEncoder.encode(eventStream.events[sampleIndex]); @@ -129,5 +130,4 @@ public int skipData(long positionUs) { currentIndex = newIndex; return skipped; } - } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/PlayerEmsgHandler.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/PlayerEmsgHandler.java index b9c1ae995ce..f368bdc071f 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/PlayerEmsgHandler.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/PlayerEmsgHandler.java @@ -290,8 +290,8 @@ public void sampleData(ParsableByteArray data, int length, @SampleDataPart int s @Override public void sampleMetadata( - long timeUs, int flags, int size, int offset, @Nullable CryptoData encryptionData) { - sampleQueue.sampleMetadata(timeUs, flags, size, offset, encryptionData); + long timeUs, int flags, int size, int offset, @Nullable CryptoData cryptoData) { + sampleQueue.sampleMetadata(timeUs, flags, size, offset, cryptoData); parseAndDiscardSamples(); } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/AdaptationSet.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/AdaptationSet.java index 316b98ebcd1..48b228e9933 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/AdaptationSet.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/AdaptationSet.java @@ -21,9 +21,7 @@ /** Represents a set of interchangeable encoded versions of a media content component. */ public class AdaptationSet { - /** - * Value of {@link #id} indicating no value is set.= - */ + /** Value of {@link #id} indicating no value is set.= */ public static final int ID_UNSET = -1; /** @@ -33,19 +31,15 @@ public class AdaptationSet { public final int id; /** - * The type of the adaptation set. One of the {@link com.google.android.exoplayer2.C} - * {@code TRACK_TYPE_*} constants. + * The type of the adaptation set. One of the {@link com.google.android.exoplayer2.C} {@code + * TRACK_TYPE_*} constants. */ public final int type; - /** - * {@link Representation}s in the adaptation set. - */ + /** {@link Representation}s in the adaptation set. */ public final List representations; - /** - * Accessibility descriptors in the adaptation set. - */ + /** Accessibility descriptors in the adaptation set. */ public final List accessibilityDescriptors; /** Essential properties in the adaptation set. */ diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/BaseUrl.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/BaseUrl.java new file mode 100644 index 00000000000..1792afd905e --- /dev/null +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/BaseUrl.java @@ -0,0 +1,73 @@ +/* + * 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 com.google.android.exoplayer2.source.dash.manifest; + +import androidx.annotation.Nullable; +import com.google.common.base.Objects; + +/** A base URL, as defined by ISO 23009-1, 2nd edition, 5.6. and ETSI TS 103 285 V1.2.1, 10.8.2.1 */ +public final class BaseUrl { + + /** The default priority. */ + public static final int DEFAULT_PRIORITY = 1; + /** The default weight. */ + public static final int DEFAULT_WEIGHT = 1; + + /** The URL. */ + public final String url; + /** The service location. */ + public final String serviceLocation; + /** The priority. */ + public final int priority; + /** The weight. */ + public final int weight; + + /** + * Creates an instance with {@link #DEFAULT_PRIORITY default priority}, {@link #DEFAULT_WEIGHT + * default weight} and using the URL as the service location. + */ + public BaseUrl(String url) { + this(url, /* serviceLocation= */ url, DEFAULT_PRIORITY, DEFAULT_WEIGHT); + } + + /** Creates an instance. */ + public BaseUrl(String url, String serviceLocation, int priority, int weight) { + this.url = url; + this.serviceLocation = serviceLocation; + this.priority = priority; + this.weight = weight; + } + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) { + return true; + } + if (!(o instanceof BaseUrl)) { + return false; + } + BaseUrl baseUrl = (BaseUrl) o; + return priority == baseUrl.priority + && weight == baseUrl.weight + && Objects.equal(url, baseUrl.url) + && Objects.equal(serviceLocation, baseUrl.serviceLocation); + } + + @Override + public int hashCode() { + return Objects.hashCode(url, serviceLocation, priority, weight); + } +} diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifest.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifest.java index b1b61fde5f7..06699afa7ae 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifest.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifest.java @@ -42,14 +42,10 @@ public class DashManifest implements FilterableManifest { */ public final long durationMs; - /** - * The {@code minBufferTime} value in milliseconds, or {@link C#TIME_UNSET} if not present. - */ + /** The {@code minBufferTime} value in milliseconds, or {@link C#TIME_UNSET} if not present. */ public final long minBufferTimeMs; - /** - * Whether the manifest has value "dynamic" for the {@code type} attribute. - */ + /** Whether the manifest has value "dynamic" for the {@code type} attribute. */ public final boolean dynamic; /** @@ -59,8 +55,7 @@ public class DashManifest implements FilterableManifest { public final long minUpdatePeriodMs; /** - * The {@code timeShiftBufferDepth} value in milliseconds, or {@link C#TIME_UNSET} if not - * present. + * The {@code timeShiftBufferDepth} value in milliseconds, or {@link C#TIME_UNSET} if not present. */ public final long timeShiftBufferDepthMs; @@ -71,8 +66,8 @@ public class DashManifest implements FilterableManifest { public final long suggestedPresentationDelayMs; /** - * The {@code publishTime} value in milliseconds since epoch, or {@link C#TIME_UNSET} if - * not present. + * The {@code publishTime} value in milliseconds since epoch, or {@link C#TIME_UNSET} if not + * present. */ public final long publishTimeMs; @@ -159,8 +154,9 @@ public final DashManifest copy(List streamKeys) { Period period = getPeriod(periodIndex); ArrayList copyAdaptationSets = copyAdaptationSets(period.adaptationSets, keys); - Period copiedPeriod = new Period(period.id, period.startMs - shiftMs, copyAdaptationSets, - period.eventStreams); + Period copiedPeriod = + new Period( + period.id, period.startMs - shiftMs, copyAdaptationSets, period.eventStreams); copyPeriods.add(copiedPeriod); } } @@ -206,10 +202,9 @@ private static ArrayList copyAdaptationSets( adaptationSet.accessibilityDescriptors, adaptationSet.essentialProperties, adaptationSet.supplementalProperties)); - } while(key.periodIndex == periodIndex); + } while (key.periodIndex == periodIndex); // Add back the last key which doesn't belong to the period being processed keys.addFirst(key); return copyAdaptationSets; } - } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java index bf72353cfc3..f58e428a6f9 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java @@ -43,6 +43,7 @@ import com.google.common.base.Ascii; import com.google.common.base.Charsets; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -99,36 +100,39 @@ public DashManifest parse(Uri uri, InputStream inputStream) throws IOException { xpp.setInput(inputStream, null); int eventType = xpp.next(); if (eventType != XmlPullParser.START_TAG || !"MPD".equals(xpp.getName())) { - throw new ParserException( - "inputStream does not contain a valid media presentation description"); + throw ParserException.createForMalformedManifest( + "inputStream does not contain a valid media presentation description", + /* cause= */ null); } - return parseMediaPresentationDescription(xpp, uri.toString()); + return parseMediaPresentationDescription(xpp, new BaseUrl(uri.toString())); } catch (XmlPullParserException e) { - throw new ParserException(e); + throw ParserException.createForMalformedManifest(/* message= */ null, /* cause= */ e); } } - protected DashManifest parseMediaPresentationDescription(XmlPullParser xpp, - String baseUrl) throws XmlPullParserException, IOException { + protected DashManifest parseMediaPresentationDescription( + XmlPullParser xpp, BaseUrl documentBaseUrl) throws XmlPullParserException, IOException { long availabilityStartTime = parseDateTime(xpp, "availabilityStartTime", C.TIME_UNSET); long durationMs = parseDuration(xpp, "mediaPresentationDuration", C.TIME_UNSET); long minBufferTimeMs = parseDuration(xpp, "minBufferTime", C.TIME_UNSET); String typeString = xpp.getAttributeValue(null, "type"); boolean dynamic = "dynamic".equals(typeString); - long minUpdateTimeMs = dynamic ? parseDuration(xpp, "minimumUpdatePeriod", C.TIME_UNSET) - : C.TIME_UNSET; - long timeShiftBufferDepthMs = dynamic - ? parseDuration(xpp, "timeShiftBufferDepth", C.TIME_UNSET) : C.TIME_UNSET; - long suggestedPresentationDelayMs = dynamic - ? parseDuration(xpp, "suggestedPresentationDelay", C.TIME_UNSET) : C.TIME_UNSET; + long minUpdateTimeMs = + dynamic ? parseDuration(xpp, "minimumUpdatePeriod", C.TIME_UNSET) : C.TIME_UNSET; + long timeShiftBufferDepthMs = + dynamic ? parseDuration(xpp, "timeShiftBufferDepth", C.TIME_UNSET) : C.TIME_UNSET; + long suggestedPresentationDelayMs = + dynamic ? parseDuration(xpp, "suggestedPresentationDelay", C.TIME_UNSET) : C.TIME_UNSET; long publishTimeMs = parseDateTime(xpp, "publishTime", C.TIME_UNSET); ProgramInformation programInformation = null; UtcTimingElement utcTiming = null; Uri location = null; ServiceDescriptionElement serviceDescription = null; long baseUrlAvailabilityTimeOffsetUs = dynamic ? 0 : C.TIME_UNSET; + ArrayList parentBaseUrls = Lists.newArrayList(documentBaseUrl); List periods = new ArrayList<>(); + ArrayList baseUrls = new ArrayList<>(); long nextPeriodStartMs = dynamic ? C.TIME_UNSET : 0; boolean seenEarlyAccessPeriod = false; boolean seenFirstBaseUrl = false; @@ -138,9 +142,9 @@ protected DashManifest parseMediaPresentationDescription(XmlPullParser xpp, if (!seenFirstBaseUrl) { baseUrlAvailabilityTimeOffsetUs = parseAvailabilityTimeOffsetUs(xpp, baseUrlAvailabilityTimeOffsetUs); - baseUrl = parseBaseUrl(xpp, baseUrl); seenFirstBaseUrl = true; } + baseUrls.addAll(parseBaseUrl(xpp, parentBaseUrls)); } else if (XmlPullParserUtil.isStartTag(xpp, "ProgramInformation")) { programInformation = parseProgramInformation(xpp); } else if (XmlPullParserUtil.isStartTag(xpp, "UTCTiming")) { @@ -153,7 +157,7 @@ protected DashManifest parseMediaPresentationDescription(XmlPullParser xpp, Pair periodWithDurationMs = parsePeriod( xpp, - baseUrl, + !baseUrls.isEmpty() ? baseUrls : parentBaseUrls, nextPeriodStartMs, baseUrlAvailabilityTimeOffsetUs, availabilityStartTime, @@ -165,12 +169,13 @@ protected DashManifest parseMediaPresentationDescription(XmlPullParser xpp, // early access. seenEarlyAccessPeriod = true; } else { - throw new ParserException("Unable to determine start of period " + periods.size()); + throw ParserException.createForMalformedManifest( + "Unable to determine start of period " + periods.size(), /* cause= */ null); } } else { long periodDurationMs = periodWithDurationMs.second; - nextPeriodStartMs = periodDurationMs == C.TIME_UNSET ? C.TIME_UNSET - : (period.startMs + periodDurationMs); + nextPeriodStartMs = + periodDurationMs == C.TIME_UNSET ? C.TIME_UNSET : (period.startMs + periodDurationMs); periods.add(period); } } else { @@ -183,12 +188,13 @@ protected DashManifest parseMediaPresentationDescription(XmlPullParser xpp, // If we know the end time of the final period, we can use it as the duration. durationMs = nextPeriodStartMs; } else if (!dynamic) { - throw new ParserException("Unable to determine duration of static manifest."); + throw ParserException.createForMalformedManifest( + "Unable to determine duration of static manifest.", /* cause= */ null); } } if (periods.isEmpty()) { - throw new ParserException("No periods found."); + throw ParserException.createForMalformedManifest("No periods found.", /* cause= */ null); } return buildMediaPresentationDescription( @@ -271,7 +277,7 @@ protected ServiceDescriptionElement parseServiceDescription(XmlPullParser xpp) protected Pair parsePeriod( XmlPullParser xpp, - String baseUrl, + List parentBaseUrls, long defaultStartMs, long baseUrlAvailabilityTimeOffsetUs, long availabilityStartTimeMs, @@ -286,6 +292,7 @@ protected Pair parsePeriod( @Nullable Descriptor assetIdentifier = null; List adaptationSets = new ArrayList<>(); List eventStreams = new ArrayList<>(); + ArrayList baseUrls = new ArrayList<>(); boolean seenFirstBaseUrl = false; long segmentBaseAvailabilityTimeOffsetUs = C.TIME_UNSET; do { @@ -294,14 +301,14 @@ protected Pair parsePeriod( if (!seenFirstBaseUrl) { baseUrlAvailabilityTimeOffsetUs = parseAvailabilityTimeOffsetUs(xpp, baseUrlAvailabilityTimeOffsetUs); - baseUrl = parseBaseUrl(xpp, baseUrl); seenFirstBaseUrl = true; } + baseUrls.addAll(parseBaseUrl(xpp, parentBaseUrls)); } else if (XmlPullParserUtil.isStartTag(xpp, "AdaptationSet")) { adaptationSets.add( parseAdaptationSet( xpp, - baseUrl, + !baseUrls.isEmpty() ? baseUrls : parentBaseUrls, segmentBase, durationMs, baseUrlAvailabilityTimeOffsetUs, @@ -361,7 +368,7 @@ protected Period buildPeriod( protected AdaptationSet parseAdaptationSet( XmlPullParser xpp, - String baseUrl, + List parentBaseUrls, @Nullable SegmentBase segmentBase, long periodDurationMs, long baseUrlAvailabilityTimeOffsetUs, @@ -389,6 +396,7 @@ protected AdaptationSet parseAdaptationSet( ArrayList essentialProperties = new ArrayList<>(); ArrayList supplementalProperties = new ArrayList<>(); List representationInfos = new ArrayList<>(); + ArrayList baseUrls = new ArrayList<>(); boolean seenFirstBaseUrl = false; do { @@ -397,9 +405,9 @@ protected AdaptationSet parseAdaptationSet( if (!seenFirstBaseUrl) { baseUrlAvailabilityTimeOffsetUs = parseAvailabilityTimeOffsetUs(xpp, baseUrlAvailabilityTimeOffsetUs); - baseUrl = parseBaseUrl(xpp, baseUrl); seenFirstBaseUrl = true; } + baseUrls.addAll(parseBaseUrl(xpp, parentBaseUrls)); } else if (XmlPullParserUtil.isStartTag(xpp, "ContentProtection")) { Pair contentProtection = parseContentProtection(xpp); if (contentProtection.first != null) { @@ -425,7 +433,7 @@ protected AdaptationSet parseAdaptationSet( RepresentationInfo representationInfo = parseRepresentation( xpp, - baseUrl, + !baseUrls.isEmpty() ? baseUrls : parentBaseUrls, mimeType, codecs, width, @@ -523,10 +531,14 @@ protected AdaptationSet buildAdaptationSet( protected int parseContentType(XmlPullParser xpp) { String contentType = xpp.getAttributeValue(null, "contentType"); - return TextUtils.isEmpty(contentType) ? C.TRACK_TYPE_UNKNOWN - : MimeTypes.BASE_TYPE_AUDIO.equals(contentType) ? C.TRACK_TYPE_AUDIO - : MimeTypes.BASE_TYPE_VIDEO.equals(contentType) ? C.TRACK_TYPE_VIDEO - : MimeTypes.BASE_TYPE_TEXT.equals(contentType) ? C.TRACK_TYPE_TEXT + return TextUtils.isEmpty(contentType) + ? C.TRACK_TYPE_UNKNOWN + : MimeTypes.BASE_TYPE_AUDIO.equals(contentType) + ? C.TRACK_TYPE_AUDIO + : MimeTypes.BASE_TYPE_VIDEO.equals(contentType) + ? C.TRACK_TYPE_VIDEO + : MimeTypes.BASE_TYPE_TEXT.equals(contentType) + ? C.TRACK_TYPE_TEXT : C.TRACK_TYPE_UNKNOWN; } @@ -621,7 +633,7 @@ protected void parseAdaptationSetChild(XmlPullParser xpp) protected RepresentationInfo parseRepresentation( XmlPullParser xpp, - String baseUrl, + List parentBaseUrls, @Nullable String adaptationSetMimeType, @Nullable String adaptationSetCodecs, int adaptationSetWidth, @@ -657,6 +669,7 @@ protected RepresentationInfo parseRepresentation( ArrayList essentialProperties = new ArrayList<>(adaptationSetEssentialProperties); ArrayList supplementalProperties = new ArrayList<>(adaptationSetSupplementalProperties); + ArrayList baseUrls = new ArrayList<>(); boolean seenFirstBaseUrl = false; do { @@ -665,9 +678,9 @@ protected RepresentationInfo parseRepresentation( if (!seenFirstBaseUrl) { baseUrlAvailabilityTimeOffsetUs = parseAvailabilityTimeOffsetUs(xpp, baseUrlAvailabilityTimeOffsetUs); - baseUrl = parseBaseUrl(xpp, baseUrl); seenFirstBaseUrl = true; } + baseUrls.addAll(parseBaseUrl(xpp, parentBaseUrls)); } else if (XmlPullParserUtil.isStartTag(xpp, "AudioChannelConfiguration")) { audioChannels = parseAudioChannelConfiguration(xpp); } else if (XmlPullParserUtil.isStartTag(xpp, "SegmentBase")) { @@ -734,8 +747,14 @@ protected RepresentationInfo parseRepresentation( supplementalProperties); segmentBase = segmentBase != null ? segmentBase : new SingleSegmentBase(); - return new RepresentationInfo(format, baseUrl, segmentBase, drmSchemeType, drmSchemeDatas, - inbandEventStreams, Representation.REVISION_ID_DEFAULT); + return new RepresentationInfo( + format, + !baseUrls.isEmpty() ? baseUrls : parentBaseUrls, + segmentBase, + drmSchemeType, + drmSchemeDatas, + inbandEventStreams, + Representation.REVISION_ID_DEFAULT); } protected Format buildFormat( @@ -757,7 +776,7 @@ protected Format buildFormat( if (MimeTypes.AUDIO_E_AC3.equals(sampleMimeType)) { sampleMimeType = parseEac3SupplementalProperties(supplementalProperties); if (MimeTypes.AUDIO_E_AC3_JOC.equals(sampleMimeType)) { - codecs = Ac3Util.E_AC_3_CODEC_STRING; + codecs = Ac3Util.E_AC3_JOC_CODEC_STRING; } } @C.SelectionFlags int selectionFlags = parseSelectionFlagsFromRoleDescriptors(roleDescriptors); @@ -819,7 +838,7 @@ protected Representation buildRepresentation( return Representation.newInstance( representationInfo.revisionId, formatBuilder.build(), - representationInfo.baseUrl, + representationInfo.baseUrls, representationInfo.segmentBase, inbandEventStreams); } @@ -831,8 +850,9 @@ protected SingleSegmentBase parseSegmentBase( throws XmlPullParserException, IOException { long timescale = parseLong(xpp, "timescale", parent != null ? parent.timescale : 1); - long presentationTimeOffset = parseLong(xpp, "presentationTimeOffset", - parent != null ? parent.presentationTimeOffset : 0); + long presentationTimeOffset = + parseLong( + xpp, "presentationTimeOffset", parent != null ? parent.presentationTimeOffset : 0); long indexStart = parent != null ? parent.indexStart : 0; long indexLength = parent != null ? parent.indexLength : 0; @@ -853,14 +873,18 @@ protected SingleSegmentBase parseSegmentBase( } } while (!XmlPullParserUtil.isEndTag(xpp, "SegmentBase")); - return buildSingleSegmentBase(initialization, timescale, presentationTimeOffset, indexStart, - indexLength); + return buildSingleSegmentBase( + initialization, timescale, presentationTimeOffset, indexStart, indexLength); } - protected SingleSegmentBase buildSingleSegmentBase(RangedUri initialization, long timescale, - long presentationTimeOffset, long indexStart, long indexLength) { - return new SingleSegmentBase(initialization, timescale, presentationTimeOffset, indexStart, - indexLength); + protected SingleSegmentBase buildSingleSegmentBase( + RangedUri initialization, + long timescale, + long presentationTimeOffset, + long indexStart, + long indexLength) { + return new SingleSegmentBase( + initialization, timescale, presentationTimeOffset, indexStart, indexLength); } protected SegmentList parseSegmentList( @@ -874,8 +898,9 @@ protected SegmentList parseSegmentList( throws XmlPullParserException, IOException { long timescale = parseLong(xpp, "timescale", parent != null ? parent.timescale : 1); - long presentationTimeOffset = parseLong(xpp, "presentationTimeOffset", - parent != null ? parent.presentationTimeOffset : 0); + long presentationTimeOffset = + parseLong( + xpp, "presentationTimeOffset", parent != null ? parent.presentationTimeOffset : 0); long duration = parseLong(xpp, "duration", parent != null ? parent.duration : C.TIME_UNSET); long startNumber = parseLong(xpp, "startNumber", parent != null ? parent.startNumber : 1); long availabilityTimeOffsetUs = @@ -956,8 +981,9 @@ protected SegmentTemplate parseSegmentTemplate( long timeShiftBufferDepthMs) throws XmlPullParserException, IOException { long timescale = parseLong(xpp, "timescale", parent != null ? parent.timescale : 1); - long presentationTimeOffset = parseLong(xpp, "presentationTimeOffset", - parent != null ? parent.presentationTimeOffset : 0); + long presentationTimeOffset = + parseLong( + xpp, "presentationTimeOffset", parent != null ? parent.presentationTimeOffset : 0); long duration = parseLong(xpp, "duration", parent != null ? parent.duration : C.TIME_UNSET); long startNumber = parseLong(xpp, "startNumber", parent != null ? parent.startNumber : 1); long endNumber = @@ -966,10 +992,11 @@ protected SegmentTemplate parseSegmentTemplate( getFinalAvailabilityTimeOffset( baseUrlAvailabilityTimeOffsetUs, segmentBaseAvailabilityTimeOffsetUs); - UrlTemplate mediaTemplate = parseUrlTemplate(xpp, "media", - parent != null ? parent.mediaTemplate : null); - UrlTemplate initializationTemplate = parseUrlTemplate(xpp, "initialization", - parent != null ? parent.initializationTemplate : null); + UrlTemplate mediaTemplate = + parseUrlTemplate(xpp, "media", parent != null ? parent.mediaTemplate : null); + UrlTemplate initializationTemplate = + parseUrlTemplate( + xpp, "initialization", parent != null ? parent.initializationTemplate : null); RangedUri initialization = null; List timeline = null; @@ -1069,8 +1096,12 @@ protected EventStream parseEventStream(XmlPullParser xpp) return buildEventStream(schemeIdUri, value, timescale, presentationTimesUs, events); } - protected EventStream buildEventStream(String schemeIdUri, String value, long timescale, - long[] presentationTimesUs, EventMessage[] events) { + protected EventStream buildEventStream( + String schemeIdUri, + String value, + long timescale, + long[] presentationTimesUs, + EventMessage[] events) { return new EventStream(schemeIdUri, value, timescale, presentationTimesUs, events); } @@ -1099,8 +1130,8 @@ protected Pair parseEvent( long duration = parseLong(xpp, "duration", C.TIME_UNSET); long presentationTime = parseLong(xpp, "presentationTime", 0); long durationMs = Util.scaleLargeTimestamp(duration, C.MILLIS_PER_SECOND, timescale); - long presentationTimesUs = Util.scaleLargeTimestamp(presentationTime, C.MICROS_PER_SECOND, - timescale); + long presentationTimesUs = + Util.scaleLargeTimestamp(presentationTime, C.MICROS_PER_SECOND, timescale); String messageData = parseString(xpp, "messageData", null); byte[] eventObject = parseEventObject(xpp, scratchOutputStream); return Pair.create( @@ -1141,8 +1172,8 @@ protected byte[] parseEventObject(XmlPullParser xpp, ByteArrayOutputStream scrat case (XmlPullParser.START_TAG): xmlSerializer.startTag(xpp.getNamespace(), xpp.getName()); for (int i = 0; i < xpp.getAttributeCount(); i++) { - xmlSerializer.attribute(xpp.getAttributeNamespace(i), xpp.getAttributeName(i), - xpp.getAttributeValue(i)); + xmlSerializer.attribute( + xpp.getAttributeNamespace(i), xpp.getAttributeName(i), xpp.getAttributeValue(i)); } break; case (XmlPullParser.END_TAG): @@ -1275,8 +1306,8 @@ protected RangedUri parseSegmentUrl(XmlPullParser xpp) { return parseRangedUrl(xpp, "media", "mediaRange"); } - protected RangedUri parseRangedUrl(XmlPullParser xpp, String urlAttribute, - String rangeAttribute) { + protected RangedUri parseRangedUrl( + XmlPullParser xpp, String urlAttribute, String rangeAttribute) { String urlText = xpp.getAttributeValue(null, urlAttribute); long rangeStart = 0; long rangeLength = C.LENGTH_UNSET; @@ -1333,14 +1364,38 @@ protected String parseLabel(XmlPullParser xpp) throws XmlPullParserException, IO * Parses a BaseURL element. * * @param xpp The parser from which to read. - * @param parentBaseUrl A base URL for resolving the parsed URL. + * @param parentBaseUrls The parent base URLs for resolving the parsed URLs. * @throws XmlPullParserException If an error occurs parsing the element. * @throws IOException If an error occurs reading the element. - * @return The parsed and resolved URL. + * @return The list of parsed and resolved URLs. */ - protected String parseBaseUrl(XmlPullParser xpp, String parentBaseUrl) + protected List parseBaseUrl(XmlPullParser xpp, List parentBaseUrls) throws XmlPullParserException, IOException { - return UriUtil.resolve(parentBaseUrl, parseText(xpp, "BaseURL")); + @Nullable String priorityValue = xpp.getAttributeValue(null, "dvb:priority"); + int priority = + priorityValue != null ? Integer.parseInt(priorityValue) : BaseUrl.DEFAULT_PRIORITY; + @Nullable String weightValue = xpp.getAttributeValue(null, "dvb:weight"); + int weight = weightValue != null ? Integer.parseInt(weightValue) : BaseUrl.DEFAULT_WEIGHT; + @Nullable String serviceLocation = xpp.getAttributeValue(null, "serviceLocation"); + String baseUrl = parseText(xpp, "BaseURL"); + if (serviceLocation == null) { + serviceLocation = baseUrl; + } + if (UriUtil.isAbsolute(baseUrl)) { + return Lists.newArrayList(new BaseUrl(baseUrl, serviceLocation, priority, weight)); + } + + List baseUrls = new ArrayList<>(); + for (int i = 0; i < parentBaseUrls.size(); i++) { + BaseUrl parentBaseUrl = parentBaseUrls.get(i); + priority = parentBaseUrl.priority; + weight = parentBaseUrl.weight; + serviceLocation = parentBaseUrl.serviceLocation; + baseUrls.add( + new BaseUrl( + UriUtil.resolve(parentBaseUrl.url, baseUrl), serviceLocation, priority, weight)); + } + return baseUrls; } /** @@ -1543,9 +1598,7 @@ public static void maybeSkipTag(XmlPullParser xpp) throws IOException, XmlPullPa } } - /** - * Removes unnecessary {@link SchemeData}s with null {@link SchemeData#data}. - */ + /** Removes unnecessary {@link SchemeData}s with null {@link SchemeData#data}. */ private static void filterRedundantIncompleteSchemeDatas(ArrayList schemeDatas) { for (int i = schemeDatas.size() - 1; i >= 0; i--) { SchemeData schemeData = schemeDatas.get(i); @@ -1616,9 +1669,9 @@ private static String checkLanguageConsistency( /** * Checks two adaptation set content types for consistency, returning the consistent type, or * throwing an {@link IllegalStateException} if the types are inconsistent. - *

      - * Two types are consistent if they are equal, or if one is {@link C#TRACK_TYPE_UNKNOWN}. - * Where one of the types is {@link C#TRACK_TYPE_UNKNOWN}, the other is returned. + * + *

      Two types are consistent if they are equal, or if one is {@link C#TRACK_TYPE_UNKNOWN}. Where + * one of the types is {@link C#TRACK_TYPE_UNKNOWN}, the other is returned. * * @param firstType The first type. * @param secondType The second type. @@ -1655,8 +1708,7 @@ protected static Descriptor parseDescriptor(XmlPullParser xpp, String tag) return new Descriptor(schemeIdUri, value, id); } - protected static int parseCea608AccessibilityChannel( - List accessibilityDescriptors) { + protected static int parseCea608AccessibilityChannel(List accessibilityDescriptors) { for (int i = 0; i < accessibilityDescriptors.size(); i++) { Descriptor descriptor = accessibilityDescriptors.get(i); if ("urn:scte:dash:cc:cea-608:2015".equals(descriptor.schemeIdUri) @@ -1672,8 +1724,7 @@ protected static int parseCea608AccessibilityChannel( return Format.NO_VALUE; } - protected static int parseCea708AccessibilityChannel( - List accessibilityDescriptors) { + protected static int parseCea708AccessibilityChannel(List accessibilityDescriptors) { for (int i = 0; i < accessibilityDescriptors.size(); i++) { Descriptor descriptor = accessibilityDescriptors.get(i); if ("urn:scte:dash:cc:cea-708:2015".equals(descriptor.schemeIdUri) @@ -1848,7 +1899,7 @@ private static long getFinalAvailabilityTimeOffset( protected static final class RepresentationInfo { public final Format format; - public final String baseUrl; + public final ImmutableList baseUrls; public final SegmentBase segmentBase; @Nullable public final String drmSchemeType; public final ArrayList drmSchemeDatas; @@ -1857,21 +1908,19 @@ protected static final class RepresentationInfo { public RepresentationInfo( Format format, - String baseUrl, + List baseUrls, SegmentBase segmentBase, @Nullable String drmSchemeType, ArrayList drmSchemeDatas, ArrayList inbandEventStreams, long revisionId) { this.format = format; - this.baseUrl = baseUrl; + this.baseUrls = ImmutableList.copyOf(baseUrls); this.segmentBase = segmentBase; this.drmSchemeType = drmSchemeType; this.drmSchemeDatas = drmSchemeDatas; this.inbandEventStreams = inbandEventStreams; this.revisionId = revisionId; } - } - } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Descriptor.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Descriptor.java index 55dba54db17..23c8ee368e4 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Descriptor.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Descriptor.java @@ -23,13 +23,9 @@ public final class Descriptor { /** The scheme URI. */ public final String schemeIdUri; - /** - * The value, or null. - */ + /** The value, or null. */ @Nullable public final String value; - /** - * The identifier, or null. - */ + /** The identifier, or null. */ @Nullable public final String id; /** @@ -52,7 +48,8 @@ public boolean equals(@Nullable Object obj) { return false; } Descriptor other = (Descriptor) obj; - return Util.areEqual(schemeIdUri, other.schemeIdUri) && Util.areEqual(value, other.value) + return Util.areEqual(schemeIdUri, other.schemeIdUri) + && Util.areEqual(value, other.value) && Util.areEqual(id, other.id); } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/EventStream.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/EventStream.java index 178693fe049..ddc2fe5d1aa 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/EventStream.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/EventStream.java @@ -20,32 +20,26 @@ /** A DASH in-MPD EventStream element, as defined by ISO/IEC 23009-1, 2nd edition, section 5.10. */ public final class EventStream { - /** - * {@link EventMessage}s in the event stream. - */ + /** {@link EventMessage}s in the event stream. */ public final EventMessage[] events; - /** - * Presentation time of the events in microsecond, sorted in ascending order. - */ + /** Presentation time of the events in microsecond, sorted in ascending order. */ public final long[] presentationTimesUs; - /** - * The scheme URI. - */ + /** The scheme URI. */ public final String schemeIdUri; - /** - * The value of the event stream. Use empty string if not defined in manifest. - */ + /** The value of the event stream. Use empty string if not defined in manifest. */ public final String value; - /** - * The timescale in units per seconds, as defined in the manifest. - */ + /** The timescale in units per seconds, as defined in the manifest. */ public final long timescale; - public EventStream(String schemeIdUri, String value, long timescale, long[] presentationTimesUs, + public EventStream( + String schemeIdUri, + String value, + long timescale, + long[] presentationTimesUs, EventMessage[] events) { this.schemeIdUri = schemeIdUri; this.value = value; @@ -54,11 +48,8 @@ public EventStream(String schemeIdUri, String value, long timescale, long[] pres this.events = events; } - /** - * A constructed id of this {@link EventStream}. Equal to {@code schemeIdUri + "/" + value}. - */ + /** A constructed id of this {@link EventStream}. Equal to {@code schemeIdUri + "/" + value}. */ public String id() { return schemeIdUri + "/" + value; } - } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Period.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Period.java index a2396e25334..449803ea1e0 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Period.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Period.java @@ -23,22 +23,16 @@ /** Encapsulates media content components over a contiguous period of time. */ public class Period { - /** - * The period identifier, if one exists. - */ + /** The period identifier, if one exists. */ @Nullable public final String id; /** The start time of the period in milliseconds, relative to the start of the manifest. */ public final long startMs; - /** - * The adaptation sets belonging to the period. - */ + /** The adaptation sets belonging to the period. */ public final List adaptationSets; - /** - * The event stream belonging to the period. - */ + /** The event stream belonging to the period. */ public final List eventStreams; /** The asset identifier for this period, if one exists */ @@ -59,7 +53,10 @@ public Period(@Nullable String id, long startMs, List adaptationS * @param adaptationSets The adaptation sets belonging to the period. * @param eventStreams The {@link EventStream}s belonging to the period. */ - public Period(@Nullable String id, long startMs, List adaptationSets, + public Period( + @Nullable String id, + long startMs, + List adaptationSets, List eventStreams) { this(id, startMs, adaptationSets, eventStreams, /* assetIdentifier= */ null); } @@ -100,5 +97,4 @@ public int getAdaptationSetIndex(int type) { } return C.INDEX_UNSET; } - } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/RangedUri.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/RangedUri.java index 60975dd54b1..1637b2625a5 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/RangedUri.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/RangedUri.java @@ -23,14 +23,10 @@ /** Defines a range of data located at a reference uri. */ public final class RangedUri { - /** - * The (zero based) index of the first byte of the range. - */ + /** The (zero based) index of the first byte of the range. */ public final long start; - /** - * The length of the range, or {@link C#LENGTH_UNSET} to indicate that the range is unbounded. - */ + /** The length of the range, or {@link C#LENGTH_UNSET} to indicate that the range is unbounded. */ public final long length; private final String referenceUri; @@ -90,10 +86,14 @@ public RangedUri attemptMerge(@Nullable RangedUri other, String baseUri) { if (other == null || !resolvedUri.equals(other.resolveUriString(baseUri))) { return null; } else if (length != C.LENGTH_UNSET && start + length == other.start) { - return new RangedUri(resolvedUri, start, + return new RangedUri( + resolvedUri, + start, other.length == C.LENGTH_UNSET ? C.LENGTH_UNSET : length + other.length); } else if (other.length != C.LENGTH_UNSET && other.start + other.length == start) { - return new RangedUri(resolvedUri, other.start, + return new RangedUri( + resolvedUri, + other.start, length == C.LENGTH_UNSET ? C.LENGTH_UNSET : other.length + length); } else { return null; diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Representation.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Representation.java index 226ae84c519..af9771ef149 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Representation.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Representation.java @@ -15,6 +15,8 @@ */ package com.google.android.exoplayer2.source.dash.manifest; +import static com.google.android.exoplayer2.util.Assertions.checkArgument; + import android.net.Uri; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; @@ -23,15 +25,14 @@ import com.google.android.exoplayer2.source.dash.DashSegmentIndex; import com.google.android.exoplayer2.source.dash.manifest.SegmentBase.MultiSegmentBase; import com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase; +import com.google.common.collect.ImmutableList; import java.util.Collections; import java.util.List; /** A DASH representation. */ public abstract class Representation { - /** - * A default value for {@link #revisionId}. - */ + /** A default value for {@link #revisionId}. */ public static final long REVISION_ID_DEFAULT = -1; /** @@ -41,17 +42,11 @@ public abstract class Representation { * often a suitable. */ public final long revisionId; - /** - * The format of the representation. - */ + /** The format of the representation. */ public final Format format; - /** - * The base URL of the representation. - */ - public final String baseUrl; - /** - * The offset of the presentation timestamps in the media stream relative to media time. - */ + /** The base URLs of the representation. */ + public final ImmutableList baseUrls; + /** The offset of the presentation timestamps in the media stream relative to media time. */ public final long presentationTimeOffsetUs; /** The in-band event streams in the representation. May be empty. */ public final List inbandEventStreams; @@ -63,13 +58,13 @@ public abstract class Representation { * * @param revisionId Identifies the revision of the content. * @param format The format of the representation. - * @param baseUrl The base URL. + * @param baseUrls The list of base URLs of the representation. * @param segmentBase A segment base element for the representation. * @return The constructed instance. */ public static Representation newInstance( - long revisionId, Format format, String baseUrl, SegmentBase segmentBase) { - return newInstance(revisionId, format, baseUrl, segmentBase, /* inbandEventStreams= */ null); + long revisionId, Format format, List baseUrls, SegmentBase segmentBase) { + return newInstance(revisionId, format, baseUrls, segmentBase, /* inbandEventStreams= */ null); } /** @@ -77,7 +72,7 @@ public static Representation newInstance( * * @param revisionId Identifies the revision of the content. * @param format The format of the representation. - * @param baseUrl The base URL. + * @param baseUrls The list of base URLs of the representation. * @param segmentBase A segment base element for the representation. * @param inbandEventStreams The in-band event streams in the representation. May be null. * @return The constructed instance. @@ -85,16 +80,11 @@ public static Representation newInstance( public static Representation newInstance( long revisionId, Format format, - String baseUrl, + List baseUrls, SegmentBase segmentBase, @Nullable List inbandEventStreams) { return newInstance( - revisionId, - format, - baseUrl, - segmentBase, - inbandEventStreams, - /* cacheKey= */ null); + revisionId, format, baseUrls, segmentBase, inbandEventStreams, /* cacheKey= */ null); } /** @@ -102,7 +92,7 @@ public static Representation newInstance( * * @param revisionId Identifies the revision of the content. * @param format The format of the representation. - * @param baseUrl The base URL of the representation. + * @param baseUrls The list of base URLs of the representation. * @param segmentBase A segment base element for the representation. * @param inbandEventStreams The in-band event streams in the representation. May be null. * @param cacheKey An optional key to be returned from {@link #getCacheKey()}, or null. This @@ -112,7 +102,7 @@ public static Representation newInstance( public static Representation newInstance( long revisionId, Format format, - String baseUrl, + List baseUrls, SegmentBase segmentBase, @Nullable List inbandEventStreams, @Nullable String cacheKey) { @@ -120,29 +110,30 @@ public static Representation newInstance( return new SingleSegmentRepresentation( revisionId, format, - baseUrl, + baseUrls, (SingleSegmentBase) segmentBase, inbandEventStreams, cacheKey, C.LENGTH_UNSET); } else if (segmentBase instanceof MultiSegmentBase) { return new MultiSegmentRepresentation( - revisionId, format, baseUrl, (MultiSegmentBase) segmentBase, inbandEventStreams); + revisionId, format, baseUrls, (MultiSegmentBase) segmentBase, inbandEventStreams); } else { - throw new IllegalArgumentException("segmentBase must be of type SingleSegmentBase or " - + "MultiSegmentBase"); + throw new IllegalArgumentException( + "segmentBase must be of type SingleSegmentBase or " + "MultiSegmentBase"); } } private Representation( long revisionId, Format format, - String baseUrl, + List baseUrls, SegmentBase segmentBase, @Nullable List inbandEventStreams) { + checkArgument(!baseUrls.isEmpty()); this.revisionId = revisionId; this.format = format; - this.baseUrl = baseUrl; + this.baseUrls = ImmutableList.copyOf(baseUrls); this.inbandEventStreams = inbandEventStreams == null ? Collections.emptyList() @@ -175,19 +166,12 @@ public RangedUri getInitializationUri() { @Nullable public abstract String getCacheKey(); - /** - * A DASH representation consisting of a single segment. - */ + /** A DASH representation consisting of a single segment. */ public static class SingleSegmentRepresentation extends Representation { - /** - * The uri of the single segment. - */ + /** The uri of the single segment. */ public final Uri uri; - - /** - * The content length, or {@link C#LENGTH_UNSET} if unknown. - */ + /** The content length, or {@link C#LENGTH_UNSET} if unknown. */ public final long contentLength; @Nullable private final String cacheKey; @@ -217,18 +201,19 @@ public static SingleSegmentRepresentation newInstance( List inbandEventStreams, @Nullable String cacheKey, long contentLength) { - RangedUri rangedUri = new RangedUri(null, initializationStart, - initializationEnd - initializationStart + 1); - SingleSegmentBase segmentBase = new SingleSegmentBase(rangedUri, 1, 0, indexStart, - indexEnd - indexStart + 1); + RangedUri rangedUri = + new RangedUri(null, initializationStart, initializationEnd - initializationStart + 1); + SingleSegmentBase segmentBase = + new SingleSegmentBase(rangedUri, 1, 0, indexStart, indexEnd - indexStart + 1); + List baseUrls = ImmutableList.of(new BaseUrl(uri)); return new SingleSegmentRepresentation( - revisionId, format, uri, segmentBase, inbandEventStreams, cacheKey, contentLength); + revisionId, format, baseUrls, segmentBase, inbandEventStreams, cacheKey, contentLength); } /** * @param revisionId Identifies the revision of the content. * @param format The format of the representation. - * @param baseUrl The base URL of the representation. + * @param baseUrls The base urls of the representation. * @param segmentBase The segment base underlying the representation. * @param inbandEventStreams The in-band event streams in the representation. May be null. * @param cacheKey An optional key to be returned from {@link #getCacheKey()}, or null. @@ -237,20 +222,20 @@ public static SingleSegmentRepresentation newInstance( public SingleSegmentRepresentation( long revisionId, Format format, - String baseUrl, + List baseUrls, SingleSegmentBase segmentBase, @Nullable List inbandEventStreams, @Nullable String cacheKey, long contentLength) { - super(revisionId, format, baseUrl, segmentBase, inbandEventStreams); - this.uri = Uri.parse(baseUrl); + super(revisionId, format, baseUrls, segmentBase, inbandEventStreams); + this.uri = Uri.parse(baseUrls.get(0).url); this.indexUri = segmentBase.getIndex(); this.cacheKey = cacheKey; this.contentLength = contentLength; // If we have an index uri then the index is defined externally, and we shouldn't return one // directly. If we don't, then we can't do better than an index defining a single segment. - segmentIndex = indexUri != null ? null - : new SingleSegmentIndex(new RangedUri(null, 0, contentLength)); + segmentIndex = + indexUri != null ? null : new SingleSegmentIndex(new RangedUri(null, 0, contentLength)); } @Override @@ -270,12 +255,9 @@ public DashSegmentIndex getIndex() { public String getCacheKey() { return cacheKey; } - } - /** - * A DASH representation consisting of multiple segments. - */ + /** A DASH representation consisting of multiple segments. */ public static class MultiSegmentRepresentation extends Representation implements DashSegmentIndex { @@ -286,17 +268,17 @@ public static class MultiSegmentRepresentation extends Representation * * @param revisionId Identifies the revision of the content. * @param format The format of the representation. - * @param baseUrl The base URL of the representation. + * @param baseUrls The base URLs of the representation. * @param segmentBase The segment base underlying the representation. * @param inbandEventStreams The in-band event streams in the representation. May be null. */ public MultiSegmentRepresentation( long revisionId, Format format, - String baseUrl, + List baseUrls, MultiSegmentBase segmentBase, @Nullable List inbandEventStreams) { - super(revisionId, format, baseUrl, segmentBase, inbandEventStreams); + super(revisionId, format, baseUrls, segmentBase, inbandEventStreams); this.segmentBase = segmentBase; } @@ -320,8 +302,8 @@ public String getCacheKey() { // DashSegmentIndex implementation. @Override - public RangedUri getSegmentUrl(long segmentIndex) { - return segmentBase.getSegmentUrl(this, segmentIndex); + public RangedUri getSegmentUrl(long segmentNum) { + return segmentBase.getSegmentUrl(this, segmentNum); } @Override @@ -330,13 +312,13 @@ public long getSegmentNum(long timeUs, long periodDurationUs) { } @Override - public long getTimeUs(long segmentIndex) { - return segmentBase.getSegmentTimeUs(segmentIndex); + public long getTimeUs(long segmentNum) { + return segmentBase.getSegmentTimeUs(segmentNum); } @Override - public long getDurationUs(long segmentIndex, long periodDurationUs) { - return segmentBase.getSegmentDurationUs(segmentIndex, periodDurationUs); + public long getDurationUs(long segmentNum, long periodDurationUs) { + return segmentBase.getSegmentDurationUs(segmentNum, periodDurationUs); } @Override @@ -368,7 +350,5 @@ public long getNextSegmentAvailableTimeUs(long periodDurationUs, long nowUnixTim public boolean isExplicit() { return segmentBase.isExplicit(); } - } - } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SegmentBase.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SegmentBase.java index 20f45b80366..754d5fc99d3 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SegmentBase.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SegmentBase.java @@ -62,16 +62,12 @@ public RangedUri getInitialization(Representation representation) { return initialization; } - /** - * Returns the presentation time offset, in microseconds. - */ + /** Returns the presentation time offset, in microseconds. */ public long getPresentationTimeOffsetUs() { return Util.scaleLargeTimestamp(presentationTimeOffset, C.MICROS_PER_SECOND, timescale); } - /** - * A {@link SegmentBase} that defines a single segment. - */ + /** A {@link SegmentBase} that defines a single segment. */ public static class SingleSegmentBase extends SegmentBase { /* package */ final long indexStart; @@ -112,12 +108,9 @@ public RangedUri getIndex() { ? null : new RangedUri(/* referenceUri= */ null, indexStart, indexLength); } - } - /** - * A {@link SegmentBase} that consists of multiple segments. - */ + /** A {@link SegmentBase} that consists of multiple segments. */ public abstract static class MultiSegmentBase extends SegmentBase { /* package */ final long startNumber; @@ -365,7 +358,6 @@ public long getSegmentCount(long periodDurationUs) { public boolean isExplicit() { return true; } - } /** A {@link MultiSegmentBase} that uses a SegmentTemplate to define its segments. */ @@ -434,8 +426,9 @@ public SegmentTemplate( @Nullable public RangedUri getInitialization(Representation representation) { if (initializationTemplate != null) { - String urlString = initializationTemplate.buildUri(representation.format.id, 0, - representation.format.bitrate, 0); + String urlString = + initializationTemplate.buildUri( + representation.format.id, 0, representation.format.bitrate, 0); return new RangedUri(urlString, 0, C.LENGTH_UNSET); } else { return super.getInitialization(representation); @@ -450,8 +443,9 @@ public RangedUri getSegmentUrl(Representation representation, long sequenceNumbe } else { time = (sequenceNumber - startNumber) * duration; } - String uriString = mediaTemplate.buildUri(representation.format.id, sequenceNumber, - representation.format.bitrate, time); + String uriString = + mediaTemplate.buildUri( + representation.format.id, sequenceNumber, representation.format.bitrate, time); return new RangedUri(uriString, 0, C.LENGTH_UNSET); } @@ -507,5 +501,4 @@ public int hashCode() { return 31 * (int) startTime + (int) duration; } } - } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SingleSegmentIndex.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SingleSegmentIndex.java index a5806450a31..77f189f5b12 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SingleSegmentIndex.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SingleSegmentIndex.java @@ -18,16 +18,12 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.source.dash.DashSegmentIndex; -/** - * A {@link DashSegmentIndex} that defines a single segment. - */ +/** A {@link DashSegmentIndex} that defines a single segment. */ /* package */ final class SingleSegmentIndex implements DashSegmentIndex { private final RangedUri uri; - /** - * @param uri A {@link RangedUri} defining the location of the segment data. - */ + /** @param uri A {@link RangedUri} defining the location of the segment data. */ public SingleSegmentIndex(RangedUri uri) { this.uri = uri; } @@ -81,5 +77,4 @@ public long getNextSegmentAvailableTimeUs(long periodDurationUs, long nowUnixTim public boolean isExplicit() { return true; } - } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/UrlTemplate.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/UrlTemplate.java index fbf06c5885f..cc3597a33af 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/UrlTemplate.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/UrlTemplate.java @@ -58,11 +58,9 @@ public static UrlTemplate compile(String template) { return new UrlTemplate(urlPieces, identifiers, identifierFormatTags, identifierCount); } - /** - * Internal constructor. Use {@link #compile(String)} to build instances of this class. - */ - private UrlTemplate(String[] urlPieces, int[] identifiers, String[] identifierFormatTags, - int identifierCount) { + /** Internal constructor. Use {@link #compile(String)} to build instances of this class. */ + private UrlTemplate( + String[] urlPieces, int[] identifiers, String[] identifierFormatTags, int identifierCount) { this.urlPieces = urlPieces; this.identifiers = identifiers; this.identifierFormatTags = identifierFormatTags; @@ -100,8 +98,8 @@ public String buildUri(String representationId, long segmentNumber, int bandwidt /** * Parses {@code template}, placing the decomposed components into the provided arrays. - *

      - * If the return value is N, {@code urlPieces} will contain (N+1) strings that must be + * + *

      If the return value is N, {@code urlPieces} will contain (N+1) strings that must be * interleaved with N arguments in order to construct a url. The N identifiers that correspond to * the required arguments, together with the tags that define their required formatting, are * returned in {@code identifiers} and {@code identifierFormatTags} respectively. @@ -113,8 +111,8 @@ public String buildUri(String representationId, long segmentNumber, int bandwidt * @return The number of identifiers in the template url. * @throws IllegalArgumentException If the template string is malformed. */ - private static int parseTemplate(String template, String[] urlPieces, int[] identifiers, - String[] identifierFormatTags) { + private static int parseTemplate( + String template, String[] urlPieces, int[] identifiers, String[] identifierFormatTags) { urlPieces[0] = ""; int templateIndex = 0; int identifierCount = 0; @@ -169,5 +167,4 @@ private static int parseTemplate(String template, String[] urlPieces, int[] iden } return identifierCount; } - } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/UtcTimingElement.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/UtcTimingElement.java index 9508623c9db..7deb92e66c8 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/UtcTimingElement.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/UtcTimingElement.java @@ -30,5 +30,4 @@ public UtcTimingElement(String schemeIdUri, String value) { public String toString() { return schemeIdUri + ", " + value; } - } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/offline/DashDownloader.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/offline/DashDownloader.java index ed195ec417f..2029b370de1 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/offline/DashDownloader.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/offline/DashDownloader.java @@ -15,14 +15,12 @@ */ package com.google.android.exoplayer2.source.dash.offline; -import android.net.Uri; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.extractor.ChunkIndex; import com.google.android.exoplayer2.offline.DownloadException; import com.google.android.exoplayer2.offline.SegmentDownloader; -import com.google.android.exoplayer2.offline.StreamKey; import com.google.android.exoplayer2.source.dash.DashSegmentIndex; import com.google.android.exoplayer2.source.dash.DashUtil; import com.google.android.exoplayer2.source.dash.DashWrappingSegmentIndex; @@ -72,14 +70,6 @@ */ public final class DashDownloader extends SegmentDownloader { - /** @deprecated Use {@link #DashDownloader(MediaItem, CacheDataSource.Factory)} instead. */ - @SuppressWarnings("deprecation") - @Deprecated - public DashDownloader( - Uri manifestUri, List streamKeys, CacheDataSource.Factory cacheDataSourceFactory) { - this(manifestUri, streamKeys, cacheDataSourceFactory, Runnable::run); - } - /** * Creates a new instance. * @@ -91,21 +81,6 @@ public DashDownloader(MediaItem mediaItem, CacheDataSource.Factory cacheDataSour this(mediaItem, cacheDataSourceFactory, Runnable::run); } - /** - * @deprecated Use {@link #DashDownloader(MediaItem, CacheDataSource.Factory, Executor)} instead. - */ - @Deprecated - public DashDownloader( - Uri manifestUri, - List streamKeys, - CacheDataSource.Factory cacheDataSourceFactory, - Executor executor) { - this( - new MediaItem.Builder().setUri(manifestUri).setStreamKeys(streamKeys).build(), - cacheDataSourceFactory, - executor); - } - /** * Creates a new instance. * @@ -188,7 +163,7 @@ private void addSegmentsForAdaptationSet( throw new DownloadException("Unbounded segment index"); } - String baseUrl = representation.baseUrl; + String baseUrl = representation.baseUrls.get(0).url; RangedUri initializationUri = representation.getInitializationUri(); if (initializationUri != null) { addSegment(periodStartUs, baseUrl, initializationUri, out); diff --git a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/BaseUrlExclusionListTest.java b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/BaseUrlExclusionListTest.java new file mode 100644 index 00000000000..cb75903c810 --- /dev/null +++ b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/BaseUrlExclusionListTest.java @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.exoplayer2.source.dash; + +import static com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy.DEFAULT_LOCATION_EXCLUSION_MS; +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.source.dash.manifest.BaseUrl; +import com.google.common.collect.ImmutableList; +import java.time.Duration; +import java.util.List; +import java.util.Random; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.shadows.ShadowSystemClock; + +/** Unit tests for {@link BaseUrlExclusionList}. */ +@RunWith(AndroidJUnit4.class) +public class BaseUrlExclusionListTest { + + @Test + public void selectBaseUrl_excludeByServiceLocation_excludesAllBaseUrlOfSameServiceLocation() { + BaseUrlExclusionList baseUrlExclusionList = new BaseUrlExclusionList(); + List baseUrls = + ImmutableList.of( + new BaseUrl( + /* url= */ "a", /* serviceLocation= */ "a", /* priority= */ 1, /* weight= */ 1), + new BaseUrl( + /* url= */ "b", /* serviceLocation= */ "a", /* priority= */ 2, /* weight= */ 1), + new BaseUrl( + /* url= */ "c", /* serviceLocation= */ "c", /* priority= */ 3, /* weight= */ 1)); + + baseUrlExclusionList.exclude(baseUrls.get(0), 5000); + + ShadowSystemClock.advanceBy(Duration.ofMillis(4999)); + assertThat(baseUrlExclusionList.selectBaseUrl(baseUrls).url).isEqualTo("c"); + ShadowSystemClock.advanceBy(Duration.ofMillis(1)); + assertThat(baseUrlExclusionList.selectBaseUrl(baseUrls).url).isEqualTo("a"); + } + + @Test + public void selectBaseUrl_excludeByPriority_excludesAllBaseUrlsOfSamePriority() { + Random mockRandom = mock(Random.class); + when(mockRandom.nextInt(anyInt())).thenReturn(0); + BaseUrlExclusionList baseUrlExclusionList = new BaseUrlExclusionList(mockRandom); + List baseUrls = + ImmutableList.of( + new BaseUrl( + /* url= */ "a", /* serviceLocation= */ "a", /* priority= */ 1, /* weight= */ 1), + new BaseUrl( + /* url= */ "b", /* serviceLocation= */ "b", /* priority= */ 1, /* weight= */ 99), + new BaseUrl( + /* url= */ "c", /* serviceLocation= */ "c", /* priority= */ 2, /* weight= */ 1)); + + baseUrlExclusionList.exclude(baseUrls.get(0), 5000); + + ShadowSystemClock.advanceBy(Duration.ofMillis(4999)); + assertThat(baseUrlExclusionList.selectBaseUrl(baseUrls).url).isEqualTo("c"); + ShadowSystemClock.advanceBy(Duration.ofMillis(1)); + assertThat(baseUrlExclusionList.selectBaseUrl(baseUrls).url).isEqualTo("a"); + } + + @Test + public void selectBaseUrl_samePriority_choiceIsRandom() { + List baseUrls = + ImmutableList.of( + new BaseUrl( + /* url= */ "a", /* serviceLocation= */ "a", /* priority= */ 1, /* weight= */ 99), + new BaseUrl( + /* url= */ "b", /* serviceLocation= */ "b", /* priority= */ 1, /* weight= */ 1)); + Random mockRandom = mock(Random.class); + when(mockRandom.nextInt(anyInt())).thenReturn(99); + + assertThat(new BaseUrlExclusionList(mockRandom).selectBaseUrl(baseUrls)) + .isEqualTo(baseUrls.get(1)); + + // Random is used for random choice. + verify(mockRandom).nextInt(/* bound= */ 100); + verifyNoMoreInteractions(mockRandom); + } + + @Test + public void selectBaseUrl_samePriority_choiceFromSameElementsRandomOnlyOnceSameAfterwards() { + List baseUrlsVideo = + ImmutableList.of( + new BaseUrl( + /* url= */ "a/v", /* serviceLocation= */ "a", /* priority= */ 1, /* weight= */ 99), + new BaseUrl( + /* url= */ "b/v", /* serviceLocation= */ "b", /* priority= */ 1, /* weight= */ 1)); + List baseUrlsAudio = + ImmutableList.of( + new BaseUrl( + /* url= */ "a/a", /* serviceLocation= */ "a", /* priority= */ 1, /* weight= */ 99), + new BaseUrl( + /* url= */ "b/a", /* serviceLocation= */ "b", /* priority= */ 1, /* weight= */ 1)); + Random mockRandom = mock(Random.class); + BaseUrlExclusionList baseUrlExclusionList = new BaseUrlExclusionList(mockRandom); + when(mockRandom.nextInt(anyInt())).thenReturn(99); + + for (int i = 0; i < 5; i++) { + assertThat(baseUrlExclusionList.selectBaseUrl(baseUrlsVideo).serviceLocation).isEqualTo("b"); + assertThat(baseUrlExclusionList.selectBaseUrl(baseUrlsAudio).serviceLocation).isEqualTo("b"); + } + // Random is used only once. + verify(mockRandom).nextInt(/* bound= */ 100); + verifyNoMoreInteractions(mockRandom); + } + + @Test + public void selectBaseUrl_twiceTheSameLocationExcluded_correctExpirationDuration() { + List baseUrls = + ImmutableList.of( + new BaseUrl( + /* url= */ "a", /* serviceLocation= */ "a", /* priority= */ 1, /* weight= */ 1), + new BaseUrl( + /* url= */ "c", /* serviceLocation= */ "a", /* priority= */ 2, /* weight= */ 1), + new BaseUrl( + /* url= */ "d", /* serviceLocation= */ "d", /* priority= */ 2, /* weight= */ 1)); + BaseUrlExclusionList baseUrlExclusionList = new BaseUrlExclusionList(); + + // Exclude location 'a'. + baseUrlExclusionList.exclude(baseUrls.get(0), 5000); + // Exclude location 'a' which increases exclusion duration of 'a'. + baseUrlExclusionList.exclude(baseUrls.get(1), 10000); + assertThat(baseUrlExclusionList.selectBaseUrl(baseUrls)).isNull(); + ShadowSystemClock.advanceBy(Duration.ofMillis(9999)); + // Location 'a' still excluded. + assertThat(baseUrlExclusionList.selectBaseUrl(baseUrls)).isNull(); + ShadowSystemClock.advanceBy(Duration.ofMillis(1)); + assertThat(baseUrlExclusionList.getPriorityCountAfterExclusion(baseUrls)).isEqualTo(2); + assertThat(baseUrlExclusionList.selectBaseUrl(baseUrls).url).isEqualTo("a"); + } + + @Test + public void selectBaseUrl_twiceTheSamePriorityExcluded_correctExpirationDuration() { + List baseUrls = + ImmutableList.of( + new BaseUrl( + /* url= */ "a", /* serviceLocation= */ "a", /* priority= */ 1, /* weight= */ 1), + new BaseUrl( + /* url= */ "b", /* serviceLocation= */ "b", /* priority= */ 1, /* weight= */ 1), + new BaseUrl( + /* url= */ "c", /* serviceLocation= */ "c", /* priority= */ 2, /* weight= */ 1)); + BaseUrlExclusionList baseUrlExclusionList = new BaseUrlExclusionList(); + + // Exclude priority 1. + baseUrlExclusionList.exclude(baseUrls.get(0), 5000); + // Exclude priority 1 again which increases the exclusion duration. + baseUrlExclusionList.exclude(baseUrls.get(1), 10000); + assertThat(baseUrlExclusionList.selectBaseUrl(baseUrls).url).isEqualTo("c"); + ShadowSystemClock.advanceBy(Duration.ofMillis(9999)); + assertThat(baseUrlExclusionList.getPriorityCountAfterExclusion(baseUrls)).isEqualTo(1); + ShadowSystemClock.advanceBy(Duration.ofMillis(1)); + assertThat(baseUrlExclusionList.getPriorityCountAfterExclusion(baseUrls)).isEqualTo(2); + } + + @Test + public void selectBaseUrl_emptyBaseUrlList_selectionIsNull() { + BaseUrlExclusionList baseUrlExclusionList = new BaseUrlExclusionList(); + + assertThat(baseUrlExclusionList.selectBaseUrl(ImmutableList.of())).isNull(); + } + + @Test + public void reset_dropsAllExclusions() { + BaseUrlExclusionList baseUrlExclusionList = new BaseUrlExclusionList(); + List baseUrls = ImmutableList.of(new BaseUrl("a")); + baseUrlExclusionList.exclude(baseUrls.get(0), 5000); + + baseUrlExclusionList.reset(); + + assertThat(baseUrlExclusionList.selectBaseUrl(baseUrls).url).isEqualTo("a"); + } + + @Test + public void getPriorityCountAfterExclusion_correctPriorityCount() { + List baseUrls = + ImmutableList.of( + new BaseUrl( + /* url= */ "a", /* serviceLocation= */ "a", /* priority= */ 1, /* weight= */ 1), + new BaseUrl( + /* url= */ "b", /* serviceLocation= */ "b", /* priority= */ 2, /* weight= */ 1), + new BaseUrl( + /* url= */ "c", /* serviceLocation= */ "c", /* priority= */ 2, /* weight= */ 1), + new BaseUrl( + /* url= */ "d", /* serviceLocation= */ "d", /* priority= */ 3, /* weight= */ 1), + new BaseUrl( + /* url= */ "e", /* serviceLocation= */ "e", /* priority= */ 3, /* weight= */ 1)); + BaseUrlExclusionList baseUrlExclusionList = new BaseUrlExclusionList(); + + // Empty base URL list. + assertThat(baseUrlExclusionList.getPriorityCountAfterExclusion(ImmutableList.of())) + .isEqualTo(0); + + assertThat(baseUrlExclusionList.getPriorityCountAfterExclusion(baseUrls)).isEqualTo(3); + // Exclude base urls. + baseUrlExclusionList.exclude(baseUrls.get(0), DEFAULT_LOCATION_EXCLUSION_MS); + assertThat(baseUrlExclusionList.getPriorityCountAfterExclusion(baseUrls)).isEqualTo(2); + baseUrlExclusionList.exclude(baseUrls.get(1), 2 * DEFAULT_LOCATION_EXCLUSION_MS); + assertThat(baseUrlExclusionList.getPriorityCountAfterExclusion(baseUrls)).isEqualTo(1); + baseUrlExclusionList.exclude(baseUrls.get(3), 3 * DEFAULT_LOCATION_EXCLUSION_MS); + assertThat(baseUrlExclusionList.getPriorityCountAfterExclusion(baseUrls)).isEqualTo(0); + // Time passes. + ShadowSystemClock.advanceBy(Duration.ofMillis(DEFAULT_LOCATION_EXCLUSION_MS)); + assertThat(baseUrlExclusionList.getPriorityCountAfterExclusion(baseUrls)).isEqualTo(1); + ShadowSystemClock.advanceBy(Duration.ofMillis(DEFAULT_LOCATION_EXCLUSION_MS)); + assertThat(baseUrlExclusionList.getPriorityCountAfterExclusion(baseUrls)).isEqualTo(2); + ShadowSystemClock.advanceBy(Duration.ofMillis(DEFAULT_LOCATION_EXCLUSION_MS)); + assertThat(baseUrlExclusionList.getPriorityCountAfterExclusion(baseUrls)).isEqualTo(3); + } + + @Test + public void getPriorityCount_correctPriorityCount() { + List baseUrls = + ImmutableList.of( + new BaseUrl( + /* url= */ "a", /* serviceLocation= */ "a", /* priority= */ 1, /* weight= */ 1), + new BaseUrl( + /* url= */ "b", /* serviceLocation= */ "b", /* priority= */ 2, /* weight= */ 1), + new BaseUrl( + /* url= */ "c", /* serviceLocation= */ "c", /* priority= */ 2, /* weight= */ 1), + new BaseUrl( + /* url= */ "d", /* serviceLocation= */ "d", /* priority= */ 3, /* weight= */ 1)); + + assertThat(BaseUrlExclusionList.getPriorityCount(baseUrls)).isEqualTo(3); + assertThat(BaseUrlExclusionList.getPriorityCount(ImmutableList.of())).isEqualTo(0); + } +} diff --git a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DashMediaPeriodTest.java b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DashMediaPeriodTest.java index 99fd1694376..fd55087b47f 100644 --- a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DashMediaPeriodTest.java +++ b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DashMediaPeriodTest.java @@ -44,9 +44,11 @@ import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit tests for {@link DashMediaPeriod}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class DashMediaPeriodTest { @Test @@ -198,6 +200,7 @@ private static DashMediaPeriod createDashMediaPeriod(DashManifest manifest, int return new DashMediaPeriod( /* id= */ periodIndex, manifest, + new BaseUrlExclusionList(), periodIndex, mock(DashChunkSource.Factory.class), mock(TransferListener.class), diff --git a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DashMediaSourceTest.java b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DashMediaSourceTest.java index d1269e18a1f..e9079e91d2b 100644 --- a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DashMediaSourceTest.java +++ b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DashMediaSourceTest.java @@ -18,10 +18,8 @@ import static com.google.common.truth.Truth.assertThat; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static org.junit.Assert.fail; -import static org.robolectric.annotation.LooperMode.Mode.PAUSED; import android.net.Uri; -import androidx.annotation.Nullable; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.C; @@ -45,12 +43,12 @@ import java.util.concurrent.atomic.AtomicReference; import org.junit.Test; import org.junit.runner.RunWith; -import org.robolectric.annotation.LooperMode; +import org.robolectric.annotation.internal.DoNotInstrument; import org.robolectric.shadows.ShadowLooper; /** Unit test for {@link DashMediaSource}. */ @RunWith(AndroidJUnit4.class) -@LooperMode(PAUSED) +@DoNotInstrument public final class DashMediaSourceTest { private static final String SAMPLE_MPD_LIVE_WITHOUT_LIVE_CONFIGURATION = @@ -138,35 +136,6 @@ public void factorySetTag_nonNullMediaItemTag_doesNotOverrideMediaItemTag() { assertThat(dashMediaItem.playbackProperties.tag).isEqualTo(mediaItemTag); } - // Tests backwards compatibility - @SuppressWarnings("deprecation") - @Test - public void factorySetTag_setsDeprecatedMediaSourceTag() { - Object tag = new Object(); - MediaItem mediaItem = MediaItem.fromUri("http://www.google.com"); - DashMediaSource.Factory factory = - new DashMediaSource.Factory(new FileDataSource.Factory()).setTag(tag); - - @Nullable Object mediaSourceTag = factory.createMediaSource(mediaItem).getTag(); - - assertThat(mediaSourceTag).isEqualTo(tag); - } - - // Tests backwards compatibility - @SuppressWarnings("deprecation") - @Test - public void factoryCreateMediaSource_setsDeprecatedMediaSourceTag() { - Object tag = new Object(); - MediaItem mediaItem = - new MediaItem.Builder().setUri("http://www.google.com").setTag(tag).build(); - DashMediaSource.Factory factory = - new DashMediaSource.Factory(new FileDataSource.Factory()).setTag(new Object()); - - @Nullable Object mediaSourceTag = factory.createMediaSource(mediaItem).getTag(); - - assertThat(mediaSourceTag).isEqualTo(tag); - } - // Tests backwards compatibility @SuppressWarnings("deprecation") @Test diff --git a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DashUtilTest.java b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DashUtilTest.java index 188d1b2a180..1eb422d27c2 100644 --- a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DashUtilTest.java +++ b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DashUtilTest.java @@ -23,18 +23,22 @@ import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.drm.DrmInitData.SchemeData; import com.google.android.exoplayer2.source.dash.manifest.AdaptationSet; +import com.google.android.exoplayer2.source.dash.manifest.BaseUrl; import com.google.android.exoplayer2.source.dash.manifest.Period; import com.google.android.exoplayer2.source.dash.manifest.Representation; import com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase; import com.google.android.exoplayer2.upstream.DummyDataSource; import com.google.android.exoplayer2.util.MimeTypes; +import com.google.common.collect.ImmutableList; import java.util.Arrays; import java.util.Collections; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit tests for {@link DashUtil}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class DashUtilTest { @Test @@ -86,7 +90,11 @@ private static Representation newRepresentation(DrmInitData drmInitData) { .setSampleMimeType(MimeTypes.VIDEO_H264) .setDrmInitData(drmInitData) .build(); - return Representation.newInstance(0, format, "", new SingleSegmentBase()); + return Representation.newInstance( + /* revisionId= */ 0, + format, + /* baseUrls= */ ImmutableList.of(new BaseUrl("")), + new SingleSegmentBase()); } private static DrmInitData newDrmInitData() { diff --git a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSourceTest.java b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSourceTest.java index e403482b6c5..1308416f183 100644 --- a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSourceTest.java +++ b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSourceTest.java @@ -15,35 +15,59 @@ */ package com.google.android.exoplayer2.source.dash; +import static com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy.DEFAULT_LOCATION_EXCLUSION_MS; +import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static com.google.common.truth.Truth.assertThat; import android.net.Uri; import android.os.SystemClock; +import androidx.annotation.Nullable; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.source.LoadEventInfo; +import com.google.android.exoplayer2.source.MediaLoadData; import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.chunk.BundledChunkExtractor; +import com.google.android.exoplayer2.source.chunk.Chunk; import com.google.android.exoplayer2.source.chunk.ChunkHolder; import com.google.android.exoplayer2.source.dash.manifest.DashManifest; import com.google.android.exoplayer2.source.dash.manifest.DashManifestParser; import com.google.android.exoplayer2.testutil.FakeDataSource; import com.google.android.exoplayer2.testutil.TestUtil; +import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection; import com.google.android.exoplayer2.trackselection.FixedTrackSelection; import com.google.android.exoplayer2.upstream.DataSpec; +import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; +import com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy; +import com.google.android.exoplayer2.upstream.HttpDataSource; +import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy; import com.google.android.exoplayer2.upstream.LoaderErrorThrower; +import com.google.android.exoplayer2.util.Assertions; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import java.io.IOException; +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; +import org.robolectric.shadows.ShadowSystemClock; /** Unit test for {@link DefaultDashChunkSource}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public class DefaultDashChunkSourceTest { private static final String SAMPLE_MPD_LIVE_WITH_OFFSET_INSIDE_WINDOW = "media/mpd/sample_mpd_live_with_offset_inside_window"; private static final String SAMPLE_MPD_VOD = "media/mpd/sample_mpd_vod"; + private static final String SAMPLE_MPD_VOD_LOCATION_FALLBACK = + "media/mpd/sample_mpd_vod_location_fallback"; @Test public void getNextChunk_forLowLatencyManifest_setsCorrectMayNotLoadAtFullNetworkSpeedFlag() @@ -62,6 +86,7 @@ public void getNextChunk_forLowLatencyManifest_setsCorrectMayNotLoadAtFullNetwor BundledChunkExtractor.FACTORY, new LoaderErrorThrower.Dummy(), manifest, + new BaseUrlExclusionList(), /* periodIndex= */ 0, /* adaptationSetIndices= */ new int[] {0}, new FixedTrackSelection(new TrackGroup(new Format.Builder().build()), /* track= */ 0), @@ -109,6 +134,7 @@ public void getNextChunk_forVodManifest_doesNotSetMayNotLoadAtFullNetworkSpeedFl BundledChunkExtractor.FACTORY, new LoaderErrorThrower.Dummy(), manifest, + new BaseUrlExclusionList(), /* periodIndex= */ 0, /* adaptationSetIndices= */ new int[] {0}, new FixedTrackSelection(new TrackGroup(new Format.Builder().build()), /* track= */ 0), @@ -130,4 +156,194 @@ public void getNextChunk_forVodManifest_doesNotSetMayNotLoadAtFullNetworkSpeedFl assertThat(output.chunk.dataSpec.flags & DataSpec.FLAG_MIGHT_NOT_USE_FULL_NETWORK_SPEED) .isEqualTo(0); } + + @Test + public void getNextChunk_onChunkLoadErrorLocationExclusionEnabled_correctFallbackBehavior() + throws Exception { + DefaultLoadErrorHandlingPolicy loadErrorHandlingPolicy = + new DefaultLoadErrorHandlingPolicy() { + @Override + public FallbackSelection getFallbackSelectionFor( + FallbackOptions fallbackOptions, LoadErrorInfo loadErrorInfo) { + return new FallbackSelection(FALLBACK_TYPE_LOCATION, DEFAULT_LOCATION_EXCLUSION_MS); + } + }; + List chunks = new ArrayList<>(); + DashChunkSource chunkSource = createDashChunkSource(/* numberOfTracks= */ 1); + ChunkHolder output = new ChunkHolder(); + + boolean requestReplacementChunk = true; + while (requestReplacementChunk) { + chunkSource.getNextChunk( + /* playbackPositionUs= */ 0, + /* loadPositionUs= */ 0, + /* queue= */ ImmutableList.of(), + output); + chunks.add(output.chunk); + requestReplacementChunk = + chunkSource.onChunkLoadError( + checkNotNull(output.chunk), + /* cancelable= */ true, + createFakeLoadErrorInfo( + output.chunk.dataSpec, /* httpResponseCode= */ 404, /* errorCount= */ 1), + loadErrorHandlingPolicy); + } + + assertThat(Lists.transform(chunks, (chunk) -> chunk.dataSpec.uri.toString())) + .containsExactly( + "http://video.com/baseUrl/a/video/video_0_1300000.m4s", + "http://video.com/baseUrl/b/video/video_0_1300000.m4s", + "http://video.com/baseUrl/d/video/video_0_1300000.m4s") + .inOrder(); + + // Assert expiration of exclusions. + ShadowSystemClock.advanceBy(Duration.ofMillis(DEFAULT_LOCATION_EXCLUSION_MS)); + chunkSource.onChunkLoadError( + checkNotNull(output.chunk), + /* cancelable= */ true, + createFakeLoadErrorInfo( + output.chunk.dataSpec, /* httpResponseCode= */ 404, /* errorCount= */ 1), + loadErrorHandlingPolicy); + chunkSource.getNextChunk( + /* playbackPositionUs= */ 0, + /* loadPositionUs= */ 0, + /* queue= */ ImmutableList.of(), + output); + assertThat(output.chunk.dataSpec.uri.toString()) + .isEqualTo("http://video.com/baseUrl/a/video/video_0_1300000.m4s"); + } + + @Test + public void getNextChunk_onChunkLoadErrorTrackExclusionEnabled_correctFallbackBehavior() + throws Exception { + DefaultLoadErrorHandlingPolicy loadErrorHandlingPolicy = + new DefaultLoadErrorHandlingPolicy() { + @Override + public FallbackSelection getFallbackSelectionFor( + FallbackOptions fallbackOptions, LoadErrorInfo loadErrorInfo) { + // Exclude tracks only. + return new FallbackSelection( + FALLBACK_TYPE_TRACK, DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_EXCLUSION_MS); + } + }; + DashChunkSource chunkSource = createDashChunkSource(/* numberOfTracks= */ 4); + ChunkHolder output = new ChunkHolder(); + List chunks = new ArrayList<>(); + boolean requestReplacementChunk = true; + while (requestReplacementChunk) { + chunkSource.getNextChunk( + /* playbackPositionUs= */ 0, + /* loadPositionUs= */ 0, + /* queue= */ ImmutableList.of(), + output); + chunks.add(output.chunk); + requestReplacementChunk = + chunkSource.onChunkLoadError( + checkNotNull(output.chunk), + /* cancelable= */ true, + createFakeLoadErrorInfo( + output.chunk.dataSpec, /* httpResponseCode= */ 404, /* errorCount= */ 1), + loadErrorHandlingPolicy); + } + assertThat(Lists.transform(chunks, (chunk) -> chunk.dataSpec.uri.toString())) + .containsExactly( + "http://video.com/baseUrl/a/video/video_0_700000.m4s", + "http://video.com/baseUrl/a/video/video_0_452000.m4s", + "http://video.com/baseUrl/a/video/video_0_250000.m4s", + "http://video.com/baseUrl/a/video/video_0_1300000.m4s") + .inOrder(); + } + + @Test + public void getNextChunk_onChunkLoadErrorExclusionDisabled_neverRequestReplacementChunk() + throws Exception { + DefaultLoadErrorHandlingPolicy loadErrorHandlingPolicy = + new DefaultLoadErrorHandlingPolicy() { + @Override + @Nullable + public FallbackSelection getFallbackSelectionFor( + FallbackOptions fallbackOptions, LoadErrorInfo loadErrorInfo) { + // Never exclude, neither tracks nor locations. + return null; + } + }; + DashChunkSource chunkSource = createDashChunkSource(/* numberOfTracks= */ 2); + ChunkHolder output = new ChunkHolder(); + chunkSource.getNextChunk( + /* playbackPositionUs= */ 0, + /* loadPositionUs= */ 0, + /* queue= */ ImmutableList.of(), + output); + + boolean requestReplacementChunk = + chunkSource.onChunkLoadError( + checkNotNull(output.chunk), + /* cancelable= */ true, + createFakeLoadErrorInfo( + output.chunk.dataSpec, /* httpResponseCode= */ 404, /* errorCount= */ 1), + loadErrorHandlingPolicy); + + assertThat(requestReplacementChunk).isFalse(); + } + + private DashChunkSource createDashChunkSource(int numberOfTracks) throws IOException { + Assertions.checkArgument(numberOfTracks < 6); + DashManifest manifest = + new DashManifestParser() + .parse( + Uri.parse("https://example.com/test.mpd"), + TestUtil.getInputStream( + ApplicationProvider.getApplicationContext(), SAMPLE_MPD_VOD_LOCATION_FALLBACK)); + int[] adaptationSetIndices = new int[] {0}; + int[] selectedTracks = new int[numberOfTracks]; + Format[] formats = new Format[numberOfTracks]; + for (int i = 0; i < numberOfTracks; i++) { + selectedTracks[i] = i; + formats[i] = + manifest + .getPeriod(0) + .adaptationSets + .get(adaptationSetIndices[0]) + .representations + .get(i) + .format; + } + AdaptiveTrackSelection adaptiveTrackSelection = + new AdaptiveTrackSelection( + new TrackGroup(formats), + selectedTracks, + new DefaultBandwidthMeter.Builder(ApplicationProvider.getApplicationContext()).build()); + return new DefaultDashChunkSource( + BundledChunkExtractor.FACTORY, + new LoaderErrorThrower.Dummy(), + manifest, + new BaseUrlExclusionList(new Random(/* seed= */ 1234)), + /* periodIndex= */ 0, + /* adaptationSetIndices= */ adaptationSetIndices, + adaptiveTrackSelection, + C.TRACK_TYPE_VIDEO, + new FakeDataSource(), + /* elapsedRealtimeOffsetMs= */ 0, + /* maxSegmentsPerLoad= */ 1, + /* enableEventMessageTrack= */ false, + /* closedCaptionFormats */ ImmutableList.of(), + /* playerTrackEmsgHandler= */ null); + } + + private LoadErrorHandlingPolicy.LoadErrorInfo createFakeLoadErrorInfo( + DataSpec dataSpec, int httpResponseCode, int errorCount) { + LoadEventInfo loadEventInfo = + new LoadEventInfo(/* loadTaskId= */ 0, dataSpec, SystemClock.elapsedRealtime()); + MediaLoadData mediaLoadData = new MediaLoadData(C.DATA_TYPE_MEDIA); + HttpDataSource.InvalidResponseCodeException invalidResponseCodeException = + new HttpDataSource.InvalidResponseCodeException( + httpResponseCode, + /* responseMessage= */ null, + /* cause= */ null, + ImmutableMap.of(), + dataSpec, + new byte[0]); + return new LoadErrorHandlingPolicy.LoadErrorInfo( + loadEventInfo, mediaLoadData, invalidResponseCodeException, errorCount); + } } diff --git a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DefaultMediaSourceFactoryTest.java b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DefaultMediaSourceFactoryTest.java index ab7f456c551..1e64b8d7a48 100644 --- a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DefaultMediaSourceFactoryTest.java +++ b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DefaultMediaSourceFactoryTest.java @@ -27,9 +27,11 @@ import com.google.android.exoplayer2.util.MimeTypes; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for creating DASH media sources with the {@link DefaultMediaSourceFactory}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public class DefaultMediaSourceFactoryTest { private static final String URI_MEDIA = "http://exoplayer.dev/video"; diff --git a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/EventSampleStreamTest.java b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/EventSampleStreamTest.java index 348290eb69e..7dfa4e65970 100644 --- a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/EventSampleStreamTest.java +++ b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/EventSampleStreamTest.java @@ -30,9 +30,11 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link EventSampleStream}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class EventSampleStreamTest { private static final String SCHEME_ID = "urn:test"; @@ -63,9 +65,12 @@ public void setUp() { */ @Test public void readDataReturnFormatForFirstRead() { - EventStream eventStream = new EventStream(SCHEME_ID, VALUE, TIME_SCALE, - new long[0], new EventMessage[0]); - EventSampleStream sampleStream = new EventSampleStream(eventStream, FORMAT, false); + EventStream eventStream = + new EventStream(SCHEME_ID, VALUE, TIME_SCALE, new long[0], new EventMessage[0]); + // Make the event stream appendable so that the format is read. Otherwise, the format will be + // skipped and the end of input will be read. + EventSampleStream sampleStream = + new EventSampleStream(eventStream, FORMAT, /* eventStreamAppendable= */ true); int result = readData(sampleStream); assertThat(result).isEqualTo(C.RESULT_FORMAT_READ); @@ -78,8 +83,8 @@ public void readDataReturnFormatForFirstRead() { */ @Test public void readDataOutOfBoundReturnEndOfStreamAfterFormatForNonDynamicEventSampleStream() { - EventStream eventStream = new EventStream(SCHEME_ID, VALUE, TIME_SCALE, - new long[0], new EventMessage[0]); + EventStream eventStream = + new EventStream(SCHEME_ID, VALUE, TIME_SCALE, new long[0], new EventMessage[0]); EventSampleStream sampleStream = new EventSampleStream(eventStream, FORMAT, false); // first read - read format readData(sampleStream); @@ -95,8 +100,8 @@ public void readDataOutOfBoundReturnEndOfStreamAfterFormatForNonDynamicEventSamp */ @Test public void readDataOutOfBoundReturnEndOfStreamAfterFormatForDynamicEventSampleStream() { - EventStream eventStream = new EventStream(SCHEME_ID, VALUE, TIME_SCALE, - new long[0], new EventMessage[0]); + EventStream eventStream = + new EventStream(SCHEME_ID, VALUE, TIME_SCALE, new long[0], new EventMessage[0]); EventSampleStream sampleStream = new EventSampleStream(eventStream, FORMAT, true); // first read - read format readData(sampleStream); @@ -113,16 +118,20 @@ public void readDataOutOfBoundReturnEndOfStreamAfterFormatForDynamicEventSampleS public void readDataReturnDataAfterFormat() { long presentationTimeUs = 1000000; EventMessage eventMessage = newEventMessageWithId(1); - EventStream eventStream = new EventStream(SCHEME_ID, VALUE, TIME_SCALE, - new long[] {presentationTimeUs}, new EventMessage[] {eventMessage}); + EventStream eventStream = + new EventStream( + SCHEME_ID, + VALUE, + TIME_SCALE, + new long[] {presentationTimeUs}, + new EventMessage[] {eventMessage}); EventSampleStream sampleStream = new EventSampleStream(eventStream, FORMAT, false); // first read - read format readData(sampleStream); int result = readData(sampleStream); assertThat(result).isEqualTo(C.RESULT_BUFFER_READ); - assertThat(inputBuffer.data.array()) - .isEqualTo(getEncodedMessage(eventMessage)); + assertThat(inputBuffer.data.array()).isEqualTo(getEncodedMessage(eventMessage)); } /** @@ -136,9 +145,13 @@ public void skipDataThenReadDataReturnDataFromSkippedPosition() { long presentationTimeUs2 = 2000000; EventMessage eventMessage1 = newEventMessageWithId(1); EventMessage eventMessage2 = newEventMessageWithId(2); - EventStream eventStream = new EventStream(SCHEME_ID, VALUE, TIME_SCALE, - new long[] {presentationTimeUs1, presentationTimeUs2}, - new EventMessage[] {eventMessage1, eventMessage2}); + EventStream eventStream = + new EventStream( + SCHEME_ID, + VALUE, + TIME_SCALE, + new long[] {presentationTimeUs1, presentationTimeUs2}, + new EventMessage[] {eventMessage1, eventMessage2}); EventSampleStream sampleStream = new EventSampleStream(eventStream, FORMAT, false); // first read - read format readData(sampleStream); @@ -147,8 +160,7 @@ public void skipDataThenReadDataReturnDataFromSkippedPosition() { int result = readData(sampleStream); assertThat(skipped).isEqualTo(1); assertThat(result).isEqualTo(C.RESULT_BUFFER_READ); - assertThat(inputBuffer.data.array()) - .isEqualTo(getEncodedMessage(eventMessage2)); + assertThat(inputBuffer.data.array()).isEqualTo(getEncodedMessage(eventMessage2)); } /** @@ -162,9 +174,13 @@ public void seekToUsThenReadDataReturnDataFromSeekPosition() { long presentationTimeUs2 = 2000000; EventMessage eventMessage1 = newEventMessageWithId(1); EventMessage eventMessage2 = newEventMessageWithId(2); - EventStream eventStream = new EventStream(SCHEME_ID, VALUE, TIME_SCALE, - new long[] {presentationTimeUs1, presentationTimeUs2}, - new EventMessage[] {eventMessage1, eventMessage2}); + EventStream eventStream = + new EventStream( + SCHEME_ID, + VALUE, + TIME_SCALE, + new long[] {presentationTimeUs1, presentationTimeUs2}, + new EventMessage[] {eventMessage1, eventMessage2}); EventSampleStream sampleStream = new EventSampleStream(eventStream, FORMAT, false); // first read - read format readData(sampleStream); @@ -172,8 +188,7 @@ public void seekToUsThenReadDataReturnDataFromSeekPosition() { sampleStream.seekToUs(presentationTimeUs2); int result = readData(sampleStream); assertThat(result).isEqualTo(C.RESULT_BUFFER_READ); - assertThat(inputBuffer.data.array()) - .isEqualTo(getEncodedMessage(eventMessage2)); + assertThat(inputBuffer.data.array()).isEqualTo(getEncodedMessage(eventMessage2)); } /** @@ -190,12 +205,20 @@ public void updateEventStreamContinueToReadAfterLastReadSamplePresentationTime() EventMessage eventMessage1 = newEventMessageWithId(1); EventMessage eventMessage2 = newEventMessageWithId(2); EventMessage eventMessage3 = newEventMessageWithId(3); - EventStream eventStream1 = new EventStream(SCHEME_ID, VALUE, TIME_SCALE, - new long[] {presentationTimeUs1, presentationTimeUs2}, - new EventMessage[] {eventMessage1, eventMessage2}); - EventStream eventStream2 = new EventStream(SCHEME_ID, VALUE, TIME_SCALE, - new long[] {presentationTimeUs1, presentationTimeUs2, presentationTimeUs3}, - new EventMessage[] {eventMessage1, eventMessage2, eventMessage3}); + EventStream eventStream1 = + new EventStream( + SCHEME_ID, + VALUE, + TIME_SCALE, + new long[] {presentationTimeUs1, presentationTimeUs2}, + new EventMessage[] {eventMessage1, eventMessage2}); + EventStream eventStream2 = + new EventStream( + SCHEME_ID, + VALUE, + TIME_SCALE, + new long[] {presentationTimeUs1, presentationTimeUs2, presentationTimeUs3}, + new EventMessage[] {eventMessage1, eventMessage2, eventMessage3}); EventSampleStream sampleStream = new EventSampleStream(eventStream1, FORMAT, true); // first read - read format readData(sampleStream); @@ -206,8 +229,7 @@ public void updateEventStreamContinueToReadAfterLastReadSamplePresentationTime() sampleStream.updateEventStream(eventStream2, true); int result = readData(sampleStream); assertThat(result).isEqualTo(C.RESULT_BUFFER_READ); - assertThat(inputBuffer.data.array()) - .isEqualTo(getEncodedMessage(eventMessage3)); + assertThat(inputBuffer.data.array()).isEqualTo(getEncodedMessage(eventMessage3)); } /** @@ -224,12 +246,20 @@ public void skipDataThenUpdateStreamContinueToReadFromSkippedPosition() { EventMessage eventMessage1 = newEventMessageWithId(1); EventMessage eventMessage2 = newEventMessageWithId(2); EventMessage eventMessage3 = newEventMessageWithId(3); - EventStream eventStream1 = new EventStream(SCHEME_ID, VALUE, TIME_SCALE, - new long[] {presentationTimeUs1, presentationTimeUs2}, - new EventMessage[] {eventMessage1, eventMessage2}); - EventStream eventStream2 = new EventStream(SCHEME_ID, VALUE, TIME_SCALE, - new long[] {presentationTimeUs1, presentationTimeUs2, presentationTimeUs3}, - new EventMessage[] {eventMessage1, eventMessage2, eventMessage3}); + EventStream eventStream1 = + new EventStream( + SCHEME_ID, + VALUE, + TIME_SCALE, + new long[] {presentationTimeUs1, presentationTimeUs2}, + new EventMessage[] {eventMessage1, eventMessage2}); + EventStream eventStream2 = + new EventStream( + SCHEME_ID, + VALUE, + TIME_SCALE, + new long[] {presentationTimeUs1, presentationTimeUs2, presentationTimeUs3}, + new EventMessage[] {eventMessage1, eventMessage2, eventMessage3}); EventSampleStream sampleStream = new EventSampleStream(eventStream1, FORMAT, true); // first read - read format readData(sampleStream); @@ -238,8 +268,7 @@ public void skipDataThenUpdateStreamContinueToReadFromSkippedPosition() { sampleStream.updateEventStream(eventStream2, true); int result = readData(sampleStream); assertThat(result).isEqualTo(C.RESULT_BUFFER_READ); - assertThat(inputBuffer.data.array()) - .isEqualTo(getEncodedMessage(eventMessage3)); + assertThat(inputBuffer.data.array()).isEqualTo(getEncodedMessage(eventMessage3)); } /** @@ -257,12 +286,20 @@ public void skipDataThenUpdateStreamContinueToReadDoNotSkippedMoreThanAvailable( EventMessage eventMessage1 = newEventMessageWithId(1); EventMessage eventMessage2 = newEventMessageWithId(2); EventMessage eventMessage3 = newEventMessageWithId(3); - EventStream eventStream1 = new EventStream(SCHEME_ID, VALUE, TIME_SCALE, - new long[] {presentationTimeUs1}, - new EventMessage[] {eventMessage1}); - EventStream eventStream2 = new EventStream(SCHEME_ID, VALUE, TIME_SCALE, - new long[] {presentationTimeUs1, presentationTimeUs2, presentationTimeUs3}, - new EventMessage[] {eventMessage1, eventMessage2, eventMessage3}); + EventStream eventStream1 = + new EventStream( + SCHEME_ID, + VALUE, + TIME_SCALE, + new long[] {presentationTimeUs1}, + new EventMessage[] {eventMessage1}); + EventStream eventStream2 = + new EventStream( + SCHEME_ID, + VALUE, + TIME_SCALE, + new long[] {presentationTimeUs1, presentationTimeUs2, presentationTimeUs3}, + new EventMessage[] {eventMessage1, eventMessage2, eventMessage3}); EventSampleStream sampleStream = new EventSampleStream(eventStream1, FORMAT, true); // first read - read format readData(sampleStream); @@ -273,8 +310,7 @@ public void skipDataThenUpdateStreamContinueToReadDoNotSkippedMoreThanAvailable( sampleStream.updateEventStream(eventStream2, true); int result = readData(sampleStream); assertThat(result).isEqualTo(C.RESULT_BUFFER_READ); - assertThat(inputBuffer.data.array()) - .isEqualTo(getEncodedMessage(eventMessage2)); + assertThat(inputBuffer.data.array()).isEqualTo(getEncodedMessage(eventMessage2)); } /** @@ -291,12 +327,20 @@ public void seekToUsThenUpdateStreamContinueToReadFromSeekPosition() { EventMessage eventMessage1 = newEventMessageWithId(1); EventMessage eventMessage2 = newEventMessageWithId(2); EventMessage eventMessage3 = newEventMessageWithId(3); - EventStream eventStream1 = new EventStream(SCHEME_ID, VALUE, TIME_SCALE, - new long[] {presentationTimeUs1, presentationTimeUs2}, - new EventMessage[] {eventMessage1, eventMessage2}); - EventStream eventStream2 = new EventStream(SCHEME_ID, VALUE, TIME_SCALE, - new long[] {presentationTimeUs1, presentationTimeUs2, presentationTimeUs3}, - new EventMessage[] {eventMessage1, eventMessage2, eventMessage3}); + EventStream eventStream1 = + new EventStream( + SCHEME_ID, + VALUE, + TIME_SCALE, + new long[] {presentationTimeUs1, presentationTimeUs2}, + new EventMessage[] {eventMessage1, eventMessage2}); + EventStream eventStream2 = + new EventStream( + SCHEME_ID, + VALUE, + TIME_SCALE, + new long[] {presentationTimeUs1, presentationTimeUs2, presentationTimeUs3}, + new EventMessage[] {eventMessage1, eventMessage2, eventMessage3}); EventSampleStream sampleStream = new EventSampleStream(eventStream1, FORMAT, true); // first read - read format readData(sampleStream); @@ -305,8 +349,7 @@ public void seekToUsThenUpdateStreamContinueToReadFromSeekPosition() { sampleStream.updateEventStream(eventStream2, true); int result = readData(sampleStream); assertThat(result).isEqualTo(C.RESULT_BUFFER_READ); - assertThat(inputBuffer.data.array()) - .isEqualTo(getEncodedMessage(eventMessage2)); + assertThat(inputBuffer.data.array()).isEqualTo(getEncodedMessage(eventMessage2)); } /** @@ -323,12 +366,20 @@ public void seekToThenUpdateStreamContinueToReadFromSeekPositionEvenSeekMoreThan EventMessage eventMessage1 = newEventMessageWithId(1); EventMessage eventMessage2 = newEventMessageWithId(2); EventMessage eventMessage3 = newEventMessageWithId(3); - EventStream eventStream1 = new EventStream(SCHEME_ID, VALUE, TIME_SCALE, - new long[] {presentationTimeUs1}, - new EventMessage[] {eventMessage1}); - EventStream eventStream2 = new EventStream(SCHEME_ID, VALUE, TIME_SCALE, - new long[] {presentationTimeUs1, presentationTimeUs2, presentationTimeUs3}, - new EventMessage[] {eventMessage1, eventMessage2, eventMessage3}); + EventStream eventStream1 = + new EventStream( + SCHEME_ID, + VALUE, + TIME_SCALE, + new long[] {presentationTimeUs1}, + new EventMessage[] {eventMessage1}); + EventStream eventStream2 = + new EventStream( + SCHEME_ID, + VALUE, + TIME_SCALE, + new long[] {presentationTimeUs1, presentationTimeUs2, presentationTimeUs3}, + new EventMessage[] {eventMessage1, eventMessage2, eventMessage3}); EventSampleStream sampleStream = new EventSampleStream(eventStream1, FORMAT, true); // first read - read format readData(sampleStream); @@ -337,8 +388,7 @@ public void seekToThenUpdateStreamContinueToReadFromSeekPositionEvenSeekMoreThan sampleStream.updateEventStream(eventStream2, true); int result = readData(sampleStream); assertThat(result).isEqualTo(C.RESULT_BUFFER_READ); - assertThat(inputBuffer.data.array()) - .isEqualTo(getEncodedMessage(eventMessage3)); + assertThat(inputBuffer.data.array()).isEqualTo(getEncodedMessage(eventMessage3)); } private int readData(EventSampleStream sampleStream) { @@ -353,5 +403,4 @@ private EventMessage newEventMessageWithId(int id) { private byte[] getEncodedMessage(EventMessage eventMessage) { return eventMessageEncoder.encode(eventMessage); } - } diff --git a/library/dash/src/test/java/com/google/android/exoplayer2/e2etest/DashPlaybackTest.java b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/e2etest/DashPlaybackTest.java similarity index 95% rename from library/dash/src/test/java/com/google/android/exoplayer2/e2etest/DashPlaybackTest.java rename to library/dash/src/test/java/com/google/android/exoplayer2/source/dash/e2etest/DashPlaybackTest.java index 372fa076466..9014a8c40b6 100644 --- a/library/dash/src/test/java/com/google/android/exoplayer2/e2etest/DashPlaybackTest.java +++ b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/e2etest/DashPlaybackTest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.google.android.exoplayer2.e2etest; +package com.google.android.exoplayer2.source.dash.e2etest; import static com.google.android.exoplayer2.util.Assertions.checkNotNull; @@ -35,12 +35,11 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.robolectric.annotation.Config; +import org.robolectric.annotation.internal.DoNotInstrument; /** End-to-end tests using DASH samples. */ -// TODO(b/143232359): Remove once https://issuetracker.google.com/143232359 is resolved. -@Config(sdk = 29) @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class DashPlaybackTest { @Rule diff --git a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParserTest.java b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParserTest.java index 24ae834f33e..8c3ea0c1275 100644 --- a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParserTest.java +++ b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParserTest.java @@ -29,17 +29,20 @@ import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.Util; import com.google.common.base.Charsets; +import com.google.common.collect.ImmutableList; import java.io.IOException; import java.io.StringReader; import java.util.Collections; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserFactory; /** Unit tests for {@link DashManifestParser}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public class DashManifestParserTest { private static final String SAMPLE_MPD_LIVE = "media/mpd/sample_mpd_live"; @@ -53,6 +56,8 @@ public class DashManifestParserTest { private static final String SAMPLE_MPD_TRICK_PLAY = "media/mpd/sample_mpd_trick_play"; private static final String SAMPLE_MPD_AVAILABILITY_TIME_OFFSET_BASE_URL = "media/mpd/sample_mpd_availabilityTimeOffset_baseUrl"; + private static final String SAMPLE_MPD_MULTIPLE_BASE_URLS = + "media/mpd/sample_mpd_multiple_baseUrls"; private static final String SAMPLE_MPD_AVAILABILITY_TIME_OFFSET_SEGMENT_TEMPLATE = "media/mpd/sample_mpd_availabilityTimeOffset_segmentTemplate"; private static final String SAMPLE_MPD_AVAILABILITY_TIME_OFFSET_SEGMENT_LIST = @@ -103,10 +108,8 @@ public void parseMediaPresentationDescription_segmentTemplate() throws IOExcepti (Representation.MultiSegmentRepresentation) representation; long firstSegmentIndex = multiSegmentRepresentation.getFirstSegmentNum(); RangedUri uri = multiSegmentRepresentation.getSegmentUrl(firstSegmentIndex); - assertThat( - uri.resolveUriString(representation.baseUrl) - .contains("redirector.googlevideo.com")) - .isTrue(); + assertThat(uri.resolveUriString(representation.baseUrls.get(0).url)) + .contains("redirector.googlevideo.com"); } } } @@ -570,6 +573,85 @@ public void availabilityTimeOffset_dynamicManifest_valuesInSegmentList_setsCorre assertThat(getAvailabilityTimeOffsetUs(adaptationSets1.get(0))).isEqualTo(9_999_000); } + @Test + public void baseUrl_absoluteBaseUrls_usesClosestBaseUrl() throws IOException { + DashManifestParser parser = new DashManifestParser(); + DashManifest manifest = + parser.parse( + Uri.parse("https://example.com/test.mpd"), + TestUtil.getInputStream( + ApplicationProvider.getApplicationContext(), + SAMPLE_MPD_AVAILABILITY_TIME_OFFSET_BASE_URL)); + + List adaptationSets0 = manifest.getPeriod(0).adaptationSets; + assertThat(adaptationSets0.get(0).representations.get(0).baseUrls.get(0).serviceLocation) + .isEqualTo("period0"); + assertThat(adaptationSets0.get(0).representations.get(0).baseUrls.get(0).priority).isEqualTo(2); + assertThat(adaptationSets0.get(0).representations.get(0).baseUrls.get(0).weight).isEqualTo(20); + assertThat(adaptationSets0.get(1).representations.get(0).baseUrls.get(0).serviceLocation) + .isEqualTo("adaptationSet1"); + assertThat(adaptationSets0.get(1).representations.get(0).baseUrls.get(0).priority).isEqualTo(3); + assertThat(adaptationSets0.get(1).representations.get(0).baseUrls.get(0).weight).isEqualTo(30); + assertThat(adaptationSets0.get(2).representations.get(0).baseUrls.get(0).serviceLocation) + .isEqualTo("representation2"); + assertThat(adaptationSets0.get(2).representations.get(0).baseUrls.get(0).priority).isEqualTo(4); + assertThat(adaptationSets0.get(2).representations.get(0).baseUrls.get(0).weight).isEqualTo(40); + assertThat(adaptationSets0.get(3).representations.get(0).baseUrls.get(0).serviceLocation) + .isEqualTo("http://video-foo.com/baseUrl/adaptationSet3"); + assertThat(adaptationSets0.get(3).representations.get(0).baseUrls.get(0).priority).isEqualTo(1); + assertThat(adaptationSets0.get(3).representations.get(0).baseUrls.get(0).weight).isEqualTo(1); + assertThat(adaptationSets0.get(3).representations.get(0).baseUrls.get(0).url) + .isEqualTo("http://video-foo.com/baseUrl/representation3"); + } + + @Test + public void baseUrl_multipleBaseUrls_correctParsingAndUnfolding() throws IOException { + DashManifestParser parser = new DashManifestParser(); + DashManifest manifest = + parser.parse( + Uri.parse("https://example.com/test.mpd"), + TestUtil.getInputStream( + ApplicationProvider.getApplicationContext(), SAMPLE_MPD_MULTIPLE_BASE_URLS)); + + ImmutableList audioBaseUrls = + manifest.getPeriod(0).adaptationSets.get(0).representations.get(0).baseUrls; + assertThat(audioBaseUrls).hasSize(6); + assertThat(audioBaseUrls.get(0).url).endsWith("/baseUrl/a/media/audio"); + assertThat(audioBaseUrls.get(1).url).endsWith("/baseUrl/b/media/audio"); + assertThat(audioBaseUrls.get(2).url).endsWith("/baseUrl/c/media/audio"); + assertThat(audioBaseUrls.get(3).url).endsWith("/baseUrl/a/files/audio"); + assertThat(audioBaseUrls.get(4).url).endsWith("/baseUrl/b/files/audio"); + assertThat(audioBaseUrls.get(5).url).endsWith("/baseUrl/c/files/audio"); + assertThat(audioBaseUrls.get(0).serviceLocation).isEqualTo("a"); + assertThat(audioBaseUrls.get(1).serviceLocation).isEqualTo("b"); + assertThat(audioBaseUrls.get(2).serviceLocation).isEqualTo("c"); + assertThat(audioBaseUrls.get(3).serviceLocation).isEqualTo("a"); + assertThat(audioBaseUrls.get(4).serviceLocation).isEqualTo("b"); + assertThat(audioBaseUrls.get(5).serviceLocation).isEqualTo("c"); + ImmutableList videoBaseUrls = + manifest.getPeriod(0).adaptationSets.get(1).representations.get(0).baseUrls; + assertThat(videoBaseUrls).hasSize(7); + assertThat(videoBaseUrls.get(0).url).endsWith("/baseUrl/a/media/video"); + assertThat(videoBaseUrls.get(1).url).endsWith("/baseUrl/b/media/video"); + assertThat(videoBaseUrls.get(2).url).endsWith("/baseUrl/c/media/video"); + assertThat(videoBaseUrls.get(3).url).endsWith("/baseUrl/a/files/video"); + assertThat(videoBaseUrls.get(4).url).endsWith("/baseUrl/b/files/video"); + assertThat(videoBaseUrls.get(5).url).endsWith("/baseUrl/c/files/video"); + assertThat(videoBaseUrls.get(6).url).endsWith("/baseUrl/d/alternative/"); + assertThat(videoBaseUrls.get(0).serviceLocation).isEqualTo("a"); + assertThat(videoBaseUrls.get(1).serviceLocation).isEqualTo("b"); + assertThat(videoBaseUrls.get(2).serviceLocation).isEqualTo("c"); + assertThat(videoBaseUrls.get(3).serviceLocation).isEqualTo("a"); + assertThat(videoBaseUrls.get(4).serviceLocation).isEqualTo("b"); + assertThat(videoBaseUrls.get(5).serviceLocation).isEqualTo("c"); + assertThat(videoBaseUrls.get(6).serviceLocation).isEqualTo("d"); + ImmutableList textBaseUrls = + manifest.getPeriod(0).adaptationSets.get(2).representations.get(0).baseUrls; + assertThat(textBaseUrls).hasSize(1); + assertThat(textBaseUrls.get(0).url).endsWith("/baseUrl/e/text/"); + assertThat(textBaseUrls.get(0).serviceLocation).isEqualTo("e"); + } + @Test public void serviceDescriptionElement_allValuesSet() throws IOException { DashManifestParser parser = new DashManifestParser(); diff --git a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestTest.java b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestTest.java index 7b3b3cab512..0b3a3efbbb5 100644 --- a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestTest.java +++ b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestTest.java @@ -23,15 +23,18 @@ import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.offline.StreamKey; import com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase; +import com.google.common.collect.ImmutableList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Random; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit tests for {@link DashManifest}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public class DashManifestTest { private static final UtcTimingElement UTC_TIMING = new UtcTimingElement("", ""); @@ -229,7 +232,11 @@ private static Representation[][][] newRepresentations( } private static Representation newRepresentation() { - return Representation.newInstance(/* revisionId= */ 0, FORMAT, /* baseUrl= */ "", SEGMENT_BASE); + return Representation.newInstance( + /* revisionId= */ 0, + FORMAT, + /* baseUrls= */ ImmutableList.of(new BaseUrl("")), + SEGMENT_BASE); } private static DashManifest newDashManifest( diff --git a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/RangedUriTest.java b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/RangedUriTest.java index 44af227d96b..486ab08cd17 100644 --- a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/RangedUriTest.java +++ b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/RangedUriTest.java @@ -21,9 +21,11 @@ import com.google.android.exoplayer2.C; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link RangedUri}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public class RangedUriTest { private static final String BASE_URI = "http://www.test.com/"; diff --git a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/SegmentBaseTest.java b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/SegmentBaseTest.java index 91ddfbbde9a..49346c4f98d 100644 --- a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/SegmentBaseTest.java +++ b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/SegmentBaseTest.java @@ -21,9 +21,11 @@ import com.google.android.exoplayer2.C; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link SegmentBase}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class SegmentBaseTest { @Test diff --git a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/UrlTemplateTest.java b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/UrlTemplateTest.java index 6736840d829..057844d848a 100644 --- a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/UrlTemplateTest.java +++ b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/UrlTemplateTest.java @@ -21,9 +21,11 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link UrlTemplate}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public class UrlTemplateTest { @Test diff --git a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DashDownloaderTest.java b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DashDownloaderTest.java index d835b857258..e47137baf97 100644 --- a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DashDownloaderTest.java +++ b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DashDownloaderTest.java @@ -57,9 +57,11 @@ import org.junit.runner.RunWith; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit tests for {@link DashDownloader}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public class DashDownloaderTest { private SimpleCache cache; diff --git a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadHelperTest.java b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadHelperTest.java index bfc11cb47ae..b7323c49a37 100644 --- a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadHelperTest.java +++ b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadHelperTest.java @@ -25,9 +25,11 @@ import com.google.android.exoplayer2.util.MimeTypes; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test to verify creation of a DASH {@link DownloadHelper}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class DownloadHelperTest { @Test diff --git a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadManagerDashTest.java b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadManagerDashTest.java index 6bdc84438b9..29102dfe3e3 100644 --- a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadManagerDashTest.java +++ b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadManagerDashTest.java @@ -55,10 +55,12 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.internal.DoNotInstrument; import org.robolectric.shadows.ShadowLog; /** Tests {@link DownloadManager}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public class DownloadManagerDashTest { private static final int ASSERT_TRUE_TIMEOUT_MS = 5000; diff --git a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadServiceDashTest.java b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadServiceDashTest.java index 98a7f6e8873..e62a644af54 100644 --- a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadServiceDashTest.java +++ b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadServiceDashTest.java @@ -57,9 +57,11 @@ import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit tests for {@link DownloadService}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public class DownloadServiceDashTest { private SimpleCache cache; diff --git a/library/extractor/README.md b/library/extractor/README.md index 28e0ccdc0ac..fa2a23ee206 100644 --- a/library/extractor/README.md +++ b/library/extractor/README.md @@ -1,11 +1,10 @@ -# ExoPlayer extractor library module # +# ExoPlayer extractor library module Provides media container extractors. -## Links ## +## Links -* [Javadoc][]: Classes matching `com.google.android.exoplayer2.extractor.*` - belong to this module. +* [Javadoc][]: Classes matching `com.google.android.exoplayer2.extractor.*` + belong to this module. [Javadoc]: https://exoplayer.dev/doc/reference/index.html - diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/CeaUtil.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/CeaUtil.java index 525b335f130..caf72df415b 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/CeaUtil.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/CeaUtil.java @@ -133,5 +133,4 @@ private static int readNon255TerminatedValue(ParsableByteArray buffer) { } private CeaUtil() {} - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ChunkIndex.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ChunkIndex.java index 3a783e4df9b..8291ed1ea41 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ChunkIndex.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ChunkIndex.java @@ -21,29 +21,19 @@ /** Defines chunks of samples within a media stream. */ public final class ChunkIndex implements SeekMap { - /** - * The number of chunks. - */ + /** The number of chunks. */ public final int length; - /** - * The chunk sizes, in bytes. - */ + /** The chunk sizes, in bytes. */ public final int[] sizes; - /** - * The chunk byte offsets. - */ + /** The chunk byte offsets. */ public final long[] offsets; - /** - * The chunk durations, in microseconds. - */ + /** The chunk durations, in microseconds. */ public final long[] durationsUs; - /** - * The start time of each chunk, in microseconds. - */ + /** The start time of each chunk, in microseconds. */ public final long[] timesUs; private final long durationUs; diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/DefaultExtractorInput.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/DefaultExtractorInput.java index 38844f61c70..e04307bad75 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/DefaultExtractorInput.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/DefaultExtractorInput.java @@ -56,12 +56,12 @@ public DefaultExtractorInput(DataReader dataReader, long position, long length) } @Override - public int read(byte[] target, int offset, int length) throws IOException { - int bytesRead = readFromPeekBuffer(target, offset, length); + public int read(byte[] buffer, int offset, int length) throws IOException { + int bytesRead = readFromPeekBuffer(buffer, offset, length); if (bytesRead == 0) { bytesRead = readFromUpstream( - target, offset, length, /* bytesAlreadyRead= */ 0, /* allowEndOfInput= */ true); + buffer, offset, length, /* bytesAlreadyRead= */ 0, /* allowEndOfInput= */ true); } commitBytesRead(bytesRead); return bytesRead; @@ -205,8 +205,11 @@ public void setRetryPosition(long position, E e) throws E private void ensureSpaceForPeek(int length) { int requiredLength = peekBufferPosition + length; if (requiredLength > peekBuffer.length) { - int newPeekCapacity = Util.constrainValue(peekBuffer.length * 2, - requiredLength + PEEK_MIN_FREE_SPACE_AFTER_RESIZE, requiredLength + PEEK_MAX_FREE_SPACE); + int newPeekCapacity = + Util.constrainValue( + peekBuffer.length * 2, + requiredLength + PEEK_MIN_FREE_SPACE_AFTER_RESIZE, + requiredLength + PEEK_MAX_FREE_SPACE); peekBuffer = Arrays.copyOf(peekBuffer, newPeekCapacity); } } @@ -300,5 +303,4 @@ private void commitBytesRead(int bytesRead) { position += bytesRead; } } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/DefaultExtractorsFactory.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/DefaultExtractorsFactory.java index ff887000a3d..0cbde6ab864 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/DefaultExtractorsFactory.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/DefaultExtractorsFactory.java @@ -103,8 +103,7 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory { static { @Nullable Constructor flacExtensionExtractorConstructor = null; try { - // LINT.IfChange - @SuppressWarnings("nullness:argument.type.incompatible") + @SuppressWarnings("nullness:argument") boolean isFlacNativeLibraryAvailable = Boolean.TRUE.equals( Class.forName("com.google.android.exoplayer2.ext.flac.FlacLibrary") @@ -116,7 +115,6 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory { .asSubclass(Extractor.class) .getConstructor(int.class); } - // LINT.ThenChange(../../../../../../../../proguard-rules.txt) } catch (ClassNotFoundException e) { // Expected if the app was built without the FLAC extension. } catch (Exception e) { diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/Extractor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/Extractor.java index 63870282b5c..21fb7f12697 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/Extractor.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/Extractor.java @@ -38,8 +38,8 @@ public interface Extractor { */ int RESULT_SEEK = 1; /** - * Returned by {@link #read(ExtractorInput, PositionHolder)} if the end of the - * {@link ExtractorInput} was reached. Equal to {@link C#RESULT_END_OF_INPUT}. + * Returned by {@link #read(ExtractorInput, PositionHolder)} if the end of the {@link + * ExtractorInput} was reached. Equal to {@link C#RESULT_END_OF_INPUT}. */ int RESULT_END_OF_INPUT = C.RESULT_END_OF_INPUT; @@ -101,8 +101,8 @@ public interface Extractor { /** * Notifies the extractor that a seek has occurred. - *

      - * Following a call to this method, the {@link ExtractorInput} passed to the next invocation of + * + *

      Following a call to this method, the {@link ExtractorInput} passed to the next invocation of * {@link #read(ExtractorInput, PositionHolder)} is required to provide data starting from {@code * position} in the stream. Valid random access positions are the start of the stream and * positions that can be obtained from any {@link SeekMap} passed to the {@link ExtractorOutput}. @@ -112,9 +112,6 @@ public interface Extractor { */ void seek(long position, long timeUs); - /** - * Releases all kept resources. - */ + /** Releases all kept resources. */ void release(); - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ExtractorInput.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ExtractorInput.java index 6799ca6de16..3dc9e0b15b1 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ExtractorInput.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ExtractorInput.java @@ -34,7 +34,7 @@ * wants to read an entire block/frame/header of known length. *

    * - *

    {@link InputStream}-like methods

    + *

    {@link InputStream}-like methods

    * *

    The {@code read()/peek()} and {@code skip()} methods provide {@link InputStream}-like * byte-level access operations. The {@code length} parameter is a maximum, and each method returns @@ -42,7 +42,7 @@ * the input was reached, or the method was interrupted, or the operation was aborted early for * another reason. * - *

    Block-based methods

    + *

    Block-based methods

    * *

    The {@code read/skip/peekFully()} and {@code advancePeekPosition()} methods assume the user * wants to read an entire block/frame/header of known length. @@ -72,14 +72,14 @@ public interface ExtractorInput extends DataReader { *

    This method blocks until at least one byte of data can be read, the end of the input is * detected, or an exception is thrown. * - * @param target A target array into which data should be written. + * @param buffer A target array into which data should be written. * @param offset The offset into the target array at which to write. * @param length The maximum number of bytes to read from the input. * @return The number of bytes read, or {@link C#RESULT_END_OF_INPUT} if the input has ended. * @throws IOException If an error occurs reading from the input. */ @Override - int read(byte[] target, int offset, int length) throws IOException; + int read(byte[] buffer, int offset, int length) throws IOException; /** * Like {@link #read(byte[], int, int)}, but reads the requested {@code length} in full. @@ -230,9 +230,7 @@ boolean peekFully(byte[] target, int offset, int length, boolean allowEndOfInput */ void advancePeekPosition(int length) throws IOException; - /** - * Resets the peek position to equal the current read position. - */ + /** Resets the peek position to equal the current read position. */ void resetPeekPosition(); /** @@ -266,5 +264,4 @@ boolean peekFully(byte[] target, int offset, int length, boolean allowEndOfInput * @throws E The given {@link Throwable} object. */ void setRetryPosition(long position, E e) throws E; - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ExtractorOutput.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ExtractorOutput.java index 09f5fa493dc..bffda30d0bf 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ExtractorOutput.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ExtractorOutput.java @@ -66,5 +66,4 @@ public void seekMap(SeekMap seekMap) { * @param seekMap The extracted {@link SeekMap}. */ void seekMap(SeekMap seekMap); - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ExtractorUtil.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ExtractorUtil.java index 3eca5c776bd..54cc61f2ef8 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ExtractorUtil.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ExtractorUtil.java @@ -15,13 +15,28 @@ */ package com.google.android.exoplayer2.extractor; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.ParserException; import java.io.EOFException; import java.io.IOException; +import org.checkerframework.dataflow.qual.Pure; /** Extractor related utility methods. */ public final class ExtractorUtil { + /** + * If {@code expression} is false, throws a {@link ParserException#createForMalformedContainer + * container malformed ParserException} with the given message. Otherwise, does nothing. + */ + @Pure + public static void checkContainerInput(boolean expression, @Nullable String message) + throws ParserException { + if (!expression) { + throw ParserException.createForMalformedContainer(message, /* cause= */ null); + } + } + /** * Peeks {@code length} bytes from the input peek position, or all the bytes to the end of the * input if there was less than {@code length} bytes left. diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/FlacFrameReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/FlacFrameReader.java index fc1b1213260..846dd05f14c 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/FlacFrameReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/FlacFrameReader.java @@ -153,7 +153,7 @@ public static long getFirstSampleNumber( SampleNumberHolder sampleNumberHolder = new SampleNumberHolder(); if (!checkAndReadFirstSampleNumber( scratch, flacStreamMetadata, isBlockSizeVariable, sampleNumberHolder)) { - throw new ParserException(); + throw ParserException.createForMalformedContainer(/* message= */ null, /* cause= */ null); } return sampleNumberHolder.sampleNumber; diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/FlacMetadataReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/FlacMetadataReader.java index 922ef0f3da2..01d2def12dc 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/FlacMetadataReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/FlacMetadataReader.java @@ -120,7 +120,8 @@ public static void readStreamMarker(ExtractorInput input) throws IOException { ParsableByteArray scratch = new ParsableByteArray(FlacConstants.STREAM_MARKER_SIZE); input.readFully(scratch.getData(), 0, FlacConstants.STREAM_MARKER_SIZE); if (scratch.readUnsignedInt() != STREAM_MARKER) { - throw new ParserException("Failed to read FLAC stream marker."); + throw ParserException.createForMalformedContainer( + "Failed to read FLAC stream marker.", /* cause= */ null); } } @@ -234,7 +235,8 @@ public static int getFrameStartMarker(ExtractorInput input) throws IOException { int syncCode = frameStartMarker >> 2; if (syncCode != SYNC_CODE) { input.resetPeekPosition(); - throw new ParserException("First frame does not start with sync code."); + throw ParserException.createForMalformedContainer( + "First frame does not start with sync code.", /* cause= */ null); } input.resetPeekPosition(); diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ForwardingExtractorInput.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ForwardingExtractorInput.java index 2a9726fac2e..c70202d1376 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ForwardingExtractorInput.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ForwardingExtractorInput.java @@ -27,8 +27,8 @@ public ForwardingExtractorInput(ExtractorInput input) { } @Override - public int read(byte[] target, int offset, int length) throws IOException { - return input.read(target, offset, length); + public int read(byte[] buffer, int offset, int length) throws IOException { + return input.read(buffer, offset, length); } @Override diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/GaplessInfoHolder.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/GaplessInfoHolder.java index 09d2fd1f882..0bf6b146d53 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/GaplessInfoHolder.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/GaplessInfoHolder.java @@ -33,20 +33,18 @@ public final class GaplessInfoHolder { Pattern.compile("^ [0-9a-fA-F]{8} ([0-9a-fA-F]{8}) ([0-9a-fA-F]{8})"); /** - * The number of samples to trim from the start of the decoded audio stream, or - * {@link Format#NO_VALUE} if not set. + * The number of samples to trim from the start of the decoded audio stream, or {@link + * Format#NO_VALUE} if not set. */ public int encoderDelay; /** - * The number of samples to trim from the end of the decoded audio stream, or - * {@link Format#NO_VALUE} if not set. + * The number of samples to trim from the end of the decoded audio stream, or {@link + * Format#NO_VALUE} if not set. */ public int encoderPadding; - /** - * Creates a new holder for gapless playback information. - */ + /** Creates a new holder for gapless playback information. */ public GaplessInfoHolder() { encoderDelay = Format.NO_VALUE; encoderPadding = Format.NO_VALUE; @@ -121,11 +119,8 @@ private boolean setFromComment(String data) { return false; } - /** - * Returns whether {@link #encoderDelay} and {@link #encoderPadding} have been set. - */ + /** Returns whether {@link #encoderDelay} and {@link #encoderPadding} have been set. */ public boolean hasGaplessInfo() { return encoderDelay != Format.NO_VALUE && encoderPadding != Format.NO_VALUE; } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/PositionHolder.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/PositionHolder.java index e4ac523350c..94ca7282d34 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/PositionHolder.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/PositionHolder.java @@ -18,9 +18,6 @@ /** Holds a position in the stream. */ public final class PositionHolder { - /** - * The held position. - */ + /** The held position. */ public long position; - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/TrackOutput.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/TrackOutput.java index a461f4b7001..1a58d232f08 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/TrackOutput.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/TrackOutput.java @@ -31,19 +31,13 @@ /** Receives track level data extracted by an {@link Extractor}. */ public interface TrackOutput { - /** - * Holds data required to decrypt a sample. - */ + /** Holds data required to decrypt a sample. */ final class CryptoData { - /** - * The encryption mode used for the sample. - */ + /** The encryption mode used for the sample. */ @C.CryptoMode public final int cryptoMode; - /** - * The encryption key associated with the sample. Its contents must not be modified. - */ + /** The encryption key associated with the sample. Its contents must not be modified. */ public final byte[] encryptionKey; /** @@ -53,8 +47,7 @@ final class CryptoData { public final int encryptedBlocks; /** - * The number of clear blocks in the encryption pattern, 0 if pattern encryption does not - * apply. + * The number of clear blocks in the encryption pattern, 0 if pattern encryption does not apply. */ public final int clearBlocks; @@ -64,8 +57,8 @@ final class CryptoData { * @param encryptedBlocks See {@link #encryptedBlocks}. * @param clearBlocks See {@link #clearBlocks}. */ - public CryptoData(@C.CryptoMode int cryptoMode, byte[] encryptionKey, int encryptedBlocks, - int clearBlocks) { + public CryptoData( + @C.CryptoMode int cryptoMode, byte[] encryptionKey, int encryptedBlocks, int clearBlocks) { this.cryptoMode = cryptoMode; this.encryptionKey = encryptionKey; this.encryptedBlocks = encryptedBlocks; @@ -81,8 +74,10 @@ public boolean equals(@Nullable Object obj) { return false; } CryptoData other = (CryptoData) obj; - return cryptoMode == other.cryptoMode && encryptedBlocks == other.encryptedBlocks - && clearBlocks == other.clearBlocks && Arrays.equals(encryptionKey, other.encryptionKey); + return cryptoMode == other.cryptoMode + && encryptedBlocks == other.encryptedBlocks + && clearBlocks == other.clearBlocks + && Arrays.equals(encryptionKey, other.encryptionKey); } @Override @@ -93,7 +88,6 @@ public int hashCode() { result = 31 * result + clearBlocks; return result; } - } /** Defines the part of the sample data to which a call to {@link #sampleData} corresponds. */ @@ -204,12 +198,8 @@ int sampleData( * @param offset The number of bytes that have been passed to {@link #sampleData(DataReader, int, * boolean)} or {@link #sampleData(ParsableByteArray, int)} since the last byte belonging to * the sample whose metadata is being passed. - * @param encryptionData The encryption data required to decrypt the sample. May be null. + * @param cryptoData The encryption data required to decrypt the sample. May be null. */ void sampleMetadata( - long timeUs, - @C.BufferFlags int flags, - int size, - int offset, - @Nullable CryptoData encryptionData); + long timeUs, @C.BufferFlags int flags, int size, int offset, @Nullable CryptoData cryptoData); } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/VorbisBitArray.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/VorbisBitArray.java index 7ec9c93832f..56f419a1847 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/VorbisBitArray.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/VorbisBitArray.java @@ -43,9 +43,7 @@ public VorbisBitArray(byte[] data) { byteLimit = data.length; } - /** - * Resets the reading position to zero. - */ + /** Resets the reading position to zero. */ public void reset() { byteOffset = 0; bitOffset = 0; @@ -97,9 +95,7 @@ public void skipBits(int numBits) { assertValidOffset(); } - /** - * Returns the reading position in bits. - */ + /** Returns the reading position in bits. */ public int getPosition() { return byteOffset * 8 + bitOffset; } @@ -115,17 +111,14 @@ public void setPosition(int position) { assertValidOffset(); } - /** - * Returns the number of remaining bits. - */ + /** Returns the number of remaining bits. */ public int bitsLeft() { return (byteLimit - byteOffset) * 8 - bitOffset; } private void assertValidOffset() { // It is fine for position to be at the end of the array, but no further. - Assertions.checkState(byteOffset >= 0 - && (byteOffset < byteLimit || (byteOffset == byteLimit && bitOffset == 0))); + Assertions.checkState( + byteOffset >= 0 && (byteOffset < byteLimit || (byteOffset == byteLimit && bitOffset == 0))); } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/VorbisUtil.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/VorbisUtil.java index ede2ab39e99..5fbd0e4ae4a 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/VorbisUtil.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/VorbisUtil.java @@ -124,8 +124,8 @@ public Mode(boolean blockFlag, int windowType, int transformType, int mapping) { /** * Returns ilog(x), which is the index of the highest set bit in {@code x}. * - * @see - * Vorbis spec + * @see Vorbis + * spec * @param x the value of which the ilog should be calculated. * @return ilog(x) */ @@ -241,7 +241,8 @@ public static CommentHeader readVorbisCommentHeader( length += comments[i].length(); } if (hasFramingBit && (headerData.readUnsignedByte() & 0x01) == 0) { - throw new ParserException("framing bit expected to be set"); + throw ParserException.createForMalformedContainer( + "framing bit expected to be set", /* cause= */ null); } length += 1; return new CommentHeader(vendor, comments, length); @@ -263,7 +264,8 @@ public static boolean verifyVorbisHeaderCapturePattern( if (quiet) { return false; } else { - throw new ParserException("too short header: " + header.bytesLeft()); + throw ParserException.createForMalformedContainer( + "too short header: " + header.bytesLeft(), /* cause= */ null); } } @@ -271,7 +273,8 @@ public static boolean verifyVorbisHeaderCapturePattern( if (quiet) { return false; } else { - throw new ParserException("expected header type " + Integer.toHexString(headerType)); + throw ParserException.createForMalformedContainer( + "expected header type " + Integer.toHexString(headerType), /* cause= */ null); } } @@ -284,7 +287,8 @@ public static boolean verifyVorbisHeaderCapturePattern( if (quiet) { return false; } else { - throw new ParserException("expected characters 'vorbis'"); + throw ParserException.createForMalformedContainer( + "expected characters 'vorbis'", /* cause= */ null); } } return true; @@ -319,7 +323,8 @@ public static Mode[] readVorbisModes(ParsableByteArray headerData, int channels) int timeCount = bitArray.readBits(6) + 1; for (int i = 0; i < timeCount; i++) { if (bitArray.readBits(16) != 0x00) { - throw new ParserException("placeholder of time domain transforms not zeroed out"); + throw ParserException.createForMalformedContainer( + "placeholder of time domain transforms not zeroed out", /* cause= */ null); } } readFloors(bitArray); @@ -328,7 +333,8 @@ public static Mode[] readVorbisModes(ParsableByteArray headerData, int channels) Mode[] modes = readModes(bitArray); if (!bitArray.readBit()) { - throw new ParserException("framing bit after modes not set as expected"); + throw ParserException.createForMalformedContainer( + "framing bit after modes not set as expected", /* cause= */ null); } return modes; } @@ -346,8 +352,7 @@ private static Mode[] readModes(VorbisBitArray bitArray) { return modes; } - private static void readMappings(int channels, VorbisBitArray bitArray) - throws ParserException { + private static void readMappings(int channels, VorbisBitArray bitArray) throws ParserException { int mappingsCount = bitArray.readBits(6) + 1; for (int i = 0; i < mappingsCount; i++) { int mappingType = bitArray.readBits(16); @@ -372,7 +377,8 @@ private static void readMappings(int channels, VorbisBitArray bitArray) couplingSteps = 0; }*/ if (bitArray.readBits(2) != 0x00) { - throw new ParserException("to reserved bits must be zero after mapping coupling steps"); + throw ParserException.createForMalformedContainer( + "to reserved bits must be zero after mapping coupling steps", /* cause= */ null); } if (submaps > 1) { for (int j = 0; j < channels; j++) { @@ -392,7 +398,8 @@ private static void readResidues(VorbisBitArray bitArray) throws ParserException for (int i = 0; i < residueCount; i++) { int residueType = bitArray.readBits(16); if (residueType > 2) { - throw new ParserException("residueType greater than 2 is not decodable"); + throw ParserException.createForMalformedContainer( + "residueType greater than 2 is not decodable", /* cause= */ null); } else { bitArray.skipBits(24); // begin bitArray.skipBits(24); // end @@ -425,7 +432,7 @@ private static void readFloors(VorbisBitArray bitArray) throws ParserException { int floorType = bitArray.readBits(16); switch (floorType) { case 0: - bitArray.skipBits(8); //order + bitArray.skipBits(8); // order bitArray.skipBits(16); // rate bitArray.skipBits(16); // barkMapSize bitArray.skipBits(6); // amplitudeBits @@ -468,15 +475,17 @@ private static void readFloors(VorbisBitArray bitArray) throws ParserException { } break; default: - throw new ParserException("floor type greater than 1 not decodable: " + floorType); + throw ParserException.createForMalformedContainer( + "floor type greater than 1 not decodable: " + floorType, /* cause= */ null); } } } private static CodeBook readBook(VorbisBitArray bitArray) throws ParserException { if (bitArray.readBits(24) != 0x564342) { - throw new ParserException("expected code book to start with [0x56, 0x43, 0x42] at " - + bitArray.getPosition()); + throw ParserException.createForMalformedContainer( + "expected code book to start with [0x56, 0x43, 0x42] at " + bitArray.getPosition(), + /* cause= */ null); } int dimensions = bitArray.readBits(16); int entries = bitArray.readBits(24); @@ -498,7 +507,7 @@ private static CodeBook readBook(VorbisBitArray bitArray) throws ParserException } } else { int length = bitArray.readBits(5) + 1; - for (int i = 0; i < lengthMap.length;) { + for (int i = 0; i < lengthMap.length; ) { int num = bitArray.readBits(iLog(entries - i)); for (int j = 0; j < num && i < lengthMap.length; i++, j++) { lengthMap[i] = length; @@ -509,7 +518,8 @@ private static CodeBook readBook(VorbisBitArray bitArray) throws ParserException int lookupType = bitArray.readBits(4); if (lookupType > 2) { - throw new ParserException("lookup type greater than 2 not decodable: " + lookupType); + throw ParserException.createForMalformedContainer( + "lookup type greater than 2 not decodable: " + lookupType, /* cause= */ null); } else if (lookupType == 1 || lookupType == 2) { bitArray.skipBits(32); // minimumValue bitArray.skipBits(32); // deltaValue @@ -550,14 +560,13 @@ private static final class CodeBook { public final int lookupType; public final boolean isOrdered; - public CodeBook(int dimensions, int entries, long[] lengthMap, int lookupType, - boolean isOrdered) { + public CodeBook( + int dimensions, int entries, long[] lengthMap, int lookupType, boolean isOrdered) { this.dimensions = dimensions; this.entries = entries; this.lengthMap = lengthMap; this.lookupType = lookupType; this.isOrdered = isOrdered; } - } } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/amr/AmrExtractor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/amr/AmrExtractor.java index 4d8ef184481..92821daf136 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/amr/AmrExtractor.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/amr/AmrExtractor.java @@ -165,10 +165,10 @@ public boolean sniff(ExtractorInput input) throws IOException { } @Override - public void init(ExtractorOutput extractorOutput) { - this.extractorOutput = extractorOutput; - trackOutput = extractorOutput.track(/* id= */ 0, C.TRACK_TYPE_AUDIO); - extractorOutput.endTracks(); + public void init(ExtractorOutput output) { + this.extractorOutput = output; + trackOutput = output.track(/* id= */ 0, C.TRACK_TYPE_AUDIO); + output.endTracks(); } @Override @@ -176,7 +176,8 @@ public int read(ExtractorInput input, PositionHolder seekPosition) throws IOExce assertInitialized(); if (input.getPosition() == 0) { if (!readAmrHeader(input)) { - throw new ParserException("Could not find AMR header."); + throw ParserException.createForMalformedContainer( + "Could not find AMR header.", /* cause= */ null); } } maybeOutputFormat(); @@ -311,7 +312,8 @@ private int peekNextSampleSize(ExtractorInput extractorInput) throws IOException if ((frameHeader & 0x83) > 0) { // The padding bits are at bit-1 positions in the following pattern: 1000 0011 // Padding bits must be 0. - throw new ParserException("Invalid padding bits for frame header " + frameHeader); + throw ParserException.createForMalformedContainer( + "Invalid padding bits for frame header " + frameHeader, /* cause= */ null); } int frameType = (frameHeader >> 3) & 0x0f; @@ -320,8 +322,9 @@ private int peekNextSampleSize(ExtractorInput extractorInput) throws IOException private int getFrameSizeInBytes(int frameType) throws ParserException { if (!isValidFrameType(frameType)) { - throw new ParserException( - "Illegal AMR " + (isWideBand ? "WB" : "NB") + " frame type " + frameType); + throw ParserException.createForMalformedContainer( + "Illegal AMR " + (isWideBand ? "WB" : "NB") + " frame type " + frameType, + /* cause= */ null); } return isWideBand ? frameSizeBytesByTypeWb[frameType] : frameSizeBytesByTypeNb[frameType]; diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flac/FlacExtractor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flac/FlacExtractor.java index d6eb4772c4f..2b7c474b010 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flac/FlacExtractor.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flac/FlacExtractor.java @@ -54,7 +54,6 @@ public final class FlacExtractor implements Extractor { /** Factory for {@link FlacExtractor} instances. */ public static final ExtractorsFactory FACTORY = () -> new Extractor[] {new FlacExtractor()}; - // LINT.IfChange /* * Flags in the two FLAC extractors should be kept in sync. If we ever change this then * DefaultExtractorsFactory will need modifying, because it currently assumes this is the case. @@ -75,7 +74,6 @@ public final class FlacExtractor implements Extractor { * required. */ public static final int FLAG_DISABLE_ID3_METADATA = 1; - // LINT.ThenChange(../../../../../../../../../../decoder_flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java) /** Parser state. */ @Documented diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flv/AudioTagPayloadReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flv/AudioTagPayloadReader.java index 0ca65e4de53..124d62dd404 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flv/AudioTagPayloadReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flv/AudioTagPayloadReader.java @@ -24,9 +24,7 @@ import com.google.android.exoplayer2.util.ParsableByteArray; import java.util.Collections; -/** - * Parses audio tags from an FLV stream and extracts AAC frames. - */ +/** Parses audio tags from an FLV stream and extracts AAC frames. */ /* package */ final class AudioTagPayloadReader extends TagPayloadReader { private static final int AUDIO_FORMAT_MP3 = 2; diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flv/FlvExtractor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flv/FlvExtractor.java index 2fdaf7dc468..ffb85d07f05 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flv/FlvExtractor.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flv/FlvExtractor.java @@ -198,12 +198,12 @@ private boolean readFlvHeader(ExtractorInput input) throws IOException { boolean hasAudio = (flags & 0x04) != 0; boolean hasVideo = (flags & 0x01) != 0; if (hasAudio && audioReader == null) { - audioReader = new AudioTagPayloadReader( - extractorOutput.track(TAG_TYPE_AUDIO, C.TRACK_TYPE_AUDIO)); + audioReader = + new AudioTagPayloadReader(extractorOutput.track(TAG_TYPE_AUDIO, C.TRACK_TYPE_AUDIO)); } if (hasVideo && videoReader == null) { - videoReader = new VideoTagPayloadReader( - extractorOutput.track(TAG_TYPE_VIDEO, C.TRACK_TYPE_VIDEO)); + videoReader = + new VideoTagPayloadReader(extractorOutput.track(TAG_TYPE_VIDEO, C.TRACK_TYPE_VIDEO)); } extractorOutput.endTracks(); diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flv/ScriptTagPayloadReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flv/ScriptTagPayloadReader.java index f0b4efb1063..696b38c8a5f 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flv/ScriptTagPayloadReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flv/ScriptTagPayloadReader.java @@ -25,9 +25,7 @@ import java.util.List; import java.util.Map; -/** - * Parses Script Data tags from an FLV stream and extracts metadata information. - */ +/** Parses Script Data tags from an FLV stream and extracts metadata information. */ /* package */ final class ScriptTagPayloadReader extends TagPayloadReader { private static final String NAME_METADATA = "onMetaData"; diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flv/TagPayloadReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flv/TagPayloadReader.java index 48914b7c2c9..8d56951b203 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flv/TagPayloadReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flv/TagPayloadReader.java @@ -15,41 +15,35 @@ */ package com.google.android.exoplayer2.extractor.flv; +import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.util.ParsableByteArray; -/** - * Extracts individual samples from FLV tags, preserving original order. - */ +/** Extracts individual samples from FLV tags, preserving original order. */ /* package */ abstract class TagPayloadReader { - /** - * Thrown when the format is not supported. - */ + /** Thrown when the format is not supported. */ public static final class UnsupportedFormatException extends ParserException { public UnsupportedFormatException(String msg) { - super(msg); + super(msg, /* cause= */ null, /* contentIsMalformed= */ false, C.DATA_TYPE_MEDIA); } - } protected final TrackOutput output; - /** - * @param output A {@link TrackOutput} to which samples should be written. - */ + /** @param output A {@link TrackOutput} to which samples should be written. */ protected TagPayloadReader(TrackOutput output) { this.output = output; } /** * Notifies the reader that a seek has occurred. - *

    - * Following a call to this method, the data passed to the next invocation of - * {@link #consume(ParsableByteArray, long)} will not be a continuation of the data that - * was previously passed. Hence the reader should reset any internal state. + * + *

    Following a call to this method, the data passed to the next invocation of {@link + * #consume(ParsableByteArray, long)} will not be a continuation of the data that was previously + * passed. Hence the reader should reset any internal state. */ public abstract void seek(); diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flv/VideoTagPayloadReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flv/VideoTagPayloadReader.java index 6ab4da1acf5..03ff74c39df 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flv/VideoTagPayloadReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flv/VideoTagPayloadReader.java @@ -24,9 +24,7 @@ import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.video.AvcConfig; -/** - * Parses video tags from an FLV stream and extracts H.264 nal units. - */ +/** Parses video tags from an FLV stream and extracts H.264 nal units. */ /* package */ final class VideoTagPayloadReader extends TagPayloadReader { // Video codec. @@ -50,9 +48,7 @@ private boolean hasOutputKeyframe; private int frameType; - /** - * @param output A {@link TrackOutput} to which samples should be written. - */ + /** @param output A {@link TrackOutput} to which samples should be written. */ public VideoTagPayloadReader(TrackOutput output) { super(output); nalStartCode = new ParsableByteArray(NalUnitUtil.NAL_START_CODE); @@ -143,5 +139,4 @@ protected boolean parsePayload(ParsableByteArray data, long timeUs) throws Parse return false; } } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/jpeg/JpegExtractor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/jpeg/JpegExtractor.java index 777126905ae..a985ec83ee3 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/jpeg/JpegExtractor.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/jpeg/JpegExtractor.java @@ -30,6 +30,7 @@ import com.google.android.exoplayer2.extractor.mp4.Mp4Extractor; import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.mp4.MotionPhotoMetadata; +import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.ParsableByteArray; import java.io.IOException; import java.lang.annotation.Documented; @@ -273,7 +274,10 @@ private void outputImageTrack(Metadata.Entry... metadataEntries) { TrackOutput imageTrackOutput = checkNotNull(extractorOutput).track(IMAGE_TRACK_ID, C.TRACK_TYPE_IMAGE); imageTrackOutput.format( - new Format.Builder().setMetadata(new Metadata(metadataEntries)).build()); + new Format.Builder() + .setContainerMimeType(MimeTypes.IMAGE_JPEG) + .setMetadata(new Metadata(metadataEntries)) + .build()); } /** diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/jpeg/XmpMotionPhotoDescriptionParser.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/jpeg/XmpMotionPhotoDescriptionParser.java index 0972c005672..17fa7756abd 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/jpeg/XmpMotionPhotoDescriptionParser.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/jpeg/XmpMotionPhotoDescriptionParser.java @@ -85,7 +85,8 @@ private static MotionPhotoDescription parseInternal(String xmpString) xpp.setInput(new StringReader(xmpString)); xpp.next(); if (!XmlPullParserUtil.isStartTag(xpp, "x:xmpmeta")) { - throw new ParserException("Couldn't find xmp metadata"); + throw ParserException.createForMalformedContainer( + "Couldn't find xmp metadata", /* cause= */ null); } long motionPhotoPresentationTimestampUs = C.TIME_UNSET; List containerItems = ImmutableList.of(); diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/DefaultEbmlReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/DefaultEbmlReader.java index 754cd7a4c2a..de4c9e23c6b 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/DefaultEbmlReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/DefaultEbmlReader.java @@ -15,7 +15,6 @@ */ package com.google.android.exoplayer2.extractor.mkv; - import androidx.annotation.IntDef; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ParserException; @@ -30,9 +29,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.RequiresNonNull; -/** - * Default implementation of {@link EbmlReader}. - */ +/** Default implementation of {@link EbmlReader}. */ /* package */ final class DefaultEbmlReader implements EbmlReader { @Documented @@ -117,7 +114,8 @@ public boolean read(ExtractorInput input) throws IOException { return true; case EbmlProcessor.ELEMENT_TYPE_UNSIGNED_INT: if (elementContentSize > MAX_INTEGER_ELEMENT_SIZE_BYTES) { - throw new ParserException("Invalid integer size: " + elementContentSize); + throw ParserException.createForMalformedContainer( + "Invalid integer size: " + elementContentSize, /* cause= */ null); } processor.integerElement(elementId, readInteger(input, (int) elementContentSize)); elementState = ELEMENT_STATE_READ_ID; @@ -125,14 +123,16 @@ public boolean read(ExtractorInput input) throws IOException { case EbmlProcessor.ELEMENT_TYPE_FLOAT: if (elementContentSize != VALID_FLOAT32_ELEMENT_SIZE_BYTES && elementContentSize != VALID_FLOAT64_ELEMENT_SIZE_BYTES) { - throw new ParserException("Invalid float size: " + elementContentSize); + throw ParserException.createForMalformedContainer( + "Invalid float size: " + elementContentSize, /* cause= */ null); } processor.floatElement(elementId, readFloat(input, (int) elementContentSize)); elementState = ELEMENT_STATE_READ_ID; return true; case EbmlProcessor.ELEMENT_TYPE_STRING: if (elementContentSize > Integer.MAX_VALUE) { - throw new ParserException("String element size: " + elementContentSize); + throw ParserException.createForMalformedContainer( + "String element size: " + elementContentSize, /* cause= */ null); } processor.stringElement(elementId, readString(input, (int) elementContentSize)); elementState = ELEMENT_STATE_READ_ID; @@ -146,7 +146,8 @@ public boolean read(ExtractorInput input) throws IOException { elementState = ELEMENT_STATE_READ_ID; break; default: - throw new ParserException("Invalid element type " + type); + throw ParserException.createForMalformedContainer( + "Invalid element type " + type, /* cause= */ null); } } } @@ -250,7 +251,5 @@ private MasterElement(int elementId, long elementEndPosition) { this.elementId = elementId; this.elementEndPosition = elementEndPosition; } - } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/EbmlProcessor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/EbmlProcessor.java index 7291ae9c832..458b2e87e31 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/EbmlProcessor.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/EbmlProcessor.java @@ -79,12 +79,12 @@ public interface EbmlProcessor { /** * Called when the start of a master element is encountered. - *

    - * Following events should be considered as taking place within this element until a matching call - * to {@link #endMasterElement(int)} is made. - *

    - * Note that it is possible for another master element of the same element ID to be nested within - * itself. + * + *

    Following events should be considered as taking place within this element until a matching + * call to {@link #endMasterElement(int)} is made. + * + *

    Note that it is possible for another master element of the same element ID to be nested + * within itself. * * @param id The element ID. * @param contentPosition The position of the start of the element's content in the stream. diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/EbmlReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/EbmlReader.java index fc32fba4f7f..c19906a93ae 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/EbmlReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/EbmlReader.java @@ -37,8 +37,8 @@ /** * Resets the state of the reader. - *

    - * Subsequent calls to {@link #read(ExtractorInput)} will start reading a new EBML structure + * + *

    Subsequent calls to {@link #read(ExtractorInput)} will start reading a new EBML structure * from scratch. */ void reset(); diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java index c3f3e5e9019..e1c68726b38 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java @@ -91,8 +91,8 @@ public class MatroskaExtractor implements Extractor { public @interface Flags {} /** * Flag to disable seeking for cues. - *

    - * Normally (i.e. when this flag is not set) the extractor will seek to the cues element if its + * + *

    Normally (i.e. when this flag is not set) the extractor will seek to the cues element if its * position is specified in the seek head and if it's after the first cluster. Setting this flag * disables seeking to the cues element. If the cues element is after the first cluster then the * media is treated as being unseekable. @@ -282,25 +282,21 @@ public class MatroskaExtractor implements Extractor { 49, 10, 48, 48, 58, 48, 48, 58, 48, 48, 44, 48, 48, 48, 32, 45, 45, 62, 32, 48, 48, 58, 48, 48, 58, 48, 48, 44, 48, 48, 48, 10 }; - /** - * The byte offset of the end timecode in {@link #SUBRIP_PREFIX}. - */ + /** The byte offset of the end timecode in {@link #SUBRIP_PREFIX}. */ private static final int SUBRIP_PREFIX_END_TIMECODE_OFFSET = 19; /** * The value by which to divide a time in microseconds to convert it to the unit of the last value * in a subrip timecode (milliseconds). */ private static final long SUBRIP_TIMECODE_LAST_VALUE_SCALING_FACTOR = 1000; - /** - * The format of a subrip timecode. - */ + /** The format of a subrip timecode. */ private static final String SUBRIP_TIMECODE_FORMAT = "%02d:%02d:%02d,%03d"; - /** - * Matroska specific format line for SSA subtitles. - */ - private static final byte[] SSA_DIALOGUE_FORMAT = Util.getUtf8Bytes("Format: Start, End, " - + "ReadOrder, Layer, Style, Name, MarginL, MarginR, MarginV, Effect, Text"); + /** Matroska specific format line for SSA subtitles. */ + private static final byte[] SSA_DIALOGUE_FORMAT = + Util.getUtf8Bytes( + "Format: Start, End, " + + "ReadOrder, Layer, Style, Name, MarginL, MarginR, MarginV, Effect, Text"); /** * A template for the prefix that must be added to each SSA sample. * @@ -317,35 +313,23 @@ public class MatroskaExtractor implements Extractor { 68, 105, 97, 108, 111, 103, 117, 101, 58, 32, 48, 58, 48, 48, 58, 48, 48, 58, 48, 48, 44, 48, 58, 48, 48, 58, 48, 48, 58, 48, 48, 44 }; - /** - * The byte offset of the end timecode in {@link #SSA_PREFIX}. - */ + /** The byte offset of the end timecode in {@link #SSA_PREFIX}. */ private static final int SSA_PREFIX_END_TIMECODE_OFFSET = 21; /** * The value by which to divide a time in microseconds to convert it to the unit of the last value * in an SSA timecode (1/100ths of a second). */ private static final long SSA_TIMECODE_LAST_VALUE_SCALING_FACTOR = 10_000; - /** - * The format of an SSA timecode. - */ + /** The format of an SSA timecode. */ private static final String SSA_TIMECODE_FORMAT = "%01d:%02d:%02d:%02d"; - /** - * The length in bytes of a WAVEFORMATEX structure. - */ + /** The length in bytes of a WAVEFORMATEX structure. */ private static final int WAVE_FORMAT_SIZE = 18; - /** - * Format tag indicating a WAVEFORMATEXTENSIBLE structure. - */ + /** Format tag indicating a WAVEFORMATEXTENSIBLE structure. */ private static final int WAVE_FORMAT_EXTENSIBLE = 0xFFFE; - /** - * Format tag for PCM. - */ + /** Format tag for PCM. */ private static final int WAVE_FORMAT_PCM = 1; - /** - * Sub format for PCM. - */ + /** Sub format for PCM. */ private static final UUID WAVE_SUBFORMAT_PCM = new UUID(0x0100000000001000L, 0x800000AA00389B71L); /** Some HTC devices signal rotation in track names. */ @@ -642,7 +626,8 @@ protected void startMasterElement(int id, long contentPosition, long contentSize case ID_SEGMENT: if (segmentContentPosition != C.POSITION_UNSET && segmentContentPosition != contentPosition) { - throw new ParserException("Multiple Segment elements not supported"); + throw ParserException.createForMalformedContainer( + "Multiple Segment elements not supported", /* cause= */ null); } segmentContentPosition = contentPosition; segmentContentSize = contentSize; @@ -712,7 +697,8 @@ protected void endMasterElement(int id) throws ParserException { break; case ID_SEEK: if (seekEntryId == UNSET_ENTRY_ID || seekEntryPosition == C.POSITION_UNSET) { - throw new ParserException("Mandatory element SeekID or SeekPosition not found"); + throw ParserException.createForMalformedContainer( + "Mandatory element SeekID or SeekPosition not found", /* cause= */ null); } if (seekEntryId == ID_CUES) { cuesContentPosition = seekEntryPosition; @@ -758,22 +744,27 @@ protected void endMasterElement(int id) throws ParserException { assertInTrackEntry(id); if (currentTrack.hasContentEncryption) { if (currentTrack.cryptoData == null) { - throw new ParserException("Encrypted Track found but ContentEncKeyID was not found"); + throw ParserException.createForMalformedContainer( + "Encrypted Track found but ContentEncKeyID was not found", /* cause= */ null); } - currentTrack.drmInitData = new DrmInitData(new SchemeData(C.UUID_NIL, - MimeTypes.VIDEO_WEBM, currentTrack.cryptoData.encryptionKey)); + currentTrack.drmInitData = + new DrmInitData( + new SchemeData( + C.UUID_NIL, MimeTypes.VIDEO_WEBM, currentTrack.cryptoData.encryptionKey)); } break; case ID_CONTENT_ENCODINGS: assertInTrackEntry(id); if (currentTrack.hasContentEncryption && currentTrack.sampleStrippedBytes != null) { - throw new ParserException("Combining encryption and compression is not supported"); + throw ParserException.createForMalformedContainer( + "Combining encryption and compression is not supported", /* cause= */ null); } break; case ID_TRACK_ENTRY: Track currentTrack = checkStateNotNull(this.currentTrack); if (currentTrack.codecId == null) { - throw new ParserException("CodecId is missing in TrackEntry element"); + throw ParserException.createForMalformedContainer( + "CodecId is missing in TrackEntry element", /* cause= */ null); } else { if (isCodecSupported(currentTrack.codecId)) { currentTrack.initializeOutput(extractorOutput, currentTrack.number); @@ -784,7 +775,8 @@ protected void endMasterElement(int id) throws ParserException { break; case ID_TRACKS: if (tracks.size() == 0) { - throw new ParserException("No valid tracks were found"); + throw ParserException.createForMalformedContainer( + "No valid tracks were found", /* cause= */ null); } extractorOutput.endTracks(); break; @@ -804,13 +796,15 @@ protected void integerElement(int id, long value) throws ParserException { case ID_EBML_READ_VERSION: // Validate that EBMLReadVersion is supported. This extractor only supports v1. if (value != 1) { - throw new ParserException("EBMLReadVersion " + value + " not supported"); + throw ParserException.createForMalformedContainer( + "EBMLReadVersion " + value + " not supported", /* cause= */ null); } break; case ID_DOC_TYPE_READ_VERSION: // Validate that DocTypeReadVersion is supported. This extractor only supports up to v2. if (value < 1 || value > 2) { - throw new ParserException("DocTypeReadVersion " + value + " not supported"); + throw ParserException.createForMalformedContainer( + "DocTypeReadVersion " + value + " not supported", /* cause= */ null); } break; case ID_SEEK_POSITION: @@ -875,31 +869,36 @@ protected void integerElement(int id, long value) throws ParserException { case ID_CONTENT_ENCODING_ORDER: // This extractor only supports one ContentEncoding element and hence the order has to be 0. if (value != 0) { - throw new ParserException("ContentEncodingOrder " + value + " not supported"); + throw ParserException.createForMalformedContainer( + "ContentEncodingOrder " + value + " not supported", /* cause= */ null); } break; case ID_CONTENT_ENCODING_SCOPE: // This extractor only supports the scope of all frames. if (value != 1) { - throw new ParserException("ContentEncodingScope " + value + " not supported"); + throw ParserException.createForMalformedContainer( + "ContentEncodingScope " + value + " not supported", /* cause= */ null); } break; case ID_CONTENT_COMPRESSION_ALGORITHM: // This extractor only supports header stripping. if (value != 3) { - throw new ParserException("ContentCompAlgo " + value + " not supported"); + throw ParserException.createForMalformedContainer( + "ContentCompAlgo " + value + " not supported", /* cause= */ null); } break; case ID_CONTENT_ENCRYPTION_ALGORITHM: // Only the value 5 (AES) is allowed according to the WebM specification. if (value != 5) { - throw new ParserException("ContentEncAlgo " + value + " not supported"); + throw ParserException.createForMalformedContainer( + "ContentEncAlgo " + value + " not supported", /* cause= */ null); } break; case ID_CONTENT_ENCRYPTION_AES_SETTINGS_CIPHER_MODE: // Only the value 1 is allowed according to the WebM specification. if (value != 1) { - throw new ParserException("AESSettingsCipherMode " + value + " not supported"); + throw ParserException.createForMalformedContainer( + "AESSettingsCipherMode " + value + " not supported", /* cause= */ null); } break; case ID_CUE_TIME: @@ -945,45 +944,22 @@ protected void integerElement(int id, long value) throws ParserException { case ID_COLOUR_PRIMARIES: assertInTrackEntry(id); currentTrack.hasColorInfo = true; - switch ((int) value) { - case 1: - currentTrack.colorSpace = C.COLOR_SPACE_BT709; - break; - case 4: // BT.470M. - case 5: // BT.470BG. - case 6: // SMPTE 170M. - case 7: // SMPTE 240M. - currentTrack.colorSpace = C.COLOR_SPACE_BT601; - break; - case 9: - currentTrack.colorSpace = C.COLOR_SPACE_BT2020; - break; - default: - break; + int colorSpace = ColorInfo.isoColorPrimariesToColorSpace((int) value); + if (colorSpace != Format.NO_VALUE) { + currentTrack.colorSpace = colorSpace; } break; case ID_COLOUR_TRANSFER: assertInTrackEntry(id); - switch ((int) value) { - case 1: // BT.709. - case 6: // SMPTE 170M. - case 7: // SMPTE 240M. - currentTrack.colorTransfer = C.COLOR_TRANSFER_SDR; - break; - case 16: - currentTrack.colorTransfer = C.COLOR_TRANSFER_ST2084; - break; - case 18: - currentTrack.colorTransfer = C.COLOR_TRANSFER_HLG; - break; - default: - break; + int colorTransfer = ColorInfo.isoTransferCharacteristicsToColorTransfer((int) value); + if (colorTransfer != Format.NO_VALUE) { + currentTrack.colorTransfer = colorTransfer; } break; case ID_COLOUR_RANGE: assertInTrackEntry(id); - switch((int) value) { - case 1: // Broadcast range. + switch ((int) value) { + case 1: // Broadcast range. currentTrack.colorRange = C.COLOR_RANGE_LIMITED; break; case 2: @@ -1095,7 +1071,8 @@ protected void stringElement(int id, String value) throws ParserException { case ID_DOC_TYPE: // Validate that DocType is supported. if (!DOC_TYPE_WEBM.equals(value) && !DOC_TYPE_MATROSKA.equals(value)) { - throw new ParserException("DocType " + value + " not supported"); + throw ParserException.createForMalformedContainer( + "DocType " + value + " not supported", /* cause= */ null); } break; case ID_NAME: @@ -1217,7 +1194,8 @@ protected void binaryElement(int id, int contentSize, ExtractorInput input) thro blockSampleSizes[sampleIndex] = 0; readScratch(input, ++headerSize); if (scratch.getData()[headerSize - 1] == 0) { - throw new ParserException("No valid varint length mask found"); + throw ParserException.createForMalformedContainer( + "No valid varint length mask found", /* cause= */ null); } long readValue = 0; for (int i = 0; i < 8; i++) { @@ -1239,7 +1217,8 @@ protected void binaryElement(int id, int contentSize, ExtractorInput input) thro } } if (readValue < Integer.MIN_VALUE || readValue > Integer.MAX_VALUE) { - throw new ParserException("EBML lacing sample size out of range."); + throw ParserException.createForMalformedContainer( + "EBML lacing sample size out of range.", /* cause= */ null); } int intReadValue = (int) readValue; blockSampleSizes[sampleIndex] = @@ -1252,7 +1231,8 @@ protected void binaryElement(int id, int contentSize, ExtractorInput input) thro contentSize - blockTrackNumberLength - headerSize - totalSamplesSize; } else { // Lacing is always in the range 0--3. - throw new ParserException("Unexpected lacing value: " + lacing); + throw ParserException.createForMalformedContainer( + "Unexpected lacing value: " + lacing, /* cause= */ null); } } @@ -1299,7 +1279,8 @@ protected void binaryElement(int id, int contentSize, ExtractorInput input) thro tracks.get(blockTrackNumber), blockAdditionalId, input, contentSize); break; default: - throw new ParserException("Unexpected id: " + id); + throw ParserException.createForMalformedContainer( + "Unexpected id: " + id, /* cause= */ null); } } @@ -1331,14 +1312,16 @@ protected void handleBlockAdditionalData( @EnsuresNonNull("currentTrack") private void assertInTrackEntry(int id) throws ParserException { if (currentTrack == null) { - throw new ParserException("Element " + id + " must be in a TrackEntry"); + throw ParserException.createForMalformedContainer( + "Element " + id + " must be in a TrackEntry", /* cause= */ null); } } @EnsuresNonNull({"cueTimesUs", "cueClusterPositions"}) private void assertInCues(int id) throws ParserException { if (cueTimesUs == null || cueClusterPositions == null) { - throw new ParserException("Element " + id + " must be in a Cues"); + throw ParserException.createForMalformedContainer( + "Element " + id + " must be in a Cues", /* cause= */ null); } } @@ -1438,7 +1421,8 @@ private int writeSampleData(ExtractorInput input, Track track, int size) throws input.readFully(scratch.getData(), 0, 1); sampleBytesRead++; if ((scratch.getData()[0] & 0x80) == 0x80) { - throw new ParserException("Extension bit is set in signal byte"); + throw ParserException.createForMalformedContainer( + "Extension bit is set in signal byte", /* cause= */ null); } sampleSignalByte = scratch.getData()[0]; sampleSignalByteRead = true; @@ -1591,8 +1575,10 @@ private int writeSampleData(ExtractorInput input, Track track, int size) throws // number of samples in the current page. This definition holds good only for Ogg and // irrelevant for Matroska. So we always set this to -1 (the decoder will ignore this value if // we set it to -1). The android platform media extractor [2] does the same. - // [1] https://android.googlesource.com/platform/frameworks/av/+/lollipop-release/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp#314 - // [2] https://android.googlesource.com/platform/frameworks/av/+/lollipop-release/media/libstagefright/NuMediaExtractor.cpp#474 + // [1] + // https://android.googlesource.com/platform/frameworks/av/+/lollipop-release/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp#314 + // [2] + // https://android.googlesource.com/platform/frameworks/av/+/lollipop-release/media/libstagefright/NuMediaExtractor.cpp#474 vorbisNumPageSamples.setPosition(0); output.sampleData(vorbisNumPageSamples, 4); sampleBytesWritten += 4; @@ -1735,9 +1721,12 @@ private int writeToOutput(ExtractorInput input, TrackOutput output, int length) */ private SeekMap buildSeekMap( @Nullable LongArray cueTimesUs, @Nullable LongArray cueClusterPositions) { - if (segmentContentPosition == C.POSITION_UNSET || durationUs == C.TIME_UNSET - || cueTimesUs == null || cueTimesUs.size() == 0 - || cueClusterPositions == null || cueClusterPositions.size() != cueTimesUs.size()) { + if (segmentContentPosition == C.POSITION_UNSET + || durationUs == C.TIME_UNSET + || cueTimesUs == null + || cueTimesUs.size() == 0 + || cueClusterPositions == null + || cueClusterPositions.size() != cueTimesUs.size()) { // Cues information is missing or incomplete. return new SeekMap.Unseekable(durationUs); } @@ -1798,7 +1787,8 @@ private boolean maybeSeekForCues(PositionHolder seekPosition, long currentPositi private long scaleTimecodeToUs(long unscaledTimecode) throws ParserException { if (timecodeScale == C.TIME_UNSET) { - throw new ParserException("Can't scale timecode prior to timecodeScale being set."); + throw ParserException.createForMalformedContainer( + "Can't scale timecode prior to timecodeScale being set.", /* cause= */ null); } return Util.scaleLargeTimestamp(unscaledTimecode, timecodeScale, 1000); } @@ -1977,15 +1967,11 @@ private static final class Track { private static final int DISPLAY_UNIT_PIXELS = 0; private static final int MAX_CHROMATICITY = 50_000; // Defined in CTA-861.3. - /** - * Default max content light level (CLL) that should be encoded into hdrStaticInfo. - */ - private static final int DEFAULT_MAX_CLL = 1000; // nits. + /** Default max content light level (CLL) that should be encoded into hdrStaticInfo. */ + private static final int DEFAULT_MAX_CLL = 1000; // nits. - /** - * Default frame-average light level (FALL) that should be encoded into hdrStaticInfo. - */ - private static final int DEFAULT_MAX_FALL = 200; // nits. + /** Default frame-average light level (FALL) that should be encoded into hdrStaticInfo. */ + private static final int DEFAULT_MAX_FALL = 200; // nits. // Common elements. public @MonotonicNonNull String name; @@ -2012,15 +1998,11 @@ private static final class Track { public float projectionPosePitch = 0f; public float projectionPoseRoll = 0f; public byte @MonotonicNonNull [] projectionData = null; - @C.StereoMode - public int stereoMode = Format.NO_VALUE; + @C.StereoMode public int stereoMode = Format.NO_VALUE; public boolean hasColorInfo = false; - @C.ColorSpace - public int colorSpace = Format.NO_VALUE; - @C.ColorTransfer - public int colorTransfer = Format.NO_VALUE; - @C.ColorRange - public int colorRange = Format.NO_VALUE; + @C.ColorSpace public int colorSpace = Format.NO_VALUE; + @C.ColorTransfer public int colorTransfer = Format.NO_VALUE; + @C.ColorRange public int colorRange = Format.NO_VALUE; public int maxContentLuminance = DEFAULT_MAX_CLL; public int maxFrameAverageLuminance = DEFAULT_MAX_FALL; public float primaryRChromaticityX = Format.NO_VALUE; @@ -2167,8 +2149,12 @@ public void initializeOutput(ExtractorOutput output, int trackId) throws ParserE if (pcmEncoding == C.ENCODING_INVALID) { pcmEncoding = Format.NO_VALUE; mimeType = MimeTypes.AUDIO_UNKNOWN; - Log.w(TAG, "Unsupported PCM bit depth: " + audioBitDepth + ". Setting mimeType to " - + mimeType); + Log.w( + TAG, + "Unsupported PCM bit depth: " + + audioBitDepth + + ". Setting mimeType to " + + mimeType); } } else { mimeType = MimeTypes.AUDIO_UNKNOWN; @@ -2243,7 +2229,8 @@ public void initializeOutput(ExtractorOutput output, int trackId) throws ParserE initializationData = ImmutableList.of(initializationDataBytes); break; default: - throw new ParserException("Unrecognized codec identifier."); + throw ParserException.createForMalformedContainer( + "Unrecognized codec identifier.", /* cause= */ null); } if (dolbyVisionConfigBytes != null) { @@ -2320,7 +2307,8 @@ public void initializeOutput(ExtractorOutput output, int trackId) throws ParserE || MimeTypes.APPLICATION_DVBSUBS.equals(mimeType)) { type = C.TRACK_TYPE_TEXT; } else { - throw new ParserException("Unexpected MIME type."); + throw ParserException.createForMalformedContainer( + "Unexpected MIME type.", /* cause= */ null); } if (name != null && !TRACK_NAME_TO_ROTATION_DEGREES.containsKey(name)) { @@ -2362,21 +2350,25 @@ public void reset() { @Nullable private byte[] getHdrStaticInfo() { // Are all fields present. - if (primaryRChromaticityX == Format.NO_VALUE || primaryRChromaticityY == Format.NO_VALUE - || primaryGChromaticityX == Format.NO_VALUE || primaryGChromaticityY == Format.NO_VALUE - || primaryBChromaticityX == Format.NO_VALUE || primaryBChromaticityY == Format.NO_VALUE + if (primaryRChromaticityX == Format.NO_VALUE + || primaryRChromaticityY == Format.NO_VALUE + || primaryGChromaticityX == Format.NO_VALUE + || primaryGChromaticityY == Format.NO_VALUE + || primaryBChromaticityX == Format.NO_VALUE + || primaryBChromaticityY == Format.NO_VALUE || whitePointChromaticityX == Format.NO_VALUE - || whitePointChromaticityY == Format.NO_VALUE || maxMasteringLuminance == Format.NO_VALUE + || whitePointChromaticityY == Format.NO_VALUE + || maxMasteringLuminance == Format.NO_VALUE || minMasteringLuminance == Format.NO_VALUE) { return null; } byte[] hdrStaticInfoData = new byte[25]; ByteBuffer hdrStaticInfo = ByteBuffer.wrap(hdrStaticInfoData).order(ByteOrder.LITTLE_ENDIAN); - hdrStaticInfo.put((byte) 0); // Type. + hdrStaticInfo.put((byte) 0); // Type. hdrStaticInfo.putShort((short) ((primaryRChromaticityX * MAX_CHROMATICITY) + 0.5f)); hdrStaticInfo.putShort((short) ((primaryRChromaticityY * MAX_CHROMATICITY) + 0.5f)); - hdrStaticInfo.putShort((short) ((primaryGChromaticityX * MAX_CHROMATICITY) + 0.5f)); + hdrStaticInfo.putShort((short) ((primaryGChromaticityX * MAX_CHROMATICITY) + 0.5f)); hdrStaticInfo.putShort((short) ((primaryGChromaticityY * MAX_CHROMATICITY) + 0.5f)); hdrStaticInfo.putShort((short) ((primaryBChromaticityX * MAX_CHROMATICITY) + 0.5f)); hdrStaticInfo.putShort((short) ((primaryBChromaticityY * MAX_CHROMATICITY) + 0.5f)); @@ -2421,10 +2413,12 @@ private byte[] getHdrStaticInfo() { return new Pair<>(MimeTypes.VIDEO_VC1, Collections.singletonList(initializationData)); } } - throw new ParserException("Failed to find FourCC VC1 initialization data"); + throw ParserException.createForMalformedContainer( + "Failed to find FourCC VC1 initialization data", /* cause= */ null); } } catch (ArrayIndexOutOfBoundsException e) { - throw new ParserException("Error parsing FourCC private data"); + throw ParserException.createForMalformedContainer( + "Error parsing FourCC private data", /* cause= */ null); } Log.w(TAG, "Unknown FourCC. Setting mimeType to " + MimeTypes.VIDEO_UNKNOWN); @@ -2441,7 +2435,8 @@ private static List parseVorbisCodecPrivate(byte[] codecPrivate) throws ParserException { try { if (codecPrivate[0] != 0x02) { - throw new ParserException("Error parsing vorbis codec private"); + throw ParserException.createForMalformedContainer( + "Error parsing vorbis codec private", /* cause= */ null); } int offset = 1; int vorbisInfoLength = 0; @@ -2459,17 +2454,20 @@ private static List parseVorbisCodecPrivate(byte[] codecPrivate) vorbisSkipLength += codecPrivate[offset++] & 0xFF; if (codecPrivate[offset] != 0x01) { - throw new ParserException("Error parsing vorbis codec private"); + throw ParserException.createForMalformedContainer( + "Error parsing vorbis codec private", /* cause= */ null); } byte[] vorbisInfo = new byte[vorbisInfoLength]; System.arraycopy(codecPrivate, offset, vorbisInfo, 0, vorbisInfoLength); offset += vorbisInfoLength; if (codecPrivate[offset] != 0x03) { - throw new ParserException("Error parsing vorbis codec private"); + throw ParserException.createForMalformedContainer( + "Error parsing vorbis codec private", /* cause= */ null); } offset += vorbisSkipLength; if (codecPrivate[offset] != 0x05) { - throw new ParserException("Error parsing vorbis codec private"); + throw ParserException.createForMalformedContainer( + "Error parsing vorbis codec private", /* cause= */ null); } byte[] vorbisBooks = new byte[codecPrivate.length - offset]; System.arraycopy(codecPrivate, offset, vorbisBooks, 0, codecPrivate.length - offset); @@ -2478,7 +2476,8 @@ private static List parseVorbisCodecPrivate(byte[] codecPrivate) initializationData.add(vorbisBooks); return initializationData; } catch (ArrayIndexOutOfBoundsException e) { - throw new ParserException("Error parsing vorbis codec private"); + throw ParserException.createForMalformedContainer( + "Error parsing vorbis codec private", /* cause= */ null); } } @@ -2501,7 +2500,8 @@ private static boolean parseMsAcmCodecPrivate(ParsableByteArray buffer) throws P return false; } } catch (ArrayIndexOutOfBoundsException e) { - throw new ParserException("Error parsing MS/ACM codec private"); + throw ParserException.createForMalformedContainer( + "Error parsing MS/ACM codec private", /* cause= */ null); } } @@ -2520,10 +2520,10 @@ private void assertOutputInitialized() { @EnsuresNonNull("codecPrivate") private byte[] getCodecPrivate(String codecId) throws ParserException { if (codecPrivate == null) { - throw new ParserException("Missing CodecPrivate for codec " + codecId); + throw ParserException.createForMalformedContainer( + "Missing CodecPrivate for codec " + codecId, /* cause= */ null); } return codecPrivate; } } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/Sniffer.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/Sniffer.java index 415d3d45460..f36adbed666 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/Sniffer.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/Sniffer.java @@ -16,6 +16,7 @@ package com.google.android.exoplayer2.extractor.mkv; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.ExtractorInput; import com.google.android.exoplayer2.util.ParsableByteArray; import java.io.IOException; @@ -26,10 +27,9 @@ */ /* package */ final class Sniffer { - /** - * The number of bytes to search for a valid header in {@link #sniff(ExtractorInput)}. - */ + /** The number of bytes to search for a valid header in {@link #sniff(ExtractorInput)}. */ private static final int SEARCH_LENGTH = 1024; + private static final int ID_EBML = 0x1A45DFA3; private final ParsableByteArray scratch; @@ -39,11 +39,14 @@ public Sniffer() { scratch = new ParsableByteArray(8); } - /** @see com.google.android.exoplayer2.extractor.Extractor#sniff(ExtractorInput) */ + /** See {@link Extractor#sniff(ExtractorInput)}. */ public boolean sniff(ExtractorInput input) throws IOException { long inputLength = input.getLength(); - int bytesToSearch = (int) (inputLength == C.LENGTH_UNSET || inputLength > SEARCH_LENGTH - ? SEARCH_LENGTH : inputLength); + int bytesToSearch = + (int) + (inputLength == C.LENGTH_UNSET || inputLength > SEARCH_LENGTH + ? SEARCH_LENGTH + : inputLength); // Find four bytes equal to ID_EBML near the start of the input. input.peekFully(scratch.getData(), 0, 4); long tag = scratch.readUnsignedInt(); @@ -106,5 +109,4 @@ private long readUint(ExtractorInput input) throws IOException { peekLength += length + 1; return value; } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/VarintReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/VarintReader.java index 6b244de72d4..a6ee6d9cc16 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/VarintReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/VarintReader.java @@ -20,9 +20,7 @@ import java.io.EOFException; import java.io.IOException; -/** - * Reads EBML variable-length integers (varints) from an {@link ExtractorInput}. - */ +/** Reads EBML variable-length integers (varints) from an {@link ExtractorInput}. */ /* package */ final class VarintReader { private static final int STATE_BEGIN_READING = 0; @@ -34,9 +32,8 @@ * *

    {@code 0x80} is a one-byte integer, {@code 0x40} is two bytes, and so on up to eight bytes. */ - private static final long[] VARINT_LENGTH_MASKS = new long[] { - 0x80L, 0x40L, 0x20L, 0x10L, 0x08L, 0x04L, 0x02L, 0x01L - }; + private static final long[] VARINT_LENGTH_MASKS = + new long[] {0x80L, 0x40L, 0x20L, 0x10L, 0x08L, 0x04L, 0x02L, 0x01L}; private final byte[] scratch; @@ -47,9 +44,7 @@ public VarintReader() { scratch = new byte[8]; } - /** - * Resets the reader to start reading a new variable-length integer. - */ + /** Resets the reader to start reading a new variable-length integer. */ public void reset() { state = STATE_BEGIN_READING; length = 0; @@ -110,9 +105,7 @@ public long readUnsignedVarint( return assembleVarint(scratch, length, removeLengthMask); } - /** - * Returns the number of bytes occupied by the most recently parsed varint. - */ + /** Returns the number of bytes occupied by the most recently parsed varint. */ public int getLastLength() { return length; } @@ -121,8 +114,8 @@ public int getLastLength() { * Parses and the length of the varint given the first byte. * * @param firstByte First byte of the varint. - * @return Length of the varint beginning with the given byte if it was valid, - * {@link C#LENGTH_UNSET} otherwise. + * @return Length of the varint beginning with the given byte if it was valid, {@link + * C#LENGTH_UNSET} otherwise. */ public static int parseUnsignedVarintLength(int firstByte) { int varIntLength = C.LENGTH_UNSET; @@ -143,8 +136,8 @@ public static int parseUnsignedVarintLength(int firstByte) { * @param removeLengthMask Removes the variable-length integer length mask from the value. * @return Parsed and assembled varint. */ - public static long assembleVarint(byte[] varintBytes, int varintLength, - boolean removeLengthMask) { + public static long assembleVarint( + byte[] varintBytes, int varintLength, boolean removeLengthMask) { long varint = varintBytes[0] & 0xFFL; if (removeLengthMask) { varint &= ~VARINT_LENGTH_MASKS[varintLength - 1]; @@ -154,5 +147,4 @@ public static long assembleVarint(byte[] varintBytes, int varintLength, } return varint; } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp3/Mp3Extractor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp3/Mp3Extractor.java index 21b7c8544fe..468e31e30a7 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp3/Mp3Extractor.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp3/Mp3Extractor.java @@ -101,22 +101,16 @@ public final class Mp3Extractor implements Extractor { ((id0 == 'C' && id1 == 'O' && id2 == 'M' && (id3 == 'M' || majorVersion == 2)) || (id0 == 'M' && id1 == 'L' && id2 == 'L' && (id3 == 'T' || majorVersion == 2))); - /** - * The maximum number of bytes to search when synchronizing, before giving up. - */ + /** The maximum number of bytes to search when synchronizing, before giving up. */ private static final int MAX_SYNC_BYTES = 128 * 1024; /** * The maximum number of bytes to peek when sniffing, excluding the ID3 header, before giving up. */ private static final int MAX_SNIFF_BYTES = 32 * 1024; - /** - * Maximum length of data read into {@link #scratch}. - */ + /** Maximum length of data read into {@link #scratch}. */ private static final int SCRATCH_LENGTH = 10; - /** - * Mask that includes the audio header values that must match between frames. - */ + /** Mask that includes the audio header values that must match between frames. */ private static final int MPEG_AUDIO_HEADER_MASK = 0xFFFE0C00; private static final int SEEK_HEADER_XING = 0x58696e67; @@ -153,17 +147,15 @@ public Mp3Extractor() { this(0); } - /** - * @param flags Flags that control the extractor's behavior. - */ + /** @param flags Flags that control the extractor's behavior. */ public Mp3Extractor(@Flags int flags) { this(flags, C.TIME_UNSET); } /** * @param flags Flags that control the extractor's behavior. - * @param forcedFirstSampleTimestampUs A timestamp to force for the first sample, or - * {@link C#TIME_UNSET} if forcing is not required. + * @param forcedFirstSampleTimestampUs A timestamp to force for the first sample, or {@link + * C#TIME_UNSET} if forcing is not required. */ public Mp3Extractor(@Flags int flags, long forcedFirstSampleTimestampUs) { this.flags = flags; @@ -365,7 +357,8 @@ private boolean synchronize(ExtractorInput input, boolean sniffing) throws IOExc // The header doesn't match the candidate header or is invalid. Try the next byte offset. if (searchedBytes++ == searchLimitBytes) { if (!sniffing) { - throw new ParserException("Searched too many bytes."); + throw ParserException.createForMalformedContainer( + "Searched too many bytes.", /* cause= */ null); } return false; } @@ -473,9 +466,10 @@ private Seeker computeSeeker(ExtractorInput input) throws IOException { private Seeker maybeReadSeekFrame(ExtractorInput input) throws IOException { ParsableByteArray frame = new ParsableByteArray(synchronizedHeader.frameSize); input.peekFully(frame.getData(), 0, synchronizedHeader.frameSize); - int xingBase = (synchronizedHeader.version & 1) != 0 - ? (synchronizedHeader.channels != 1 ? 36 : 21) // MPEG 1 - : (synchronizedHeader.channels != 1 ? 21 : 13); // MPEG 2 or 2.5 + int xingBase = + (synchronizedHeader.version & 1) != 0 + ? (synchronizedHeader.channels != 1 ? 36 : 21) // MPEG 1 + : (synchronizedHeader.channels != 1 ? 21 : 13); // MPEG 2 or 2.5 int seekHeader = getSeekFrameHeader(frame, xingBase); @Nullable Seeker seeker; if (seekHeader == SEEK_HEADER_XING || seekHeader == SEEK_HEADER_INFO) { @@ -518,9 +512,7 @@ private void assertInitialized() { Util.castNonNull(extractorOutput); } - /** - * Returns whether the headers match in those bits masked by {@link #MPEG_AUDIO_HEADER_MASK}. - */ + /** Returns whether the headers match in those bits masked by {@link #MPEG_AUDIO_HEADER_MASK}. */ private static boolean headersMatch(int headerA, long headerB) { return (headerA & MPEG_AUDIO_HEADER_MASK) == (headerB & MPEG_AUDIO_HEADER_MASK); } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp3/VbriSeeker.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp3/VbriSeeker.java index daf5265ddda..f2532863c41 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp3/VbriSeeker.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp3/VbriSeeker.java @@ -55,8 +55,9 @@ public static VbriSeeker create( return null; } int sampleRate = mpegAudioHeader.sampleRate; - long durationUs = Util.scaleLargeTimestamp(numFrames, - C.MICROS_PER_SECOND * (sampleRate >= 32000 ? 1152 : 576), sampleRate); + long durationUs = + Util.scaleLargeTimestamp( + numFrames, C.MICROS_PER_SECOND * (sampleRate >= 32000 ? 1152 : 576), sampleRate); int entryCount = frame.readUnsignedShort(); int scale = frame.readUnsignedShort(); int entrySize = frame.readUnsignedShort(); diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp3/XingSeeker.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp3/XingSeeker.java index d95721be5d7..51950e62822 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp3/XingSeeker.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp3/XingSeeker.java @@ -57,8 +57,8 @@ public static XingSeeker create( // If the frame count is missing/invalid, the header can't be used to determine the duration. return null; } - long durationUs = Util.scaleLargeTimestamp(frameCount, samplesPerFrame * C.MICROS_PER_SECOND, - sampleRate); + long durationUs = + Util.scaleLargeTimestamp(frameCount, samplesPerFrame * C.MICROS_PER_SECOND, sampleRate); if ((flags & 0x06) != 0x06) { // If the size in bytes or table of contents is missing, the stream is not seekable. return new XingSeeker(position, mpegAudioHeader.frameSize, durationUs); @@ -141,8 +141,8 @@ public SeekPoints getSeekPoints(long timeUs) { double nextScaledPosition = prevTableIndex == 99 ? 256 : tableOfContents[prevTableIndex + 1]; // Linearly interpolate between the two scaled positions. double interpolateFraction = percent - prevTableIndex; - scaledPosition = prevScaledPosition - + (interpolateFraction * (nextScaledPosition - prevScaledPosition)); + scaledPosition = + prevScaledPosition + (interpolateFraction * (nextScaledPosition - prevScaledPosition)); } long positionOffset = Math.round((scaledPosition / 256) * dataSize); // Ensure returned positions skip the frame containing the XING header. @@ -164,8 +164,10 @@ public long getTimeUs(long position) { long nextTimeUs = getTimeUsForTableIndex(prevTableIndex + 1); long nextScaledPosition = prevTableIndex == 99 ? 256 : tableOfContents[prevTableIndex + 1]; // Linearly interpolate between the two table entries. - double interpolateFraction = prevScaledPosition == nextScaledPosition ? 0 - : ((scaledPosition - prevScaledPosition) / (nextScaledPosition - prevScaledPosition)); + double interpolateFraction = + prevScaledPosition == nextScaledPosition + ? 0 + : ((scaledPosition - prevScaledPosition) / (nextScaledPosition - prevScaledPosition)); return prevTimeUs + Math.round(interpolateFraction * (nextTimeUs - prevTimeUs)); } @@ -188,5 +190,4 @@ public long getDataEndPosition() { private long getTimeUsForTableIndex(int tableIndex) { return (durationUs * tableIndex) / 100; } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Atom.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Atom.java index 273421a8131..a85d928f04d 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Atom.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Atom.java @@ -24,29 +24,19 @@ @SuppressWarnings("ConstantField") /* package */ abstract class Atom { - /** - * Size of an atom header, in bytes. - */ + /** Size of an atom header, in bytes. */ public static final int HEADER_SIZE = 8; - /** - * Size of a full atom header, in bytes. - */ + /** Size of a full atom header, in bytes. */ public static final int FULL_HEADER_SIZE = 12; - /** - * Size of a long atom header, in bytes. - */ + /** Size of a long atom header, in bytes. */ public static final int LONG_HEADER_SIZE = 16; - /** - * Value for the size field in an atom that defines its size in the largesize field. - */ + /** Value for the size field in an atom that defines its size in the largesize field. */ public static final int DEFINES_LARGE_SIZE = 1; - /** - * Value for the size field in an atom that extends to the end of the file. - */ + /** Value for the size field in an atom that extends to the end of the file. */ public static final int EXTENDS_TO_END_SIZE = 0; @SuppressWarnings("ConstantCaseForConstants") @@ -85,6 +75,9 @@ @SuppressWarnings("ConstantCaseForConstants") public static final int TYPE_av1C = 0x61763143; + @SuppressWarnings("ConstantCaseForConstants") + public static final int TYPE_colr = 0x636f6c72; + @SuppressWarnings("ConstantCaseForConstants") public static final int TYPE_dvav = 0x64766176; @@ -171,6 +164,9 @@ @SuppressWarnings("ConstantCaseForConstants") public static final int TYPE_dtse = 0x64747365; + @SuppressWarnings("ConstantCaseForConstants") + public static final int TYPE_dtsx = 0x64747378; + @SuppressWarnings("ConstantCaseForConstants") public static final int TYPE_ddts = 0x64647473; @@ -419,14 +415,10 @@ public String toString() { return getAtomTypeString(type); } - /** - * An MP4 atom that is a leaf. - */ + /** An MP4 atom that is a leaf. */ /* package */ static final class LeafAtom extends Atom { - /** - * The atom data. - */ + /** The atom data. */ public final ParsableByteArray data; /** @@ -437,12 +429,9 @@ public LeafAtom(int type, ParsableByteArray data) { super(type); this.data = data; } - } - /** - * An MP4 atom that has child atoms. - */ + /** An MP4 atom that has child atoms. */ /* package */ static final class ContainerAtom extends Atom { public final long endPosition; @@ -548,22 +537,19 @@ public int getChildAtomOfTypeCount(int type) { @Override public String toString() { return getAtomTypeString(type) - + " leaves: " + Arrays.toString(leafChildren.toArray()) - + " containers: " + Arrays.toString(containerChildren.toArray()); + + " leaves: " + + Arrays.toString(leafChildren.toArray()) + + " containers: " + + Arrays.toString(containerChildren.toArray()); } - } - /** - * Parses the version number out of the additional integer component of a full atom. - */ + /** Parses the version number out of the additional integer component of a full atom. */ public static int parseFullAtomVersion(int fullAtomInt) { return 0x000000FF & (fullAtomInt >> 24); } - /** - * Parses the atom flags out of the additional integer component of a full atom. - */ + /** Parses the atom flags out of the additional integer component of a full atom. */ public static int parseFullAtomFlags(int fullAtomInt) { return 0x00FFFFFF & fullAtomInt; } @@ -575,10 +561,10 @@ public static int parseFullAtomFlags(int fullAtomInt) { * @return The corresponding four character string. */ public static String getAtomTypeString(int type) { - return "" + (char) ((type >> 24) & 0xFF) + return "" + + (char) ((type >> 24) & 0xFF) + (char) ((type >> 16) & 0xFF) + (char) ((type >> 8) & 0xFF) + (char) (type & 0xFF); } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java index dea3113b616..f6ed6f7796f 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java @@ -17,6 +17,7 @@ import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static com.google.android.exoplayer2.util.MimeTypes.getMimeTypeFromMp4ObjectType; +import static com.google.android.exoplayer2.util.Util.castNonNull; import static java.lang.Math.max; import android.util.Pair; @@ -29,16 +30,17 @@ import com.google.android.exoplayer2.audio.Ac4Util; import com.google.android.exoplayer2.audio.OpusUtil; import com.google.android.exoplayer2.drm.DrmInitData; +import com.google.android.exoplayer2.extractor.ExtractorUtil; import com.google.android.exoplayer2.extractor.GaplessInfoHolder; import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.mp4.SmtaMetadataEntry; -import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.CodecSpecificDataUtil; import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.video.AvcConfig; +import com.google.android.exoplayer2.video.ColorInfo; import com.google.android.exoplayer2.video.DolbyVisionConfig; import com.google.android.exoplayer2.video.HevcConfig; import com.google.common.base.Function; @@ -49,34 +51,40 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; /** Utility methods for parsing MP4 format atom payloads according to ISO/IEC 14496-12. */ -@SuppressWarnings({"ConstantField"}) +@SuppressWarnings("ConstantField") /* package */ final class AtomParsers { private static final String TAG = "AtomParsers"; @SuppressWarnings("ConstantCaseForConstants") - private static final int TYPE_vide = 0x76696465; + private static final int TYPE_clcp = 0x636c6370; @SuppressWarnings("ConstantCaseForConstants") - private static final int TYPE_soun = 0x736f756e; + private static final int TYPE_mdta = 0x6d647461; @SuppressWarnings("ConstantCaseForConstants") - private static final int TYPE_text = 0x74657874; + private static final int TYPE_meta = 0x6d657461; + + @SuppressWarnings("ConstantCaseForConstants") + private static final int TYPE_nclc = 0x6e636c63; + + @SuppressWarnings("ConstantCaseForConstants") + private static final int TYPE_nclx = 0x6e636c78; @SuppressWarnings("ConstantCaseForConstants") private static final int TYPE_sbtl = 0x7362746c; @SuppressWarnings("ConstantCaseForConstants") - private static final int TYPE_subt = 0x73756274; + private static final int TYPE_soun = 0x736f756e; @SuppressWarnings("ConstantCaseForConstants") - private static final int TYPE_clcp = 0x636c6370; + private static final int TYPE_subt = 0x73756274; @SuppressWarnings("ConstantCaseForConstants") - private static final int TYPE_meta = 0x6d657461; + private static final int TYPE_text = 0x74657874; @SuppressWarnings("ConstantCaseForConstants") - private static final int TYPE_mdta = 0x6d647461; + private static final int TYPE_vide = 0x76696465; /** * The threshold number of samples to trim from the start/end of an audio track when applying an @@ -316,10 +324,20 @@ private static Track parseTrak( } } } - return stsdData.format == null ? null - : new Track(tkhdData.id, trackType, mdhdData.first, movieTimescale, durationUs, - stsdData.format, stsdData.requiredSampleTransformation, stsdData.trackEncryptionBoxes, - stsdData.nalUnitLengthFieldLength, editListDurations, editListMediaTimes); + return stsdData.format == null + ? null + : new Track( + tkhdData.id, + trackType, + mdhdData.first, + movieTimescale, + durationUs, + stsdData.format, + stsdData.requiredSampleTransformation, + stsdData.trackEncryptionBoxes, + stsdData.nalUnitLengthFieldLength, + editListDurations, + editListMediaTimes); } /** @@ -341,7 +359,8 @@ private static TrackSampleTable parseStbl( } else { @Nullable Atom.LeafAtom stz2Atom = stblAtom.getLeafAtomOfType(Atom.TYPE_stz2); if (stz2Atom == null) { - throw new ParserException("Track has no sample table size information"); + throw ParserException.createForMalformedContainer( + "Track has no sample table size information", /* cause= */ null); } sampleSizeBox = new Stz2SampleSizeBox(stz2Atom); } @@ -576,15 +595,19 @@ private static TrackSampleTable parseStbl( && track.type == C.TRACK_TYPE_AUDIO && timestamps.length >= 2) { long editStartTime = checkNotNull(track.editListMediaTimes)[0]; - long editEndTime = editStartTime + Util.scaleLargeTimestamp(track.editListDurations[0], - track.timescale, track.movieTimescale); + long editEndTime = + editStartTime + + Util.scaleLargeTimestamp( + track.editListDurations[0], track.timescale, track.movieTimescale); if (canApplyEditWithGaplessInfo(timestamps, duration, editStartTime, editEndTime)) { long paddingTimeUnits = duration - editEndTime; - long encoderDelay = Util.scaleLargeTimestamp(editStartTime - timestamps[0], - track.format.sampleRate, track.timescale); - long encoderPadding = Util.scaleLargeTimestamp(paddingTimeUnits, - track.format.sampleRate, track.timescale); - if ((encoderDelay != 0 || encoderPadding != 0) && encoderDelay <= Integer.MAX_VALUE + long encoderDelay = + Util.scaleLargeTimestamp( + editStartTime - timestamps[0], track.format.sampleRate, track.timescale); + long encoderPadding = + Util.scaleLargeTimestamp(paddingTimeUnits, track.format.sampleRate, track.timescale); + if ((encoderDelay != 0 || encoderPadding != 0) + && encoderDelay <= Integer.MAX_VALUE && encoderPadding <= Integer.MAX_VALUE) { gaplessInfoHolder.encoderDelay = (int) encoderDelay; gaplessInfoHolder.encoderPadding = (int) encoderPadding; @@ -905,7 +928,7 @@ private static StsdData parseStsd( for (int i = 0; i < numberOfEntries; i++) { int childStartPosition = stsd.getPosition(); int childAtomSize = stsd.readInt(); - Assertions.checkState(childAtomSize > 0, "childAtomSize should be positive"); + ExtractorUtil.checkContainerInput(childAtomSize > 0, "childAtomSize must be positive"); int childAtomType = stsd.readInt(); if (childAtomType == Atom.TYPE_avc1 || childAtomType == Atom.TYPE_avc3 @@ -923,8 +946,16 @@ private static StsdData parseStsd( || childAtomType == Atom.TYPE_dva1 || childAtomType == Atom.TYPE_dvhe || childAtomType == Atom.TYPE_dvh1) { - parseVideoSampleEntry(stsd, childAtomType, childStartPosition, childAtomSize, trackId, - rotationDegrees, drmInitData, out, i); + parseVideoSampleEntry( + stsd, + childAtomType, + childStartPosition, + childAtomSize, + trackId, + rotationDegrees, + drmInitData, + out, + i); } else if (childAtomType == Atom.TYPE_mp4a || childAtomType == Atom.TYPE_enca || childAtomType == Atom.TYPE_ac_3 @@ -934,6 +965,7 @@ private static StsdData parseStsd( || childAtomType == Atom.TYPE_dtse || childAtomType == Atom.TYPE_dtsh || childAtomType == Atom.TYPE_dtsl + || childAtomType == Atom.TYPE_dtsx || childAtomType == Atom.TYPE_samr || childAtomType == Atom.TYPE_sawb || childAtomType == Atom.TYPE_lpcm @@ -948,13 +980,24 @@ private static StsdData parseStsd( || childAtomType == Atom.TYPE_ulaw || childAtomType == Atom.TYPE_Opus || childAtomType == Atom.TYPE_fLaC) { - parseAudioSampleEntry(stsd, childAtomType, childStartPosition, childAtomSize, trackId, - language, isQuickTime, drmInitData, out, i); - } else if (childAtomType == Atom.TYPE_TTML || childAtomType == Atom.TYPE_tx3g - || childAtomType == Atom.TYPE_wvtt || childAtomType == Atom.TYPE_stpp + parseAudioSampleEntry( + stsd, + childAtomType, + childStartPosition, + childAtomSize, + trackId, + language, + isQuickTime, + drmInitData, + out, + i); + } else if (childAtomType == Atom.TYPE_TTML + || childAtomType == Atom.TYPE_tx3g + || childAtomType == Atom.TYPE_wvtt + || childAtomType == Atom.TYPE_stpp || childAtomType == Atom.TYPE_c608) { - parseTextSampleEntry(stsd, childAtomType, childStartPosition, childAtomSize, trackId, - language, out); + parseTextSampleEntry( + stsd, childAtomType, childStartPosition, childAtomSize, trackId, language, out); } else if (childAtomType == Atom.TYPE_mett) { parseMetaDataSampleEntry(stsd, childAtomType, childStartPosition, trackId, out); } else if (childAtomType == Atom.TYPE_camm) { @@ -1043,8 +1086,10 @@ private static void parseVideoSampleEntry( parseSampleEntryEncryptionData(parent, position, size); if (sampleEntryEncryptionData != null) { atomType = sampleEntryEncryptionData.first; - drmInitData = drmInitData == null ? null - : drmInitData.copyWithSchemeType(sampleEntryEncryptionData.second.schemeType); + drmInitData = + drmInitData == null + ? null + : drmInitData.copyWithSchemeType(sampleEntryEncryptionData.second.schemeType); out.trackEncryptionBoxes[entryIndex] = sampleEntryEncryptionData.second; } parent.setPosition(childPosition); @@ -1064,8 +1109,8 @@ private static void parseVideoSampleEntry( @Nullable List initializationData = null; @Nullable String codecs = null; @Nullable byte[] projectionData = null; - @C.StereoMode - int stereoMode = Format.NO_VALUE; + @C.StereoMode int stereoMode = Format.NO_VALUE; + @Nullable ColorInfo colorInfo = null; while (childPosition - position < size) { parent.setPosition(childPosition); int childStartPosition = parent.getPosition(); @@ -1074,10 +1119,10 @@ private static void parseVideoSampleEntry( // Handle optional terminating four zero bytes in MOV files. break; } - Assertions.checkState(childAtomSize > 0, "childAtomSize should be positive"); + ExtractorUtil.checkContainerInput(childAtomSize > 0, "childAtomSize must be positive"); int childAtomType = parent.readInt(); if (childAtomType == Atom.TYPE_avcC) { - Assertions.checkState(mimeType == null); + ExtractorUtil.checkContainerInput(mimeType == null, /* message= */ null); mimeType = MimeTypes.VIDEO_H264; parent.setPosition(childStartPosition + Atom.HEADER_SIZE); AvcConfig avcConfig = AvcConfig.parse(parent); @@ -1088,7 +1133,7 @@ private static void parseVideoSampleEntry( } codecs = avcConfig.codecs; } else if (childAtomType == Atom.TYPE_hvcC) { - Assertions.checkState(mimeType == null); + ExtractorUtil.checkContainerInput(mimeType == null, /* message= */ null); mimeType = MimeTypes.VIDEO_H265; parent.setPosition(childStartPosition + Atom.HEADER_SIZE); HevcConfig hevcConfig = HevcConfig.parse(parent); @@ -1102,16 +1147,16 @@ private static void parseVideoSampleEntry( mimeType = MimeTypes.VIDEO_DOLBY_VISION; } } else if (childAtomType == Atom.TYPE_vpcC) { - Assertions.checkState(mimeType == null); + ExtractorUtil.checkContainerInput(mimeType == null, /* message= */ null); mimeType = (atomType == Atom.TYPE_vp08) ? MimeTypes.VIDEO_VP8 : MimeTypes.VIDEO_VP9; } else if (childAtomType == Atom.TYPE_av1C) { - Assertions.checkState(mimeType == null); + ExtractorUtil.checkContainerInput(mimeType == null, /* message= */ null); mimeType = MimeTypes.VIDEO_AV1; } else if (childAtomType == Atom.TYPE_d263) { - Assertions.checkState(mimeType == null); + ExtractorUtil.checkContainerInput(mimeType == null, /* message= */ null); mimeType = MimeTypes.VIDEO_H263; } else if (childAtomType == Atom.TYPE_esds) { - Assertions.checkState(mimeType == null); + ExtractorUtil.checkContainerInput(mimeType == null, /* message= */ null); Pair<@NullableType String, byte @NullableType []> mimeTypeAndInitializationDataBytes = parseEsdsFromParent(parent, childStartPosition); mimeType = mimeTypeAndInitializationDataBytes.first; @@ -1146,6 +1191,25 @@ private static void parseVideoSampleEntry( break; } } + } else if (childAtomType == Atom.TYPE_colr) { + int colorType = parent.readInt(); + boolean isNclx = colorType == TYPE_nclx; + if (isNclx || colorType == TYPE_nclc) { + // For more info on syntax, see Section 8.5.2.2 in ISO/IEC 14496-12:2012(E) and + // https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap3/qtff3.html. + int colorPrimaries = parent.readUnsignedShort(); + int transferCharacteristics = parent.readUnsignedShort(); + parent.skipBytes(2); // matrix_coefficients. + boolean fullRangeFlag = isNclx && (parent.readUnsignedByte() & 0b10000000) != 0; + colorInfo = + new ColorInfo( + ColorInfo.isoColorPrimariesToColorSpace(colorPrimaries), + fullRangeFlag ? C.COLOR_RANGE_FULL : C.COLOR_RANGE_LIMITED, + ColorInfo.isoTransferCharacteristicsToColorTransfer(transferCharacteristics), + /* hdrStaticInfo= */ null); + } else { + Log.w(TAG, "Unsupported color type: " + Atom.getAtomTypeString(colorType)); + } } childPosition += childAtomSize; } @@ -1168,6 +1232,7 @@ private static void parseVideoSampleEntry( .setStereoMode(stereoMode) .setInitializationData(initializationData) .setDrmInitData(drmInitData) + .setColorInfo(colorInfo) .build(); } @@ -1253,14 +1318,14 @@ private static void parseAudioSampleEntry( if (quickTimeSoundDescriptionVersion == 0 || quickTimeSoundDescriptionVersion == 1) { channelCount = parent.readUnsignedShort(); - parent.skipBytes(6); // sampleSize, compressionId, packetSize. + parent.skipBytes(6); // sampleSize, compressionId, packetSize. sampleRate = parent.readUnsignedFixedPoint1616(); if (quickTimeSoundDescriptionVersion == 1) { parent.skipBytes(16); } } else if (quickTimeSoundDescriptionVersion == 2) { - parent.skipBytes(16); // always[3,16,Minus2,0,65536], sizeOfStructOnly + parent.skipBytes(16); // always[3,16,Minus2,0,65536], sizeOfStructOnly sampleRate = (int) Math.round(parent.readDouble()); channelCount = parent.readUnsignedIntToInt(); @@ -1280,8 +1345,10 @@ private static void parseAudioSampleEntry( parseSampleEntryEncryptionData(parent, position, size); if (sampleEntryEncryptionData != null) { atomType = sampleEntryEncryptionData.first; - drmInitData = drmInitData == null ? null - : drmInitData.copyWithSchemeType(sampleEntryEncryptionData.second.schemeType); + drmInitData = + drmInitData == null + ? null + : drmInitData.copyWithSchemeType(sampleEntryEncryptionData.second.schemeType); out.trackEncryptionBoxes[entryIndex] = sampleEntryEncryptionData.second; } parent.setPosition(childPosition); @@ -1305,6 +1372,8 @@ private static void parseAudioSampleEntry( mimeType = MimeTypes.AUDIO_DTS_HD; } else if (atomType == Atom.TYPE_dtse) { mimeType = MimeTypes.AUDIO_DTS_EXPRESS; + } else if (atomType == Atom.TYPE_dtsx) { + mimeType = MimeTypes.AUDIO_DTS_UHD; } else if (atomType == Atom.TYPE_samr) { mimeType = MimeTypes.AUDIO_AMR_NB; } else if (atomType == Atom.TYPE_sawb) { @@ -1337,7 +1406,7 @@ private static void parseAudioSampleEntry( while (childPosition - position < size) { parent.setPosition(childPosition); int childAtomSize = parent.readInt(); - Assertions.checkState(childAtomSize > 0, "childAtomSize should be positive"); + ExtractorUtil.checkContainerInput(childAtomSize > 0, "childAtomSize must be positive"); int childAtomType = parent.readInt(); if (childAtomType == Atom.TYPE_mhaC) { // See ISO_IEC_23008-3;2019 MHADecoderConfigurationRecord @@ -1374,12 +1443,12 @@ private static void parseAudioSampleEntry( } } else if (childAtomType == Atom.TYPE_dac3) { parent.setPosition(Atom.HEADER_SIZE + childPosition); - out.format = Ac3Util.parseAc3AnnexFFormat(parent, Integer.toString(trackId), language, - drmInitData); + out.format = + Ac3Util.parseAc3AnnexFFormat(parent, Integer.toString(trackId), language, drmInitData); } else if (childAtomType == Atom.TYPE_dec3) { parent.setPosition(Atom.HEADER_SIZE + childPosition); - out.format = Ac3Util.parseEAc3AnnexFFormat(parent, Integer.toString(trackId), language, - drmInitData); + out.format = + Ac3Util.parseEAc3AnnexFFormat(parent, Integer.toString(trackId), language, drmInitData); } else if (childAtomType == Atom.TYPE_dac4) { parent.setPosition(Atom.HEADER_SIZE + childPosition); out.format = @@ -1448,12 +1517,13 @@ private static void parseAudioSampleEntry( * Returns the position of the esds box within a parent, or {@link C#POSITION_UNSET} if no esds * box is found */ - private static int findEsdsPosition(ParsableByteArray parent, int position, int size) { + private static int findEsdsPosition(ParsableByteArray parent, int position, int size) + throws ParserException { int childAtomPosition = parent.getPosition(); while (childAtomPosition - position < size) { parent.setPosition(childAtomPosition); int childAtomSize = parent.readInt(); - Assertions.checkState(childAtomSize > 0, "childAtomSize should be positive"); + ExtractorUtil.checkContainerInput(childAtomSize > 0, "childAtomSize must be positive"); int childType = parent.readInt(); if (childType == Atom.TYPE_esds) { return childAtomPosition; @@ -1513,12 +1583,12 @@ private static int findEsdsPosition(ParsableByteArray parent, int position, int */ @Nullable private static Pair parseSampleEntryEncryptionData( - ParsableByteArray parent, int position, int size) { + ParsableByteArray parent, int position, int size) throws ParserException { int childPosition = parent.getPosition(); while (childPosition - position < size) { parent.setPosition(childPosition); int childAtomSize = parent.readInt(); - Assertions.checkState(childAtomSize > 0, "childAtomSize should be positive"); + ExtractorUtil.checkContainerInput(childAtomSize > 0, "childAtomSize must be positive"); int childAtomType = parent.readInt(); if (childAtomType == Atom.TYPE_sinf) { @Nullable @@ -1535,7 +1605,7 @@ private static Pair parseSampleEntryEncryptionData( @Nullable /* package */ static Pair parseCommonEncryptionSinfFromParent( - ParsableByteArray parent, int position, int size) { + ParsableByteArray parent, int position, int size) throws ParserException { int childPosition = position + Atom.HEADER_SIZE; int schemeInformationBoxPosition = C.POSITION_UNSET; int schemeInformationBoxSize = 0; @@ -1558,17 +1628,19 @@ private static Pair parseSampleEntryEncryptionData( childPosition += childAtomSize; } - if (C.CENC_TYPE_cenc.equals(schemeType) || C.CENC_TYPE_cbc1.equals(schemeType) - || C.CENC_TYPE_cens.equals(schemeType) || C.CENC_TYPE_cbcs.equals(schemeType)) { - Assertions.checkStateNotNull(dataFormat, "frma atom is mandatory"); - Assertions.checkState( + if (C.CENC_TYPE_cenc.equals(schemeType) + || C.CENC_TYPE_cbc1.equals(schemeType) + || C.CENC_TYPE_cens.equals(schemeType) + || C.CENC_TYPE_cbcs.equals(schemeType)) { + ExtractorUtil.checkContainerInput(dataFormat != null, "frma atom is mandatory"); + ExtractorUtil.checkContainerInput( schemeInformationBoxPosition != C.POSITION_UNSET, "schi atom is mandatory"); + @Nullable TrackEncryptionBox encryptionBox = - Assertions.checkStateNotNull( - parseSchiFromParent( - parent, schemeInformationBoxPosition, schemeInformationBoxSize, schemeType), - "tenc atom is mandatory"); - return Pair.create(dataFormat, encryptionBox); + parseSchiFromParent( + parent, schemeInformationBoxPosition, schemeInformationBoxSize, schemeType); + ExtractorUtil.checkContainerInput(encryptionBox != null, "tenc atom is mandatory"); + return Pair.create(dataFormat, castNonNull(encryptionBox)); } else { return null; } @@ -1605,8 +1677,14 @@ private static TrackEncryptionBox parseSchiFromParent( constantIv = new byte[constantIvSize]; parent.readBytes(constantIv, 0, constantIvSize); } - return new TrackEncryptionBox(defaultIsProtected, schemeType, defaultPerSampleIvSize, - defaultKeyId, defaultCryptByteBlock, defaultSkipByteBlock, constantIv); + return new TrackEncryptionBox( + defaultIsProtected, + schemeType, + defaultPerSampleIvSize, + defaultKeyId, + defaultCryptByteBlock, + defaultSkipByteBlock, + constantIv); } childPosition += childAtomSize; } @@ -1672,8 +1750,9 @@ private static final class ChunkIterator { private int nextSamplesPerChunkChangeIndex; private int remainingSamplesPerChunkChanges; - public ChunkIterator(ParsableByteArray stsc, ParsableByteArray chunkOffsets, - boolean chunkOffsetsAreLongs) { + public ChunkIterator( + ParsableByteArray stsc, ParsableByteArray chunkOffsets, boolean chunkOffsetsAreLongs) + throws ParserException { this.stsc = stsc; this.chunkOffsets = chunkOffsets; this.chunkOffsetsAreLongs = chunkOffsetsAreLongs; @@ -1681,7 +1760,7 @@ public ChunkIterator(ParsableByteArray stsc, ParsableByteArray chunkOffsets, length = chunkOffsets.readUnsignedIntToInt(); stsc.setPosition(Atom.FULL_HEADER_SIZE); remainingSamplesPerChunkChanges = stsc.readUnsignedIntToInt(); - Assertions.checkState(stsc.readInt() == 1, "first_chunk must be 1"); + ExtractorUtil.checkContainerInput(stsc.readInt() == 1, "first_chunk must be 1"); index = -1; } @@ -1689,22 +1768,23 @@ public boolean moveNext() { if (++index == length) { return false; } - offset = chunkOffsetsAreLongs ? chunkOffsets.readUnsignedLongToLong() - : chunkOffsets.readUnsignedInt(); + offset = + chunkOffsetsAreLongs + ? chunkOffsets.readUnsignedLongToLong() + : chunkOffsets.readUnsignedInt(); if (index == nextSamplesPerChunkChangeIndex) { numSamples = stsc.readUnsignedIntToInt(); stsc.skipBytes(4); // Skip sample_description_index - nextSamplesPerChunkChangeIndex = --remainingSamplesPerChunkChanges > 0 - ? (stsc.readUnsignedIntToInt() - 1) : C.INDEX_UNSET; + nextSamplesPerChunkChangeIndex = + --remainingSamplesPerChunkChanges > 0 + ? (stsc.readUnsignedIntToInt() - 1) + : C.INDEX_UNSET; } return true; } - } - /** - * Holds data parsed from a tkhd atom. - */ + /** Holds data parsed from a tkhd atom. */ private static final class TkhdData { private final int id; @@ -1716,12 +1796,9 @@ public TkhdData(int id, long duration, int rotationDegrees) { this.duration = duration; this.rotationDegrees = rotationDegrees; } - } - /** - * Holds data parsed from an stsd atom and its children. - */ + /** Holds data parsed from an stsd atom and its children. */ private static final class StsdData { public static final int STSD_HEADER_SIZE = 8; @@ -1736,17 +1813,12 @@ public StsdData(int numberOfEntries) { trackEncryptionBoxes = new TrackEncryptionBox[numberOfEntries]; requiredSampleTransformation = Track.TRANSFORMATION_NONE; } - } - /** - * A box containing sample sizes (e.g. stsz, stz2). - */ + /** A box containing sample sizes (e.g. stsz, stz2). */ private interface SampleSizeBox { - /** - * Returns the number of samples. - */ + /** Returns the number of samples. */ int getSampleCount(); /** Returns the size of each sample if fixed, or {@link C#LENGTH_UNSET} otherwise. */ @@ -1756,9 +1828,7 @@ private interface SampleSizeBox { int readNextSampleSize(); } - /** - * An stsz sample size box. - */ + /** An stsz sample size box. */ /* package */ static final class StszSampleSizeBox implements SampleSizeBox { private final int fixedSampleSize; @@ -1804,9 +1874,7 @@ public int readNextSampleSize() { } } - /** - * An stz2 sample size box. - */ + /** An stz2 sample size box. */ /* package */ static final class Stz2SampleSizeBox implements SampleSizeBox { private final ParsableByteArray data; @@ -1854,5 +1922,4 @@ public int readNextSampleSize() { } } } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/DefaultSampleValues.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/DefaultSampleValues.java index 1ec02373567..f1f6f577745 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/DefaultSampleValues.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/DefaultSampleValues.java @@ -28,5 +28,4 @@ public DefaultSampleValues(int sampleDescriptionIndex, int duration, int size, i this.size = size; this.flags = flags; } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/FixedSampleSizeRechunker.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/FixedSampleSizeRechunker.java index 5ebc0a3587d..ae16c8107f4 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/FixedSampleSizeRechunker.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/FixedSampleSizeRechunker.java @@ -26,9 +26,7 @@ */ /* package */ final class FixedSampleSizeRechunker { - /** - * The result of a rechunking operation. - */ + /** The result of a rechunking operation. */ public static final class Results { public final long[] offsets; @@ -52,12 +50,9 @@ private Results( this.flags = flags; this.duration = duration; } - } - /** - * Maximum number of bytes for each buffer in rechunked output. - */ + /** Maximum number of bytes for each buffer in rechunked output. */ private static final int MAX_SAMPLE_SIZE = 8 * 1024; /** @@ -68,7 +63,10 @@ private Results( * @param chunkSampleCounts Sample counts for each of the MP4 stream's chunks. * @param timestampDeltaInTimeUnits Timestamp delta between each sample in time units. */ - public static Results rechunk(int fixedSampleSize, long[] chunkOffsets, int[] chunkSampleCounts, + public static Results rechunk( + int fixedSampleSize, + long[] chunkOffsets, + int[] chunkSampleCounts, long timestampDeltaInTimeUnits) { int maxSampleCount = MAX_SAMPLE_SIZE / fixedSampleSize; diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java index ef71d825590..b72159be1d5 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java @@ -91,8 +91,8 @@ public class FragmentedMp4Extractor implements Extractor { * Flag to work around an issue in some video streams where every frame is marked as a sync frame. * The workaround overrides the sync frame flags in the stream, forcing them to false except for * the first sample in each segment. - *

    - * This flag does nothing if the stream is not a video stream. + * + *

    This flag does nothing if the stream is not a video stream. */ public static final int FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME = 1; /** Flag to ignore any tfdt boxes in the stream. */ @@ -110,6 +110,7 @@ public class FragmentedMp4Extractor implements Extractor { @SuppressWarnings("ConstantCaseForConstants") private static final int SAMPLE_GROUP_TYPE_seig = 0x73656967; + private static final byte[] PIFF_SAMPLE_ENCRYPTION_BOX_EXTENDED_TYPE = new byte[] {-94, 57, 79, 82, 90, -101, 79, 20, -94, 68, 108, 66, 124, 100, -115, -12}; @@ -182,9 +183,7 @@ public FragmentedMp4Extractor() { this(0); } - /** - * @param flags Flags that control the extractor's behavior. - */ + /** @param flags Flags that control the extractor's behavior. */ public FragmentedMp4Extractor(@Flags int flags) { this(flags, /* timestampAdjuster= */ null); } @@ -380,7 +379,8 @@ private boolean readAtomHeader(ExtractorInput input) throws IOException { } if (atomSize < atomHeaderBytesRead) { - throw new ParserException("Atom size less than header length (unsupported)."); + throw ParserException.createForUnsupportedContainerFeature( + "Atom size less than header length (unsupported)."); } long atomPosition = input.getPosition() - atomHeaderBytesRead; @@ -421,10 +421,12 @@ private boolean readAtomHeader(ExtractorInput input) throws IOException { } } else if (shouldParseLeafAtom(atomType)) { if (atomHeaderBytesRead != Atom.HEADER_SIZE) { - throw new ParserException("Leaf atom defines extended atom size (unsupported)."); + throw ParserException.createForUnsupportedContainerFeature( + "Leaf atom defines extended atom size (unsupported)."); } if (atomSize > Integer.MAX_VALUE) { - throw new ParserException("Leaf atom with length > 2147483647 (unsupported)."); + throw ParserException.createForUnsupportedContainerFeature( + "Leaf atom with length > 2147483647 (unsupported)."); } ParsableByteArray atomData = new ParsableByteArray((int) atomSize); System.arraycopy(atomHeader.getData(), 0, atomData.getData(), 0, Atom.HEADER_SIZE); @@ -432,7 +434,8 @@ private boolean readAtomHeader(ExtractorInput input) throws IOException { parserState = STATE_READING_ATOM_PAYLOAD; } else { if (atomSize > Integer.MAX_VALUE) { - throw new ParserException("Skipping atom with length > 2147483647 (unsupported)."); + throw ParserException.createForUnsupportedContainerFeature( + "Skipping atom with length > 2147483647 (unsupported)."); } atomData = null; parserState = STATE_READING_ATOM_PAYLOAD; @@ -685,13 +688,16 @@ private static Pair parseTrex(ParsableByteArray tr int defaultSampleSize = trex.readInt(); int defaultSampleFlags = trex.readInt(); - return Pair.create(trackId, new DefaultSampleValues(defaultSampleDescriptionIndex, - defaultSampleDuration, defaultSampleSize, defaultSampleFlags)); + return Pair.create( + trackId, + new DefaultSampleValues( + defaultSampleDescriptionIndex, + defaultSampleDuration, + defaultSampleSize, + defaultSampleFlags)); } - /** - * Parses an mehd atom (defined in 14496-12). - */ + /** Parses an mehd atom (defined in 14496-12). */ private static long parseMehd(ParsableByteArray mehd) { mehd.setPosition(Atom.HEADER_SIZE); int fullAtom = mehd.readInt(); @@ -699,9 +705,13 @@ private static long parseMehd(ParsableByteArray mehd) { return version == 0 ? mehd.readUnsignedInt() : mehd.readUnsignedLongToLong(); } - private static void parseMoof(ContainerAtom moof, SparseArray trackBundles, + private static void parseMoof( + ContainerAtom moof, + SparseArray trackBundles, boolean haveSideloadedTrack, - @Flags int flags, byte[] extendedTypeScratch) throws ParserException { + @Flags int flags, + byte[] extendedTypeScratch) + throws ParserException { int moofContainerChildrenSize = moof.containerChildren.size(); for (int i = 0; i < moofContainerChildrenSize; i++) { Atom.ContainerAtom child = moof.containerChildren.get(i); @@ -712,12 +722,14 @@ private static void parseMoof(ContainerAtom moof, SparseArray track } } - /** - * Parses a traf atom (defined in 14496-12). - */ - private static void parseTraf(ContainerAtom traf, SparseArray trackBundles, + /** Parses a traf atom (defined in 14496-12). */ + private static void parseTraf( + ContainerAtom traf, + SparseArray trackBundles, boolean haveSideloadedTrack, - @Flags int flags, byte[] extendedTypeScratch) throws ParserException { + @Flags int flags, + byte[] extendedTypeScratch) + throws ParserException { LeafAtom tfhd = checkNotNull(traf.getLeafAtomOfType(Atom.TYPE_tfhd)); @Nullable TrackBundle trackBundle = parseTfhd(tfhd.data, trackBundles, haveSideloadedTrack); if (trackBundle == null) { @@ -805,8 +817,9 @@ private static void parseTruns(ContainerAtom traf, TrackBundle trackBundle, @Fla } } - private static void parseSaiz(TrackEncryptionBox encryptionBox, ParsableByteArray saiz, - TrackFragment out) throws ParserException { + private static void parseSaiz( + TrackEncryptionBox encryptionBox, ParsableByteArray saiz, TrackFragment out) + throws ParserException { int vectorSize = encryptionBox.perSampleIvSize; saiz.setPosition(Atom.HEADER_SIZE); int fullAtom = saiz.readInt(); @@ -818,11 +831,12 @@ private static void parseSaiz(TrackEncryptionBox encryptionBox, ParsableByteArra int sampleCount = saiz.readUnsignedIntToInt(); if (sampleCount > out.sampleCount) { - throw new ParserException( + throw ParserException.createForMalformedContainer( "Saiz sample count " + sampleCount + " is greater than fragment sample count" - + out.sampleCount); + + out.sampleCount, + /* cause= */ null); } int totalSize = 0; @@ -861,7 +875,8 @@ private static void parseSaio(ParsableByteArray saio, TrackFragment out) throws int entryCount = saio.readUnsignedIntToInt(); if (entryCount != 1) { // We only support one trun element currently, so always expect one entry. - throw new ParserException("Unexpected saio entry count: " + entryCount); + throw ParserException.createForMalformedContainer( + "Unexpected saio entry count: " + entryCount, /* cause= */ null); } int version = Atom.parseFullAtomVersion(fullAtom); @@ -917,8 +932,12 @@ private static TrackBundle parseTfhd( ((atomFlags & 0x20 /* default_sample_flags_present */) != 0) ? tfhd.readInt() : defaultSampleValues.flags; - trackBundle.fragment.header = new DefaultSampleValues(defaultSampleDescriptionIndex, - defaultSampleDuration, defaultSampleSize, defaultSampleFlags); + trackBundle.fragment.header = + new DefaultSampleValues( + defaultSampleDescriptionIndex, + defaultSampleDuration, + defaultSampleSize, + defaultSampleFlags); return trackBundle; } @@ -984,7 +1003,8 @@ private static int parseTrun( // Currently we only support a single edit that moves the entire media timeline (indicated by // duration == 0). Other uses of edit lists are uncommon and unsupported. - if (track.editListDurations != null && track.editListDurations.length == 1 + if (track.editListDurations != null + && track.editListDurations.length == 1 && track.editListDurations[0] == 0) { edtsOffsetUs = Util.scaleLargeTimestamp( @@ -996,8 +1016,9 @@ private static int parseTrun( long[] sampleDecodingTimeUsTable = fragment.sampleDecodingTimeUsTable; boolean[] sampleIsSyncFrameTable = fragment.sampleIsSyncFrameTable; - boolean workaroundEveryVideoFrameIsSyncFrame = track.type == C.TRACK_TYPE_VIDEO - && (flags & FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME) != 0; + boolean workaroundEveryVideoFrameIsSyncFrame = + track.type == C.TRACK_TYPE_VIDEO + && (flags & FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME) != 0; int trackRunEnd = trackRunStart + fragment.trunLength[index]; long timescale = track.timescale; @@ -1030,8 +1051,8 @@ private static int parseTrun( sampleDecodingTimeUsTable[i] += trackBundle.moovSampleTable.durationUs; } sampleSizeTable[i] = sampleSize; - sampleIsSyncFrameTable[i] = ((sampleFlags >> 16) & 0x1) == 0 - && (!workaroundEveryVideoFrameIsSyncFrame || i == 0); + sampleIsSyncFrameTable[i] = + ((sampleFlags >> 16) & 0x1) == 0 && (!workaroundEveryVideoFrameIsSyncFrame || i == 0); cumulativeTime += sampleDuration; } fragment.nextFragmentDecodeTime = cumulativeTime; @@ -1040,13 +1061,15 @@ private static int parseTrun( private static int checkNonNegative(int value) throws ParserException { if (value < 0) { - throw new ParserException("Unexpected negative value: " + value); + throw ParserException.createForMalformedContainer( + "Unexpected negative value: " + value, /* cause= */ null); } return value; } - private static void parseUuid(ParsableByteArray uuid, TrackFragment out, - byte[] extendedTypeScratch) throws ParserException { + private static void parseUuid( + ParsableByteArray uuid, TrackFragment out, byte[] extendedTypeScratch) + throws ParserException { uuid.setPosition(Atom.HEADER_SIZE); uuid.readBytes(extendedTypeScratch, 0, 16); @@ -1073,7 +1096,8 @@ private static void parseSenc(ParsableByteArray senc, int offset, TrackFragment if ((flags & 0x01 /* override_track_encryption_box_parameters */) != 0) { // TODO: Implement this. - throw new ParserException("Overriding TrackEncryptionBox parameters is unsupported."); + throw ParserException.createForUnsupportedContainerFeature( + "Overriding TrackEncryptionBox parameters is unsupported."); } boolean subsampleEncryption = (flags & 0x02 /* use_subsample_encryption */) != 0; @@ -1083,11 +1107,12 @@ private static void parseSenc(ParsableByteArray senc, int offset, TrackFragment Arrays.fill(out.sampleHasSubsampleEncryptionTable, 0, out.sampleCount, false); return; } else if (sampleCount != out.sampleCount) { - throw new ParserException( + throw ParserException.createForMalformedContainer( "Senc sample count " + sampleCount + " is different from fragment sample count" - + out.sampleCount); + + out.sampleCount, + /* cause= */ null); } Arrays.fill(out.sampleHasSubsampleEncryptionTable, 0, sampleCount, subsampleEncryption); @@ -1126,7 +1151,8 @@ private static void parseSampleGroups( sbgp.skipBytes(4); // grouping_type_parameter. } if (sbgp.readInt() != 1) { // entry_count. - throw new ParserException("Entry count in sbgp != 1 (unsupported)."); + throw ParserException.createForUnsupportedContainerFeature( + "Entry count in sbgp != 1 (unsupported)."); } sgpd.setPosition(Atom.HEADER_SIZE); @@ -1134,13 +1160,15 @@ private static void parseSampleGroups( sgpd.skipBytes(4); // grouping_type == seig. if (sgpdVersion == 1) { if (sgpd.readUnsignedInt() == 0) { - throw new ParserException("Variable length description in sgpd found (unsupported)"); + throw ParserException.createForUnsupportedContainerFeature( + "Variable length description in sgpd found (unsupported)"); } } else if (sgpdVersion >= 2) { sgpd.skipBytes(4); // default_sample_description_index. } if (sgpd.readUnsignedInt() != 1) { // entry_count. - throw new ParserException("Entry count in sgpd != 1 (unsupported)."); + throw ParserException.createForUnsupportedContainerFeature( + "Entry count in sgpd != 1 (unsupported)."); } // CencSampleEncryptionInformationGroupEntry @@ -1162,8 +1190,15 @@ private static void parseSampleGroups( sgpd.readBytes(constantIv, 0, constantIvSize); } out.definesEncryptionData = true; - out.trackEncryptionBox = new TrackEncryptionBox(isProtected, schemeType, perSampleIvSize, keyId, - cryptByteBlock, skipByteBlock, constantIv); + out.trackEncryptionBox = + new TrackEncryptionBox( + isProtected, + schemeType, + perSampleIvSize, + keyId, + cryptByteBlock, + skipByteBlock, + constantIv); } /** @@ -1191,8 +1226,8 @@ private static Pair parseSidx(ParsableByteArray atom, long inp earliestPresentationTime = atom.readUnsignedLongToLong(); offset += atom.readUnsignedLongToLong(); } - long earliestPresentationTimeUs = Util.scaleLargeTimestamp(earliestPresentationTime, - C.MICROS_PER_SECOND, timescale); + long earliestPresentationTimeUs = + Util.scaleLargeTimestamp(earliestPresentationTime, C.MICROS_PER_SECOND, timescale); atom.skipBytes(2); @@ -1209,7 +1244,8 @@ private static Pair parseSidx(ParsableByteArray atom, long inp int type = 0x80000000 & firstInt; if (type != 0) { - throw new ParserException("Unhandled indirect reference"); + throw ParserException.createForMalformedContainer( + "Unhandled indirect reference", /* cause= */ null); } long referenceDuration = atom.readUnsignedInt(); @@ -1227,8 +1263,8 @@ private static Pair parseSidx(ParsableByteArray atom, long inp offset += sizes[i]; } - return Pair.create(earliestPresentationTimeUs, - new ChunkIndex(sizes, offsets, durationsUs, timesUs)); + return Pair.create( + earliestPresentationTimeUs, new ChunkIndex(sizes, offsets, durationsUs, timesUs)); } private void readEncryptionData(ExtractorInput input) throws IOException { @@ -1249,7 +1285,8 @@ private void readEncryptionData(ExtractorInput input) throws IOException { } int bytesToSkip = (int) (nextDataOffset - input.getPosition()); if (bytesToSkip < 0) { - throw new ParserException("Offset to encryption data was negative."); + throw ParserException.createForMalformedContainer( + "Offset to encryption data was negative.", /* cause= */ null); } input.skipFully(bytesToSkip); nextTrackBundle.fragment.fillEncryptionData(input); @@ -1279,7 +1316,8 @@ private boolean readSample(ExtractorInput input) throws IOException { // read the header of the next atom. int bytesToSkip = (int) (endOfMdatPosition - input.getPosition()); if (bytesToSkip < 0) { - throw new ParserException("Offset to end of mdat was negative."); + throw ParserException.createForMalformedContainer( + "Offset to end of mdat was negative.", /* cause= */ null); } input.skipFully(bytesToSkip); enterReadingAtomHeaderState(); @@ -1357,7 +1395,8 @@ private boolean readSample(ExtractorInput input) throws IOException { nalPrefix.setPosition(0); int nalLengthInt = nalPrefix.readInt(); if (nalLengthInt < 1) { - throw new ParserException("Invalid NAL length"); + throw ParserException.createForMalformedContainer( + "Invalid NAL length", /* cause= */ null); } sampleCurrentNalBytesRemaining = nalLengthInt - 1; // Write a start code for the current NAL unit. @@ -1524,14 +1563,18 @@ private static boolean shouldParseLeafAtom(int atom) { /** Returns whether the extractor should decode a container atom with type {@code atom}. */ private static boolean shouldParseContainerAtom(int atom) { - return atom == Atom.TYPE_moov || atom == Atom.TYPE_trak || atom == Atom.TYPE_mdia - || atom == Atom.TYPE_minf || atom == Atom.TYPE_stbl || atom == Atom.TYPE_moof - || atom == Atom.TYPE_traf || atom == Atom.TYPE_mvex || atom == Atom.TYPE_edts; + return atom == Atom.TYPE_moov + || atom == Atom.TYPE_trak + || atom == Atom.TYPE_mdia + || atom == Atom.TYPE_minf + || atom == Atom.TYPE_stbl + || atom == Atom.TYPE_moof + || atom == Atom.TYPE_traf + || atom == Atom.TYPE_mvex + || atom == Atom.TYPE_edts; } - /** - * Holds data corresponding to a metadata sample. - */ + /** Holds data corresponding to a metadata sample. */ private static final class MetadataSampleInfo { public final long presentationTimeDeltaUs; @@ -1541,12 +1584,9 @@ public MetadataSampleInfo(long presentationTimeDeltaUs, int size) { this.presentationTimeDeltaUs = presentationTimeDeltaUs; this.size = size; } - } - /** - * Holds data corresponding to a single track. - */ + /** Holds data corresponding to a single track. */ private static final class TrackBundle { private static final int SINGLE_SUBSAMPLE_ENCRYPTION_DATA_LENGTH = 8; @@ -1817,7 +1857,5 @@ public TrackEncryptionBox getEncryptionBoxIfEncrypted() { : moovSampleTable.track.getSampleDescriptionEncryptionBox(sampleDescriptionIndex); return encryptionBox != null && encryptionBox.isEncrypted ? encryptionBox : null; } - } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/MetadataUtil.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/MetadataUtil.java index a5470dace62..9aa19cff569 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/MetadataUtil.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/MetadataUtil.java @@ -594,5 +594,4 @@ private static int parseUint8AttributeValue(ParsableByteArray data) { Log.w(TAG, "Failed to parse uint8 attribute value"); return -1; } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.java index 092dbae496e..d542fa85450 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.java @@ -133,7 +133,7 @@ public final class Mp4Extractor implements Extractor, SeekMap { */ private static final long MAXIMUM_READ_AHEAD_BYTES_STREAM = 10 * 1024 * 1024; - private final @Flags int flags; + @Flags private final int flags; // Temporary arrays. private final ParsableByteArray nalStartCode; @@ -166,9 +166,7 @@ public final class Mp4Extractor implements Extractor, SeekMap { @FileType private int fileType; @Nullable private MotionPhotoMetadata motionPhotoMetadata; - /** - * Creates a new extractor for unfragmented MP4 streams. - */ + /** Creates a new extractor for unfragmented MP4 streams. */ public Mp4Extractor() { this(/* flags= */ 0); } @@ -362,7 +360,8 @@ private boolean readAtomHeader(ExtractorInput input) throws IOException { } if (atomSize < atomHeaderBytesRead) { - throw new ParserException("Atom size less than header length (unsupported)."); + throw ParserException.createForUnsupportedContainerFeature( + "Atom size less than header length (unsupported)."); } if (shouldParseContainerAtom(atomType)) { @@ -452,9 +451,7 @@ private void processAtomEnded(long atomEndPosition) throws ParserException { } } - /** - * Updates the stored track metadata to reflect the contents of the specified moov atom. - */ + /** Updates the stored track metadata to reflect the contents of the specified moov atom. */ private void processMoovAtom(ContainerAtom moov) throws ParserException { int firstVideoTrackIndex = C.INDEX_UNSET; long durationUs = C.TIME_UNSET; @@ -503,8 +500,8 @@ private void processMoovAtom(ContainerAtom moov) throws ParserException { long trackDurationUs = track.durationUs != C.TIME_UNSET ? track.durationUs : trackSampleTable.durationUs; durationUs = max(durationUs, trackDurationUs); - Mp4Track mp4Track = new Mp4Track(track, trackSampleTable, - extractorOutput.track(i, track.type)); + Mp4Track mp4Track = + new Mp4Track(track, trackSampleTable, extractorOutput.track(i, track.type)); // Each sample has up to three bytes of overhead for the start code that replaces its length. // Allow ten source samples per output sample, like the platform extractor. @@ -602,7 +599,8 @@ private int readSample(ExtractorInput input, PositionHolder positionHolder) thro nalLength.setPosition(0); int nalLengthInt = nalLength.readInt(); if (nalLengthInt < 0) { - throw new ParserException("Invalid NAL length"); + throw ParserException.createForMalformedContainer( + "Invalid NAL length", /* cause= */ null); } sampleCurrentNalBytesRemaining = nalLengthInt; // Write a start code for the current NAL unit. @@ -634,8 +632,12 @@ private int readSample(ExtractorInput input, PositionHolder positionHolder) thro sampleCurrentNalBytesRemaining -= writtenBytes; } } - trackOutput.sampleMetadata(track.sampleTable.timestampsUs[sampleIndex], - track.sampleTable.flags[sampleIndex], sampleSize, 0, null); + trackOutput.sampleMetadata( + track.sampleTable.timestampsUs[sampleIndex], + track.sampleTable.flags[sampleIndex], + sampleSize, + 0, + null); track.sampleIndex++; sampleTrackIndex = C.INDEX_UNSET; sampleBytesRead = 0; @@ -908,7 +910,5 @@ public Mp4Track(Track track, TrackSampleTable sampleTable, TrackOutput trackOutp this.sampleTable = sampleTable; this.trackOutput = trackOutput; } - } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/PsshAtomUtil.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/PsshAtomUtil.java index c47ca8d6ba1..3be0946e94d 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/PsshAtomUtil.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/PsshAtomUtil.java @@ -104,8 +104,8 @@ public static UUID parseUuid(byte[] atom) { /** * Parses the version from a PSSH atom. Version 0 and 1 PSSH atoms are supported. - *

    - * The version is only parsed if the data is a valid PSSH atom. + * + *

    The version is only parsed if the data is a valid PSSH atom. * * @param atom The atom to parse. * @return The parsed version. -1 if the input is not a valid PSSH atom, or if the PSSH atom has @@ -201,7 +201,5 @@ public PsshAtom(UUID uuid, int version, byte[] schemeData) { this.version = version; this.schemeData = schemeData; } - } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/SefReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/SefReader.java index ccf5180f412..36586e70595 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/SefReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/SefReader.java @@ -231,7 +231,7 @@ private static SlowMotionData readSlowMotionData(ParsableByteArray data, int dat for (int i = 0; i < segmentStrings.size(); i++) { List values = COLON_SPLITTER.splitToList(segmentStrings.get(i)); if (values.size() != 3) { - throw new ParserException(); + throw ParserException.createForMalformedContainer(/* message= */ null, /* cause= */ null); } try { long startTimeMs = Long.parseLong(values.get(0)); @@ -240,7 +240,7 @@ private static SlowMotionData readSlowMotionData(ParsableByteArray data, int dat int speedDivisor = 1 << (speedMode - 1); segments.add(new SlowMotionData.Segment(startTimeMs, endTimeMs, speedDivisor)); } catch (NumberFormatException e) { - throw new ParserException(e); + throw ParserException.createForMalformedContainer(/* message= */ null, /* cause= */ e); } } return new SlowMotionData(segments); @@ -260,7 +260,7 @@ private static int nameToDataType(String name) throws ParserException { case "Super_SlowMotion_Deflickering_On": return TYPE_SUPER_SLOW_DEFLICKERING_ON; default: - throw new ParserException("Invalid SEF name"); + throw ParserException.createForMalformedContainer("Invalid SEF name", /* cause= */ null); } } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Sniffer.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Sniffer.java index 5a8b467cc2f..2c4a847ee59 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Sniffer.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Sniffer.java @@ -108,8 +108,11 @@ public static boolean sniffUnfragmented(ExtractorInput input, boolean acceptHeic private static boolean sniffInternal(ExtractorInput input, boolean fragmented, boolean acceptHeic) throws IOException { long inputLength = input.getLength(); - int bytesToSearch = (int) (inputLength == C.LENGTH_UNSET || inputLength > SEARCH_LENGTH - ? SEARCH_LENGTH : inputLength); + int bytesToSearch = + (int) + (inputLength == C.LENGTH_UNSET || inputLength > SEARCH_LENGTH + ? SEARCH_LENGTH + : inputLength); ParsableByteArray buffer = new ParsableByteArray(64); int bytesSearched = 0; @@ -223,5 +226,4 @@ private static boolean isCompatibleBrand(int brand, boolean acceptHeic) { private Sniffer() { // Prevent instantiation. } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Track.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Track.java index 1e917f825d1..3771be0952b 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Track.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Track.java @@ -34,18 +34,12 @@ public final class Track { @Retention(RetentionPolicy.SOURCE) @IntDef({TRANSFORMATION_NONE, TRANSFORMATION_CEA608_CDAT}) public @interface Transformation {} - /** - * A no-op sample transformation. - */ + /** A no-op sample transformation. */ public static final int TRANSFORMATION_NONE = 0; - /** - * A transformation for caption samples in cdat atoms. - */ + /** A transformation for caption samples in cdat atoms. */ public static final int TRANSFORMATION_CEA608_CDAT = 1; - /** - * The track identifier. - */ + /** The track identifier. */ public final int id; /** @@ -53,24 +47,16 @@ public final class Track { */ public final int type; - /** - * The track timescale, defined as the number of time units that pass in one second. - */ + /** The track timescale, defined as the number of time units that pass in one second. */ public final long timescale; - /** - * The movie timescale. - */ + /** The movie timescale. */ public final long movieTimescale; - /** - * The duration of the track in microseconds, or {@link C#TIME_UNSET} if unknown. - */ + /** The duration of the track in microseconds, or {@link C#TIME_UNSET} if unknown. */ public final long durationUs; - /** - * The format. - */ + /** The format. */ public final Format format; /** @@ -79,14 +65,10 @@ public final class Track { */ @Transformation public final int sampleTransformation; - /** - * Durations of edit list segments in the movie timescale. Null if there is no edit list. - */ + /** Durations of edit list segments in the movie timescale. Null if there is no edit list. */ @Nullable public final long[] editListDurations; - /** - * Media times for edit list segments in the track timescale. Null if there is no edit list. - */ + /** Media times for edit list segments in the track timescale. Null if there is no edit list. */ @Nullable public final long[] editListMediaTimes; /** @@ -97,10 +79,18 @@ public final class Track { @Nullable private final TrackEncryptionBox[] sampleDescriptionEncryptionBoxes; - public Track(int id, int type, long timescale, long movieTimescale, long durationUs, - Format format, @Transformation int sampleTransformation, - @Nullable TrackEncryptionBox[] sampleDescriptionEncryptionBoxes, int nalUnitLengthFieldLength, - @Nullable long[] editListDurations, @Nullable long[] editListMediaTimes) { + public Track( + int id, + int type, + long timescale, + long movieTimescale, + long durationUs, + Format format, + @Transformation int sampleTransformation, + @Nullable TrackEncryptionBox[] sampleDescriptionEncryptionBoxes, + int nalUnitLengthFieldLength, + @Nullable long[] editListDurations, + @Nullable long[] editListMediaTimes) { this.id = id; this.type = type; this.timescale = timescale; @@ -123,7 +113,8 @@ public Track(int id, int type, long timescale, long movieTimescale, long duratio */ @Nullable public TrackEncryptionBox getSampleDescriptionEncryptionBox(int sampleDescriptionIndex) { - return sampleDescriptionEncryptionBoxes == null ? null + return sampleDescriptionEncryptionBoxes == null + ? null : sampleDescriptionEncryptionBoxes[sampleDescriptionIndex]; } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackEncryptionBox.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackEncryptionBox.java index 986c5bb2553..aed1bcf48fb 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackEncryptionBox.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackEncryptionBox.java @@ -29,14 +29,10 @@ public final class TrackEncryptionBox { private static final String TAG = "TrackEncryptionBox"; - /** - * Indicates the encryption state of the samples in the sample group. - */ + /** Indicates the encryption state of the samples in the sample group. */ public final boolean isEncrypted; - /** - * The protection scheme type, as defined by the 'schm' box, or null if unknown. - */ + /** The protection scheme type, as defined by the 'schm' box, or null if unknown. */ @Nullable public final String schemeType; /** @@ -76,8 +72,9 @@ public TrackEncryptionBox( this.schemeType = schemeType; this.perSampleIvSize = perSampleIvSize; this.defaultInitializationVector = defaultInitializationVector; - cryptoData = new TrackOutput.CryptoData(schemeToCryptoMode(schemeType), keyId, - defaultEncryptedBlocks, defaultClearBlocks); + cryptoData = + new TrackOutput.CryptoData( + schemeToCryptoMode(schemeType), keyId, defaultEncryptedBlocks, defaultClearBlocks); } @C.CryptoMode @@ -94,10 +91,12 @@ private static int schemeToCryptoMode(@Nullable String schemeType) { case C.CENC_TYPE_cbcs: return C.CRYPTO_MODE_AES_CBC; default: - Log.w(TAG, "Unsupported protection scheme type '" + schemeType + "'. Assuming AES-CTR " - + "crypto mode."); + Log.w( + TAG, + "Unsupported protection scheme type '" + + schemeType + + "'. Assuming AES-CTR crypto mode."); return C.CRYPTO_MODE_AES_CTR; } } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackFragment.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackFragment.java index 92ce551f488..5a1fc6e0d83 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackFragment.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackFragment.java @@ -21,56 +21,34 @@ import java.io.IOException; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; -/** - * A holder for information corresponding to a single fragment of an mp4 file. - */ +/** A holder for information corresponding to a single fragment of an mp4 file. */ /* package */ final class TrackFragment { /** The default values for samples from the track fragment header. */ public @MonotonicNonNull DefaultSampleValues header; - /** - * The position (byte offset) of the start of fragment. - */ + /** The position (byte offset) of the start of fragment. */ public long atomPosition; - /** - * The position (byte offset) of the start of data contained in the fragment. - */ + /** The position (byte offset) of the start of data contained in the fragment. */ public long dataPosition; - /** - * The position (byte offset) of the start of auxiliary data. - */ + /** The position (byte offset) of the start of auxiliary data. */ public long auxiliaryDataPosition; - /** - * The number of track runs of the fragment. - */ + /** The number of track runs of the fragment. */ public int trunCount; - /** - * The total number of samples in the fragment. - */ + /** The total number of samples in the fragment. */ public int sampleCount; - /** - * The position (byte offset) of the start of sample data of each track run in the fragment. - */ + /** The position (byte offset) of the start of sample data of each track run in the fragment. */ public long[] trunDataPosition; - /** - * The number of samples contained by each track run in the fragment. - */ + /** The number of samples contained by each track run in the fragment. */ public int[] trunLength; - /** - * The size of each sample in the fragment. - */ + /** The size of each sample in the fragment. */ public int[] sampleSizeTable; /** The composition time offset of each sample in the fragment, in microseconds. */ public int[] sampleCompositionTimeOffsetUsTable; /** The decoding time of each sample in the fragment, in microseconds. */ public long[] sampleDecodingTimeUsTable; - /** - * Indicates which samples are sync frames. - */ + /** Indicates which samples are sync frames. */ public boolean[] sampleIsSyncFrameTable; - /** - * Whether the fragment defines encryption data. - */ + /** Whether the fragment defines encryption data. */ public boolean definesEncryptionData; /** * If {@link #definesEncryptionData} is true, indicates which samples use sub-sample encryption. @@ -84,9 +62,7 @@ * otherwise. */ public final ParsableByteArray sampleEncryptionData; - /** - * Whether {@link #sampleEncryptionData} needs populating with the actual encryption data. - */ + /** Whether {@link #sampleEncryptionData} needs populating with the actual encryption data. */ public boolean sampleEncryptionDataNeedsFill; /** * The duration of all the samples defined in the fragments up to and including this one, plus the @@ -113,10 +89,10 @@ public TrackFragment() { /** * Resets the fragment. - *

    - * {@link #sampleCount} and {@link #nextFragmentDecodeTime} are set to 0, and both - * {@link #definesEncryptionData} and {@link #sampleEncryptionDataNeedsFill} is set to false, - * and {@link #trackEncryptionBox} is set to null. + * + *

    {@link #sampleCount} and {@link #nextFragmentDecodeTime} are set to 0, and both {@link + * #definesEncryptionData} and {@link #sampleEncryptionDataNeedsFill} is set to false, and {@link + * #trackEncryptionBox} is set to null. */ public void reset() { trunCount = 0; @@ -129,8 +105,8 @@ public void reset() { /** * Configures the fragment for the specified number of samples. - *

    - * The {@link #sampleCount} of the fragment is set to the specified sample count, and the + * + *

    The {@link #sampleCount} of the fragment is set to the specified sample count, and the * contained tables are resized if necessary such that they are at least this length. * * @param sampleCount The number of samples in the new run. diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackSampleTable.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackSampleTable.java index ca500b29318..5104aeb2097 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackSampleTable.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackSampleTable.java @@ -19,9 +19,7 @@ import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Util; -/** - * Sample table for a track in an MP4 file. - */ +/** Sample table for a track in an MP4 file. */ /* package */ final class TrackSampleTable { /** The track corresponding to this sample table. */ @@ -101,5 +99,4 @@ public int getIndexOfLaterOrEqualSynchronizationSample(long timeUs) { } return C.INDEX_UNSET; } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/FlacReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/FlacReader.java index a86b4350c01..fd7688baade 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/FlacReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/FlacReader.java @@ -32,9 +32,7 @@ import java.util.Arrays; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; -/** - * {@link StreamReader} to extract Flac data out of Ogg byte stream. - */ +/** {@link StreamReader} to extract Flac data out of Ogg byte stream. */ /* package */ final class FlacReader extends StreamReader { private static final byte AUDIO_PACKET_TYPE = (byte) 0xFF; @@ -45,7 +43,9 @@ @Nullable private FlacOggSeeker flacOggSeeker; public static boolean verifyBitstreamType(ParsableByteArray data) { - return data.bytesLeft() >= 5 && data.readUnsignedByte() == 0x7F && // packet type + return data.bytesLeft() >= 5 + && data.readUnsignedByte() == 0x7F + && // packet type data.readUnsignedInt() == 0x464C4143; // ASCII signature "FLAC" } @@ -157,7 +157,5 @@ public SeekMap createSeekMap() { checkState(firstFrameOffset != -1); return new FlacSeekTableSeekMap(streamMetadata, firstFrameOffset); } - } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggExtractor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggExtractor.java index 49c8e2fb3b6..32fb588c755 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggExtractor.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggExtractor.java @@ -74,7 +74,8 @@ public int read(ExtractorInput input, PositionHolder seekPosition) throws IOExce checkStateNotNull(output); // Check that init has been called. if (streamReader == null) { if (!sniffInternal(input)) { - throw new ParserException("Failed to determine bitstream type"); + throw ParserException.createForMalformedContainer( + "Failed to determine bitstream type", /* cause= */ null); } input.resetPeekPosition(); } @@ -114,5 +115,4 @@ private static ParsableByteArray resetPosition(ParsableByteArray scratch) { scratch.setPosition(0); return scratch; } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggPacket.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggPacket.java index dcca44b3d83..b31d3769b22 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggPacket.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggPacket.java @@ -26,22 +26,18 @@ import java.io.IOException; import java.util.Arrays; -/** - * OGG packet class. - */ +/** OGG packet class. */ /* package */ final class OggPacket { private final OggPageHeader pageHeader = new OggPageHeader(); - private final ParsableByteArray packetArray = new ParsableByteArray( - new byte[OggPageHeader.MAX_PAGE_PAYLOAD], 0); + private final ParsableByteArray packetArray = + new ParsableByteArray(new byte[OggPageHeader.MAX_PAGE_PAYLOAD], 0); private int currentSegmentIndex = C.INDEX_UNSET; private int segmentCount; private boolean populated; - /** - * Resets this reader. - */ + /** Resets this reader. */ public void reset() { pageHeader.reset(); packetArray.reset(/* limit= */ 0); @@ -99,8 +95,8 @@ public boolean populate(ExtractorInput input) throws IOException { populated = pageHeader.laces[segmentIndex - 1] != 255; } // Advance now since we are sure reading didn't throw an exception. - currentSegmentIndex = segmentIndex == pageHeader.pageSegmentCount ? C.INDEX_UNSET - : segmentIndex; + currentSegmentIndex = + segmentIndex == pageHeader.pageSegmentCount ? C.INDEX_UNSET : segmentIndex; } return true; } @@ -119,16 +115,12 @@ public OggPageHeader getPageHeader() { return pageHeader; } - /** - * Returns a {@link ParsableByteArray} containing the packet's payload. - */ + /** Returns a {@link ParsableByteArray} containing the packet's payload. */ public ParsableByteArray getPayload() { return packetArray; } - /** - * Trims the packet data array. - */ + /** Trims the packet data array. */ public void trimPayload() { if (packetArray.getData().length == OggPageHeader.MAX_PAGE_PAYLOAD) { return; @@ -158,5 +150,4 @@ private int calculatePacketSize(int startSegmentIndex) { } return size; } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggPageHeader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggPageHeader.java index 70a1f22f54e..306e64f559c 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggPageHeader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggPageHeader.java @@ -24,16 +24,14 @@ import com.google.android.exoplayer2.util.ParsableByteArray; import java.io.IOException; -/** - * Data object to store header information. - */ -/* package */ final class OggPageHeader { +/** Data object to store header information. */ +/* package */ final class OggPageHeader { public static final int EMPTY_PAGE_HEADER_SIZE = 27; public static final int MAX_SEGMENT_COUNT = 255; public static final int MAX_PAGE_PAYLOAD = 255 * 255; - public static final int MAX_PAGE_SIZE = EMPTY_PAGE_HEADER_SIZE + MAX_SEGMENT_COUNT - + MAX_PAGE_PAYLOAD; + public static final int MAX_PAGE_SIZE = + EMPTY_PAGE_HEADER_SIZE + MAX_SEGMENT_COUNT + MAX_PAGE_PAYLOAD; private static final int CAPTURE_PATTERN = 0x4f676753; // OggS private static final int CAPTURE_PATTERN_SIZE = 4; @@ -54,16 +52,14 @@ public int headerSize; public int bodySize; /** - * Be aware that {@code laces.length} is always {@link #MAX_SEGMENT_COUNT}. Instead use - * {@link #pageSegmentCount} to iterate. + * Be aware that {@code laces.length} is always {@link #MAX_SEGMENT_COUNT}. Instead use {@link + * #pageSegmentCount} to iterate. */ public final int[] laces = new int[MAX_SEGMENT_COUNT]; private final ParsableByteArray scratch = new ParsableByteArray(MAX_SEGMENT_COUNT); - /** - * Resets all primitive member fields to zero. - */ + /** Resets all primitive member fields to zero. */ public void reset() { revision = 0; type = 0; @@ -145,7 +141,8 @@ public boolean populate(ExtractorInput input, boolean quiet) throws IOException if (quiet) { return false; } else { - throw new ParserException("unsupported bit stream revision"); + throw ParserException.createForUnsupportedContainerFeature( + "unsupported bit stream revision"); } } type = scratch.readUnsignedByte(); diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/OpusReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/OpusReader.java index 08b6fb8caea..32791c33d5a 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/OpusReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/OpusReader.java @@ -25,9 +25,7 @@ import java.util.List; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; -/** - * {@link StreamReader} to extract Opus data out of Ogg byte stream. - */ +/** {@link StreamReader} to extract Opus data out of Ogg byte stream. */ /* package */ final class OpusReader extends StreamReader { private static final int OPUS_CODE = 0x4f707573; diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/StreamReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/StreamReader.java index f160655459e..7b0871c1511 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/StreamReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/StreamReader.java @@ -90,9 +90,7 @@ protected void reset(boolean headerData) { currentGranule = 0; } - /** - * @see Extractor#seek(long, long) - */ + /** @see Extractor#seek(long, long) */ final void seek(long position, long timeUs) { oggPacket.reset(); if (position == 0) { @@ -294,7 +292,5 @@ public void startSeek(long targetGranule) { public SeekMap createSeekMap() { return new SeekMap.Unseekable(C.TIME_UNSET); } - } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/VorbisReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/VorbisReader.java index 7e7b6eb84db..607bffe858c 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/VorbisReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/VorbisReader.java @@ -31,9 +31,7 @@ import java.util.Arrays; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; -/** - * {@link StreamReader} to extract Vorbis data out of Ogg byte stream. - */ +/** {@link StreamReader} to extract Vorbis data out of Ogg byte stream. */ /* package */ final class VorbisReader extends StreamReader { @Nullable private VorbisSetup vorbisSetup; @@ -81,8 +79,8 @@ protected long preparePayload(ParsableByteArray packet) { int packetBlockSize = decodeBlockSize(packet.getData()[0], checkStateNotNull(vorbisSetup)); // a packet contains samples produced from overlapping the previous and current frame data // (https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-350001.3.2) - int samplesInPacket = seenFirstAudioPacket ? (packetBlockSize + previousPacketBlockSize) / 4 - : 0; + int samplesInPacket = + seenFirstAudioPacket ? (packetBlockSize + previousPacketBlockSize) / 4 : 0; // codec expects the number of samples appended to audio data appendNumberOfSamples(packet, samplesInPacket); @@ -196,9 +194,7 @@ private static int decodeBlockSize(byte firstByteOfAudioPacket, VorbisSetup vorb return currentBlockSize; } - /** - * Class to hold all data read from Vorbis setup headers. - */ + /** Class to hold all data read from Vorbis setup headers. */ /* package */ static final class VorbisSetup { public final VorbisUtil.VorbisIdHeader idHeader; @@ -207,15 +203,17 @@ private static int decodeBlockSize(byte firstByteOfAudioPacket, VorbisSetup vorb public final Mode[] modes; public final int iLogModes; - public VorbisSetup(VorbisUtil.VorbisIdHeader idHeader, VorbisUtil.CommentHeader - commentHeader, byte[] setupHeaderData, Mode[] modes, int iLogModes) { + public VorbisSetup( + VorbisUtil.VorbisIdHeader idHeader, + VorbisUtil.CommentHeader commentHeader, + byte[] setupHeaderData, + Mode[] modes, + int iLogModes) { this.idHeader = idHeader; this.commentHeader = commentHeader; this.setupHeaderData = setupHeaderData; this.modes = modes; this.iLogModes = iLogModes; } - } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/rawcc/RawCcExtractor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/rawcc/RawCcExtractor.java index d9339fa689b..a1c49777456 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/rawcc/RawCcExtractor.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/rawcc/RawCcExtractor.java @@ -144,7 +144,8 @@ private boolean parseTimestampAndSampleCount(ExtractorInput input) throws IOExce } timestampUs = dataScratch.readLong(); } else { - throw new ParserException("Unsupported version number: " + version); + throw ParserException.createForMalformedContainer( + "Unsupported version number: " + version, /* cause= */ null); } remainingSampleCount = dataScratch.readUnsignedByte(); diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac3Extractor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac3Extractor.java index 94a277582dc..65f0f3a60aa 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac3Extractor.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac3Extractor.java @@ -42,6 +42,7 @@ public final class Ac3Extractor implements Extractor { * up. */ private static final int MAX_SNIFF_BYTES = 8 * 1024; + private static final int AC3_SYNC_WORD = 0x0B77; private static final int MAX_SYNC_FRAME_SIZE = 2786; @@ -142,5 +143,4 @@ public int read(ExtractorInput input, PositionHolder seekPosition) throws IOExce reader.consume(sampleData); return RESULT_CONTINUE; } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac3Reader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac3Reader.java index 2de59a5a07f..262dab358c3 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac3Reader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac3Reader.java @@ -71,9 +71,7 @@ public final class Ac3Reader implements ElementaryStreamReader { // Used when reading the samples. private long timeUs; - /** - * Constructs a new reader for (E-)AC-3 elementary streams. - */ + /** Constructs a new reader for (E-)AC-3 elementary streams. */ public Ac3Reader() { this(null); } @@ -98,10 +96,10 @@ public void seek() { } @Override - public void createTracks(ExtractorOutput extractorOutput, TrackIdGenerator generator) { - generator.generateNewId(); - formatId = generator.getFormatId(); - output = extractorOutput.track(generator.getTrackId(), C.TRACK_TYPE_AUDIO); + public void createTracks(ExtractorOutput extractorOutput, TrackIdGenerator idGenerator) { + idGenerator.generateNewId(); + formatId = idGenerator.getFormatId(); + output = extractorOutput.track(idGenerator.getTrackId(), C.TRACK_TYPE_AUDIO); } @Override @@ -215,5 +213,4 @@ private void parseHeader() { // specifies the number of PCM audio samples per second. sampleDurationUs = C.MICROS_PER_SECOND * frameInfo.sampleCount / format.sampleRate; } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac4Reader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac4Reader.java index 0f088836d1a..6581ecefdbb 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac4Reader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac4Reader.java @@ -99,10 +99,10 @@ public void seek() { } @Override - public void createTracks(ExtractorOutput extractorOutput, TrackIdGenerator generator) { - generator.generateNewId(); - formatId = generator.getFormatId(); - output = extractorOutput.track(generator.getTrackId(), C.TRACK_TYPE_AUDIO); + public void createTracks(ExtractorOutput extractorOutput, TrackIdGenerator idGenerator) { + idGenerator.generateNewId(); + formatId = idGenerator.getFormatId(); + output = extractorOutput.track(idGenerator.getTrackId(), C.TRACK_TYPE_AUDIO); } @Override diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/AdtsExtractor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/AdtsExtractor.java index 7c93c210f37..f4fc317fdc1 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/AdtsExtractor.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/AdtsExtractor.java @@ -287,7 +287,8 @@ private void calculateAverageFrameSize(ExtractorInput input) throws IOException // Either the stream is malformed OR we're not parsing an ADTS stream. if (currentFrameSize <= 6) { hasCalculatedAverageFrameSize = true; - throw new ParserException("Malformed ADTS stream"); + throw ParserException.createForMalformedContainer( + "Malformed ADTS stream", /* cause= */ null); } totalValidFramesSize += currentFrameSize; if (++numValidFrames == NUM_FRAMES_FOR_AVERAGE_FRAME_SIZE) { diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/AdtsReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/AdtsReader.java index 13d76134dac..0e1a1ed783d 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/AdtsReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/AdtsReader.java @@ -98,9 +98,7 @@ public final class AdtsReader implements ElementaryStreamReader { private @MonotonicNonNull TrackOutput currentOutput; private long currentSampleDuration; - /** - * @param exposeId3 True if the reader should expose ID3 information. - */ + /** @param exposeId3 True if the reader should expose ID3 information. */ public AdtsReader(boolean exposeId3) { this(exposeId3, null); } @@ -219,9 +217,7 @@ private boolean continueRead(ParsableByteArray source, byte[] target, int target return bytesRead == targetLength; } - /** - * Sets the state to STATE_FINDING_SAMPLE. - */ + /** Sets the state to STATE_FINDING_SAMPLE. */ private void setFindingSampleState() { state = STATE_FINDING_SAMPLE; bytesRead = 0; @@ -229,8 +225,8 @@ private void setFindingSampleState() { } /** - * Sets the state to STATE_READING_ID3_HEADER and resets the fields required for - * {@link #parseId3Header()}. + * Sets the state to STATE_READING_ID3_HEADER and resets the fields required for {@link + * #parseId3Header()}. */ private void setReadingId3HeaderState() { state = STATE_READING_ID3_HEADER; @@ -247,8 +243,8 @@ private void setReadingId3HeaderState() { * @param priorReadBytes Size of prior read bytes * @param sampleSize Size of the sample */ - private void setReadingSampleState(TrackOutput outputToUse, long currentSampleDuration, - int priorReadBytes, int sampleSize) { + private void setReadingSampleState( + TrackOutput outputToUse, long currentSampleDuration, int priorReadBytes, int sampleSize) { state = STATE_READING_SAMPLE; bytesRead = priorReadBytes; this.currentOutput = outputToUse; @@ -256,9 +252,7 @@ private void setReadingSampleState(TrackOutput outputToUse, long currentSampleDu this.sampleSize = sampleSize; } - /** - * Sets the state to STATE_READING_ADTS_HEADER. - */ + /** Sets the state to STATE_READING_ADTS_HEADER. */ private void setReadingAdtsHeaderState() { state = STATE_READING_ADTS_HEADER; bytesRead = 0; @@ -468,8 +462,8 @@ private boolean tryRead(ParsableByteArray source, byte[] target, int targetLengt private void parseId3Header() { id3Output.sampleData(id3HeaderBuffer, ID3_HEADER_SIZE); id3HeaderBuffer.setPosition(ID3_SIZE_OFFSET); - setReadingSampleState(id3Output, 0, ID3_HEADER_SIZE, - id3HeaderBuffer.readSynchSafeInt() + ID3_HEADER_SIZE); + setReadingSampleState( + id3Output, 0, ID3_HEADER_SIZE, id3HeaderBuffer.readSynchSafeInt() + ID3_HEADER_SIZE); } /** Parses the sample header. */ diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/DefaultTsPayloadReaderFactory.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/DefaultTsPayloadReaderFactory.java index 6b5579e3a91..3d9c2b04c5a 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/DefaultTsPayloadReaderFactory.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/DefaultTsPayloadReaderFactory.java @@ -117,11 +117,11 @@ public DefaultTsPayloadReaderFactory(@Flags int flags) { * @param flags A combination of {@code FLAG_*} values that control the behavior of the created * readers. * @param closedCaptionFormats {@link Format}s to be exposed by payload readers for streams with - * embedded closed captions when no caption service descriptors are provided. If - * {@link #FLAG_OVERRIDE_CAPTION_DESCRIPTORS} is set, {@code closedCaptionFormats} overrides - * any descriptor information. If not set, and {@code closedCaptionFormats} is empty, a - * closed caption track with {@link Format#accessibilityChannel} {@link Format#NO_VALUE} will - * be exposed. + * embedded closed captions when no caption service descriptors are provided. If {@link + * #FLAG_OVERRIDE_CAPTION_DESCRIPTORS} is set, {@code closedCaptionFormats} overrides any + * descriptor information. If not set, and {@code closedCaptionFormats} is empty, a closed + * caption track with {@link Format#accessibilityChannel} {@link Format#NO_VALUE} will be + * exposed. */ public DefaultTsPayloadReaderFactory(@Flags int flags, List closedCaptionFormats) { this.flags = flags; @@ -142,10 +142,12 @@ public TsPayloadReader createPayloadReader(int streamType, EsInfo esInfo) { return new PesReader(new MpegAudioReader(esInfo.language)); case TsExtractor.TS_STREAM_TYPE_AAC_ADTS: return isSet(FLAG_IGNORE_AAC_STREAM) - ? null : new PesReader(new AdtsReader(false, esInfo.language)); + ? null + : new PesReader(new AdtsReader(false, esInfo.language)); case TsExtractor.TS_STREAM_TYPE_AAC_LATM: return isSet(FLAG_IGNORE_AAC_STREAM) - ? null : new PesReader(new LatmReader(esInfo.language)); + ? null + : new PesReader(new LatmReader(esInfo.language)); case TsExtractor.TS_STREAM_TYPE_AC3: case TsExtractor.TS_STREAM_TYPE_E_AC3: return new PesReader(new Ac3Reader(esInfo.language)); @@ -163,9 +165,13 @@ public TsPayloadReader createPayloadReader(int streamType, EsInfo esInfo) { case TsExtractor.TS_STREAM_TYPE_H263: return new PesReader(new H263Reader(buildUserDataReader(esInfo))); case TsExtractor.TS_STREAM_TYPE_H264: - return isSet(FLAG_IGNORE_H264_STREAM) ? null - : new PesReader(new H264Reader(buildSeiReader(esInfo), - isSet(FLAG_ALLOW_NON_IDR_KEYFRAMES), isSet(FLAG_DETECT_ACCESS_UNITS))); + return isSet(FLAG_IGNORE_H264_STREAM) + ? null + : new PesReader( + new H264Reader( + buildSeiReader(esInfo), + isSet(FLAG_ALLOW_NON_IDR_KEYFRAMES), + isSet(FLAG_DETECT_ACCESS_UNITS))); case TsExtractor.TS_STREAM_TYPE_H265: return new PesReader(new H265Reader(buildSeiReader(esInfo))); case TsExtractor.TS_STREAM_TYPE_SPLICE_INFO: @@ -175,8 +181,7 @@ public TsPayloadReader createPayloadReader(int streamType, EsInfo esInfo) { case TsExtractor.TS_STREAM_TYPE_ID3: return new PesReader(new Id3Reader()); case TsExtractor.TS_STREAM_TYPE_DVBSUBS: - return new PesReader( - new DvbSubtitleReader(esInfo.dvbSubtitleInfos)); + return new PesReader(new DvbSubtitleReader(esInfo.dvbSubtitleInfos)); case TsExtractor.TS_STREAM_TYPE_AIT: return new SectionReader(new PassthroughSectionPayloadReader(MimeTypes.APPLICATION_AIT)); default: diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/DtsReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/DtsReader.java index 3ffc44b7307..0a10aa7790d 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/DtsReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/DtsReader.java @@ -179,8 +179,8 @@ private void parseHeader() { sampleSize = DtsUtil.getDtsFrameSize(frameData); // In this class a sample is an access unit (frame in DTS), but the format's sample rate // specifies the number of PCM audio samples per second. - sampleDurationUs = (int) (C.MICROS_PER_SECOND - * DtsUtil.parseDtsAudioSampleCount(frameData) / format.sampleRate); + sampleDurationUs = + (int) + (C.MICROS_PER_SECOND * DtsUtil.parseDtsAudioSampleCount(frameData) / format.sampleRate); } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/DvbSubtitleReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/DvbSubtitleReader.java index 592e28ba57a..34552c3089a 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/DvbSubtitleReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/DvbSubtitleReader.java @@ -39,9 +39,7 @@ public final class DvbSubtitleReader implements ElementaryStreamReader { private int sampleBytesWritten; private long sampleTimeUs; - /** - * @param subtitleInfos Information about the DVB subtitles associated to the stream. - */ + /** @param subtitleInfos Information about the DVB subtitles associated to the stream. */ public DvbSubtitleReader(List subtitleInfos) { this.subtitleInfos = subtitleInfos; outputs = new TrackOutput[subtitleInfos.size()]; @@ -121,5 +119,4 @@ private boolean checkNextByte(ParsableByteArray data, int expectedValue) { bytesToCheck--; return writingSample; } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/ElementaryStreamReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/ElementaryStreamReader.java index a8769597238..48227d66703 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/ElementaryStreamReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/ElementaryStreamReader.java @@ -23,9 +23,7 @@ /** Extracts individual samples from an elementary media stream, preserving original order. */ public interface ElementaryStreamReader { - /** - * Notifies the reader that a seek has occurred. - */ + /** Notifies the reader that a seek has occurred. */ void seek(); /** @@ -53,9 +51,6 @@ public interface ElementaryStreamReader { */ void consume(ParsableByteArray data) throws ParserException; - /** - * Called when a packet ends. - */ + /** Called when a packet ends. */ void packetFinished(); - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/H262Reader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/H262Reader.java index de9756e1551..c42c3557e86 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/H262Reader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/H262Reader.java @@ -46,8 +46,8 @@ public final class H262Reader implements ElementaryStreamReader { private @MonotonicNonNull TrackOutput output; // Maps (frame_rate_code - 1) indices to values, as defined in ITU-T H.262 Table 6-4. - private static final double[] FRAME_RATE_VALUES = new double[] { - 24000d / 1001, 24, 25, 30000d / 1001, 30, 50, 60000d / 1001, 60}; + private static final double[] FRAME_RATE_VALUES = + new double[] {24000d / 1001, 24, 25, 30000d / 1001, 30, 50, 60000d / 1001, 60}; @Nullable private final UserDataReader userDataReader; @Nullable private final ParsableByteArray userDataParsable; @@ -191,8 +191,10 @@ public void consume(ParsableByteArray data) { if (!startedFirstSample || sampleHasPicture) { // Start the next sample. samplePosition = totalBytesWritten - bytesWrittenPastStartCode; - sampleTimeUs = pesTimeUs != C.TIME_UNSET ? pesTimeUs - : (startedFirstSample ? (sampleTimeUs + frameDurationUs) : 0); + sampleTimeUs = + pesTimeUs != C.TIME_UNSET + ? pesTimeUs + : (startedFirstSample ? (sampleTimeUs + frameDurationUs) : 0); sampleIsKeyframe = false; pesTimeUs = C.TIME_UNSET; startedFirstSample = true; @@ -230,7 +232,7 @@ private static Pair parseCsdBuffer(CsdBuffer csdBuffer, String for float pixelWidthHeightRatio = 1f; int aspectRatioCode = (csdData[7] & 0xF0) >> 4; - switch(aspectRatioCode) { + switch (aspectRatioCode) { case 2: pixelWidthHeightRatio = (4 * height) / (float) (3 * width); break; @@ -285,9 +287,7 @@ public CsdBuffer(int initialCapacity) { data = new byte[initialCapacity]; } - /** - * Resets the buffer, clearing any data that it holds. - */ + /** Resets the buffer, clearing any data that it holds. */ public void reset() { isFilling = false; length = 0; @@ -300,9 +300,9 @@ public void reset() { * @param startCodeValue The start code value. * @param bytesAlreadyPassed The number of bytes of the start code that have been passed to * {@link #onData(byte[], int, int)}, or 0. - * @return Whether the csd data is now complete. If true is returned, neither - * this method nor {@link #onData(byte[], int, int)} should be called again without an - * interleaving call to {@link #reset()}. + * @return Whether the csd data is now complete. If true is returned, neither this method nor + * {@link #onData(byte[], int, int)} should be called again without an interleaving call to + * {@link #reset()}. */ public boolean onStartCode(int startCodeValue, int bytesAlreadyPassed) { if (isFilling) { @@ -338,7 +338,5 @@ public void onData(byte[] newData, int offset, int limit) { System.arraycopy(newData, offset, data, length, readLength); length += readLength; } - } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/H264Reader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/H264Reader.java index 116bcfef29b..6790747ac97 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/H264Reader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/H264Reader.java @@ -153,8 +153,11 @@ public void consume(ParsableByteArray data) { // Indicate the end of the previous NAL unit. If the length to the start of the next unit // is negative then we wrote too many bytes to the NAL buffers. Discard the excess bytes // when notifying that the unit has ended. - endNalUnit(absolutePosition, bytesWrittenPastPosition, - lengthToNalUnit < 0 ? -lengthToNalUnit : 0, pesTimeUs); + endNalUnit( + absolutePosition, + bytesWrittenPastPosition, + lengthToNalUnit < 0 ? -lengthToNalUnit : 0, + pesTimeUs); // Indicate the start of the next NAL unit. startNalUnit(absolutePosition, nalUnitType, pesTimeUs); // Continue scanning the data. @@ -286,8 +289,8 @@ private static final class SampleReader { private long sampleTimeUs; private boolean sampleIsKeyframe; - public SampleReader(TrackOutput output, boolean allowNonIdrKeyframes, - boolean detectAccessUnits) { + public SampleReader( + TrackOutput output, boolean allowNonIdrKeyframes, boolean detectAccessUnits) { this.output = output; this.allowNonIdrKeyframes = allowNonIdrKeyframes; this.detectAccessUnits = detectAccessUnits; @@ -323,9 +326,10 @@ public void startNalUnit(long position, int type, long pesTimeUs) { nalUnitTimeUs = pesTimeUs; nalUnitStartPosition = position; if ((allowNonIdrKeyframes && nalUnitType == NAL_UNIT_TYPE_NON_IDR) - || (detectAccessUnits && (nalUnitType == NAL_UNIT_TYPE_IDR - || nalUnitType == NAL_UNIT_TYPE_NON_IDR - || nalUnitType == NAL_UNIT_TYPE_PARTITION_A))) { + || (detectAccessUnits + && (nalUnitType == NAL_UNIT_TYPE_IDR + || nalUnitType == NAL_UNIT_TYPE_NON_IDR + || nalUnitType == NAL_UNIT_TYPE_PARTITION_A))) { // Store the previous header and prepare to populate the new one. SliceHeaderData newSliceHeader = previousSliceHeader; previousSliceHeader = sliceHeader; @@ -438,8 +442,7 @@ public void appendToNalUnit(byte[] data, int offset, int limit) { } deltaPicOrderCntBottom = bitArray.readSignedExpGolombCodedInt(); } - } else if (spsData.picOrderCountType == 1 - && !spsData.deltaPicOrderAlwaysZeroFlag) { + } else if (spsData.picOrderCountType == 1 && !spsData.deltaPicOrderAlwaysZeroFlag) { if (!bitArray.canReadExpGolombCodedNum()) { return; } @@ -451,9 +454,21 @@ public void appendToNalUnit(byte[] data, int offset, int limit) { deltaPicOrderCnt1 = bitArray.readSignedExpGolombCodedInt(); } } - sliceHeader.setAll(spsData, nalRefIdc, sliceType, frameNum, picParameterSetId, fieldPicFlag, - bottomFieldFlagPresent, bottomFieldFlag, idrPicFlag, idrPicId, picOrderCntLsb, - deltaPicOrderCntBottom, deltaPicOrderCnt0, deltaPicOrderCnt1); + sliceHeader.setAll( + spsData, + nalRefIdc, + sliceType, + frameNum, + picParameterSetId, + fieldPicFlag, + bottomFieldFlagPresent, + bottomFieldFlag, + idrPicFlag, + idrPicId, + picOrderCntLsb, + deltaPicOrderCntBottom, + deltaPicOrderCnt0, + deltaPicOrderCnt1); isFilling = false; } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java index dd5dcc17821..9dccd88280a 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java @@ -76,9 +76,7 @@ public final class H265Reader implements ElementaryStreamReader { // Scratch variables to avoid allocations. private final ParsableByteArray seiWrapper; - /** - * @param seiReader An SEI reader for consuming closed caption channels. - */ + /** @param seiReader An SEI reader for consuming closed caption channels. */ public H265Reader(SeiReader seiReader) { this.seiReader = seiReader; prefixFlags = new boolean[3]; @@ -157,8 +155,11 @@ public void consume(ParsableByteArray data) { // Indicate the end of the previous NAL unit. If the length to the start of the next unit // is negative then we wrote too many bytes to the NAL buffers. Discard the excess bytes // when notifying that the unit has ended. - endNalUnit(absolutePosition, bytesWrittenPastPosition, - lengthToNalUnit < 0 ? -lengthToNalUnit : 0, pesTimeUs); + endNalUnit( + absolutePosition, + bytesWrittenPastPosition, + lengthToNalUnit < 0 ? -lengthToNalUnit : 0, + pesTimeUs); // Indicate the start of the next NAL unit. startNalUnit(absolutePosition, bytesWrittenPastPosition, nalUnitType, pesTimeUs); // Continue scanning the data. @@ -371,9 +372,7 @@ private static Format parseMediaFormat( .build(); } - /** - * Skips scaling_list_data(). See H.265/HEVC (2014) 7.3.4. - */ + /** Skips scaling_list_data(). See H.265/HEVC (2014) 7.3.4. */ private static void skipScalingList(ParsableNalUnitBitArray bitArray) { for (int sizeId = 0; sizeId < 4; sizeId++) { for (int matrixId = 0; matrixId < 6; matrixId += sizeId == 3 ? 3 : 1) { diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/Id3Reader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/Id3Reader.java index 66eb67f16c7..74937ddce9f 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/Id3Reader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/Id3Reader.java @@ -97,7 +97,8 @@ public void consume(ParsableByteArray data) { if (sampleBytesRead + headerBytesAvailable == ID3_HEADER_LENGTH) { // We've finished reading the ID3 header. Extract the sample size. id3Header.setPosition(0); - if ('I' != id3Header.readUnsignedByte() || 'D' != id3Header.readUnsignedByte() + if ('I' != id3Header.readUnsignedByte() + || 'D' != id3Header.readUnsignedByte() || '3' != id3Header.readUnsignedByte()) { Log.w(TAG, "Discarding invalid ID3 tag"); writingSample = false; @@ -122,5 +123,4 @@ public void packetFinished() { output.sampleMetadata(sampleTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null); writingSample = false; } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/LatmReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/LatmReader.java index 64f56f6455f..8cd33f28511 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/LatmReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/LatmReader.java @@ -73,9 +73,7 @@ public final class LatmReader implements ElementaryStreamReader { private int channelCount; @Nullable private String codecs; - /** - * @param language Track language. - */ + /** @param language Track language. */ public LatmReader(@Nullable String language) { this.language = language; sampleDataBuffer = new ParsableByteArray(INITIAL_BUFFER_SIZE); @@ -166,7 +164,7 @@ private void parseAudioMuxElement(ParsableBitArray data) throws ParserException if (audioMuxVersionA == 0) { if (numSubframes != 0) { - throw new ParserException(); + throw ParserException.createForMalformedContainer(/* message= */ null, /* cause= */ null); } int muxSlotLengthBytes = parsePayloadLengthInfo(data); parsePayloadMux(data, muxSlotLengthBytes); @@ -174,7 +172,8 @@ private void parseAudioMuxElement(ParsableBitArray data) throws ParserException data.skipBits((int) otherDataLenBits); } } else { - throw new ParserException(); // Not defined by ISO/IEC 14496-3:2009. + // Not defined by ISO/IEC 14496-3:2009. + throw ParserException.createForMalformedContainer(/* message= */ null, /* cause= */ null); } } @@ -188,13 +187,13 @@ private void parseStreamMuxConfig(ParsableBitArray data) throws ParserException latmGetValue(data); // Skip taraBufferFullness. } if (!data.readBit()) { - throw new ParserException(); + throw ParserException.createForMalformedContainer(/* message= */ null, /* cause= */ null); } numSubframes = data.readBits(6); int numProgram = data.readBits(4); int numLayer = data.readBits(3); if (numProgram != 0 || numLayer != 0) { - throw new ParserException(); + throw ParserException.createForMalformedContainer(/* message= */ null, /* cause= */ null); } if (audioMuxVersion == 0) { int startPosition = data.getPosition(); @@ -241,7 +240,8 @@ private void parseStreamMuxConfig(ParsableBitArray data) throws ParserException data.skipBits(8); // crcCheckSum. } } else { - throw new ParserException(); // This is not defined by ISO/IEC 14496-3:2009. + // This is not defined by ISO/IEC 14496-3:2009. + throw ParserException.createForMalformedContainer(/* message= */ null, /* cause= */ null); } } @@ -288,7 +288,7 @@ private int parsePayloadLengthInfo(ParsableBitArray data) throws ParserException } while (tmp == 255); return muxSlotLengthBytes; } else { - throw new ParserException(); + throw ParserException.createForMalformedContainer(/* message= */ null, /* cause= */ null); } } @@ -319,5 +319,4 @@ private static long latmGetValue(ParsableBitArray data) { int bytesForValue = data.readBits(2); return data.readBits((bytesForValue + 1) * 8); } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/MpegAudioReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/MpegAudioReader.java index f65f515a9a8..a3e07123325 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/MpegAudioReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/MpegAudioReader.java @@ -118,13 +118,13 @@ public void packetFinished() { /** * Attempts to locate the start of the next frame header. - *

    - * If a frame header is located then the state is changed to {@link #STATE_READING_HEADER}, the + * + *

    If a frame header is located then the state is changed to {@link #STATE_READING_HEADER}, the * first two bytes of the header are written into {@link #headerScratch}, and the position of the * source is advanced to the byte that immediately follows these two bytes. - *

    - * If a frame header is not located then the position of the source is advanced to the limit, and - * the method should be called again with the next source to continue the search. + * + *

    If a frame header is not located then the position of the source is advanced to the limit, + * and the method should be called again with the next source to continue the search. * * @param source The source from which to read. */ diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/NalUnitTargetBuffer.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/NalUnitTargetBuffer.java index ece2fdf7674..04081c7cdf6 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/NalUnitTargetBuffer.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/NalUnitTargetBuffer.java @@ -19,8 +19,8 @@ import java.util.Arrays; /** - * A buffer that fills itself with data corresponding to a specific NAL unit, as it is - * encountered in the stream. + * A buffer that fills itself with data corresponding to a specific NAL unit, as it is encountered + * in the stream. */ /* package */ final class NalUnitTargetBuffer { @@ -40,17 +40,13 @@ public NalUnitTargetBuffer(int targetType, int initialCapacity) { nalData[2] = 1; } - /** - * Resets the buffer, clearing any data that it holds. - */ + /** Resets the buffer, clearing any data that it holds. */ public void reset() { isFilling = false; isCompleted = false; } - /** - * Returns whether the buffer currently holds a complete NAL unit of the target type. - */ + /** Returns whether the buffer currently holds a complete NAL unit of the target type. */ public boolean isCompleted() { return isCompleted; } @@ -92,8 +88,8 @@ public void appendToNalUnit(byte[] data, int offset, int limit) { /** * Called to indicate that a NAL unit has ended. * - * @param discardPadding The number of excess bytes that were passed to - * {@link #appendToNalUnit(byte[], int, int)}, which should be discarded. + * @param discardPadding The number of excess bytes that were passed to {@link + * #appendToNalUnit(byte[], int, int)}, which should be discarded. * @return Whether the ended NAL unit is of the target type. */ public boolean endNalUnit(int discardPadding) { @@ -105,5 +101,4 @@ public boolean endNalUnit(int discardPadding) { isCompleted = true; return true; } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/PassthroughSectionPayloadReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/PassthroughSectionPayloadReader.java index 72667e2a3f5..111cfd8750c 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/PassthroughSectionPayloadReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/PassthroughSectionPayloadReader.java @@ -62,9 +62,10 @@ public void init( @Override public void consume(ParsableByteArray sectionData) { assertInitialized(); + long sampleTimestampUs = timestampAdjuster.getLastAdjustedTimestampUs(); long subsampleOffsetUs = timestampAdjuster.getTimestampOffsetUs(); - if (subsampleOffsetUs == C.TIME_UNSET) { - // Don't output samples without a known subsample offset. + if (sampleTimestampUs == C.TIME_UNSET || subsampleOffsetUs == C.TIME_UNSET) { + // Don't output samples without a known sample timestamp and subsample offset. return; } if (subsampleOffsetUs != format.subsampleOffsetUs) { @@ -73,12 +74,7 @@ public void consume(ParsableByteArray sectionData) { } int sampleSize = sectionData.bytesLeft(); output.sampleData(sectionData, sampleSize); - output.sampleMetadata( - timestampAdjuster.getLastAdjustedTimestampUs(), - C.BUFFER_FLAG_KEY_FRAME, - sampleSize, - 0, - null); + output.sampleMetadata(sampleTimestampUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null); } @EnsuresNonNull({"timestampAdjuster", "output"}) diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/PesReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/PesReader.java index eb3606a8b06..7b4ca00cef7 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/PesReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/PesReader.java @@ -65,7 +65,9 @@ public PesReader(ElementaryStreamReader reader) { } @Override - public void init(TimestampAdjuster timestampAdjuster, ExtractorOutput extractorOutput, + public void init( + TimestampAdjuster timestampAdjuster, + ExtractorOutput extractorOutput, TrackIdGenerator idGenerator) { this.timestampAdjuster = timestampAdjuster; reader.createTracks(extractorOutput, idGenerator); @@ -208,8 +210,11 @@ private boolean parseHeader() { if (packetLength == 0) { payloadSize = C.LENGTH_UNSET; } else { - payloadSize = packetLength + 6 /* packetLength does not include the first 6 bytes */ - - HEADER_SIZE - extendedHeaderLength; + payloadSize = + packetLength + + 6 /* packetLength does not include the first 6 bytes */ + - HEADER_SIZE + - extendedHeaderLength; if (payloadSize < 0) { Log.w(TAG, "Found negative packet payload size: " + payloadSize); payloadSize = C.LENGTH_UNSET; @@ -249,5 +254,4 @@ private void parseHeaderExtension() { timeUs = timestampAdjuster.adjustTsTimestamp(pts); } } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/PsExtractor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/PsExtractor.java index f8aed61321c..4611a25825e 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/PsExtractor.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/PsExtractor.java @@ -92,8 +92,11 @@ public boolean sniff(ExtractorInput input) throws IOException { input.peekFully(scratch, 0, 14); // Verify the PACK_START_CODE for the first 4 bytes - if (PACK_START_CODE != (((scratch[0] & 0xFF) << 24) | ((scratch[1] & 0xFF) << 16) - | ((scratch[2] & 0xFF) << 8) | (scratch[3] & 0xFF))) { + if (PACK_START_CODE + != (((scratch[0] & 0xFF) << 24) + | ((scratch[1] & 0xFF) << 16) + | ((scratch[2] & 0xFF) << 8) + | (scratch[3] & 0xFF))) { return false; } // Verify the 01xxx1xx marker on the 5th byte @@ -121,8 +124,8 @@ public boolean sniff(ExtractorInput input) throws IOException { input.advancePeekPosition(packStuffingLength); // Now check that the next 3 bytes are the beginning of an MPEG start code input.peekFully(scratch, 0, 3); - return (PACKET_START_CODE_PREFIX == (((scratch[0] & 0xFF) << 16) | ((scratch[1] & 0xFF) << 8) - | (scratch[2] & 0xFF))); + return (PACKET_START_CODE_PREFIX + == (((scratch[0] & 0xFF) << 16) | ((scratch[1] & 0xFF) << 8) | (scratch[2] & 0xFF))); } @Override @@ -132,16 +135,23 @@ public void init(ExtractorOutput output) { @Override public void seek(long position, long timeUs) { - boolean hasNotEncounteredFirstTimestamp = - timestampAdjuster.getTimestampOffsetUs() == C.TIME_UNSET; - if (hasNotEncounteredFirstTimestamp - || (timestampAdjuster.getFirstSampleTimestampUs() != 0 - && timestampAdjuster.getFirstSampleTimestampUs() != timeUs)) { - // - If the timestamp adjuster in the PS stream has not encountered any sample, it's going to - // treat the first timestamp encountered as sample time 0, which is incorrect. In this case, - // we have to set the first sample timestamp manually. - // - If the timestamp adjuster has its timestamp set manually before, and now we seek to a - // different position, we need to set the first sample timestamp manually again. + // If the timestamp adjuster has not yet established a timestamp offset, we need to reset its + // expected first sample timestamp to be the new seek position. Without this, the timestamp + // adjuster would incorrectly establish its timestamp offset assuming that the first sample + // after this seek corresponds to the start of the stream (or a previous seek position, if there + // was one). + boolean resetTimestampAdjuster = timestampAdjuster.getTimestampOffsetUs() == C.TIME_UNSET; + if (!resetTimestampAdjuster) { + long adjusterFirstSampleTimestampUs = timestampAdjuster.getFirstSampleTimestampUs(); + // Also reset the timestamp adjuster if its offset was calculated based on a non-zero position + // in the stream (other than the position being seeked to), since in this case the offset may + // not be accurate. + resetTimestampAdjuster = + adjusterFirstSampleTimestampUs != C.TIME_UNSET + && adjusterFirstSampleTimestampUs != 0 + && adjusterFirstSampleTimestampUs != timeUs; + } + if (resetTimestampAdjuster) { timestampAdjuster.reset(timeUs); } @@ -210,7 +220,7 @@ public int read(ExtractorInput input, PositionHolder seekPosition) throws IOExce input.skipFully(systemHeaderLength + 6); return RESULT_CONTINUE; } else if (((nextStartCode & 0xFFFFFF00) >> 8) != PACKET_START_CODE_PREFIX) { - input.skipFully(1); // Skip bytes until we see a valid start code again. + input.skipFully(1); // Skip bytes until we see a valid start code again. return RESULT_CONTINUE; } @@ -296,9 +306,7 @@ private void maybeOutputSeekMap(long inputLength) { } } - /** - * Parses PES packet data and extracts samples. - */ + /** Parses PES packet data and extracts samples. */ private static final class PesReader { private static final int PES_SCRATCH_SIZE = 64; @@ -321,10 +329,10 @@ public PesReader(ElementaryStreamReader pesPayloadReader, TimestampAdjuster time /** * Notifies the reader that a seek has occurred. - *

    - * Following a call to this method, the data passed to the next invocation of - * {@link #consume(ParsableByteArray)} will not be a continuation of the data that was - * previously passed. Hence the reader should reset any internal state. + * + *

    Following a call to this method, the data passed to the next invocation of {@link + * #consume(ParsableByteArray)} will not be a continuation of the data that was previously + * passed. Hence the reader should reset any internal state. */ public void seek() { seenFirstDts = false; @@ -393,7 +401,5 @@ private void parseHeaderExtension() { timeUs = timestampAdjuster.adjustTsTimestamp(pts); } } - } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/SectionPayloadReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/SectionPayloadReader.java index 4bd58675658..40e15fa08d6 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/SectionPayloadReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/SectionPayloadReader.java @@ -32,7 +32,9 @@ public interface SectionPayloadReader { * @param idGenerator A {@link PesReader.TrackIdGenerator} that generates unique track ids for the * {@link TrackOutput}s. */ - void init(TimestampAdjuster timestampAdjuster, ExtractorOutput extractorOutput, + void init( + TimestampAdjuster timestampAdjuster, + ExtractorOutput extractorOutput, TrackIdGenerator idGenerator); /** @@ -43,5 +45,4 @@ void init(TimestampAdjuster timestampAdjuster, ExtractorOutput extractorOutput, * Otherwise, all bytes belonging to the table section are included. */ void consume(ParsableByteArray sectionData); - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/SectionReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/SectionReader.java index 3b2bd4ce894..4a73799c07c 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/SectionReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/SectionReader.java @@ -48,7 +48,9 @@ public SectionReader(SectionPayloadReader reader) { } @Override - public void init(TimestampAdjuster timestampAdjuster, ExtractorOutput extractorOutput, + public void init( + TimestampAdjuster timestampAdjuster, + ExtractorOutput extractorOutput, TrackIdGenerator idGenerator) { reader.init(timestampAdjuster, extractorOutput, idGenerator); waitingForPayloadStart = true; @@ -137,5 +139,4 @@ public void consume(ParsableByteArray data, @Flags int flags) { } } } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/SeiReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/SeiReader.java index 9fff73315c7..b3229db2629 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/SeiReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/SeiReader.java @@ -33,9 +33,7 @@ public final class SeiReader { private final List closedCaptionFormats; private final TrackOutput[] outputs; - /** - * @param closedCaptionFormats A list of formats for the closed caption channels to expose. - */ + /** @param closedCaptionFormats A list of formats for the closed caption channels to expose. */ public SeiReader(List closedCaptionFormats) { this.closedCaptionFormats = closedCaptionFormats; outputs = new TrackOutput[closedCaptionFormats.size()]; @@ -47,8 +45,9 @@ public void createTracks(ExtractorOutput extractorOutput, TrackIdGenerator idGen TrackOutput output = extractorOutput.track(idGenerator.getTrackId(), C.TRACK_TYPE_TEXT); Format channelFormat = closedCaptionFormats.get(i); @Nullable String channelMimeType = channelFormat.sampleMimeType; - Assertions.checkArgument(MimeTypes.APPLICATION_CEA608.equals(channelMimeType) - || MimeTypes.APPLICATION_CEA708.equals(channelMimeType), + Assertions.checkArgument( + MimeTypes.APPLICATION_CEA608.equals(channelMimeType) + || MimeTypes.APPLICATION_CEA708.equals(channelMimeType), "Invalid closed caption mime type provided: " + channelMimeType); String formatId = channelFormat.id != null ? channelFormat.id : idGenerator.getFormatId(); output.format( diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/TsDurationReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/TsDurationReader.java index 05577ca2421..6f2406bf2c4 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/TsDurationReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/TsDurationReader.java @@ -196,5 +196,4 @@ private long readLastPcrValueFromBuffer(ParsableByteArray packetBuffer, int pcrP } return C.TIME_UNSET; } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java index 325f05ff2b1..1ff9c06e795 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java @@ -64,13 +64,9 @@ public final class TsExtractor implements Extractor { @IntDef({MODE_MULTI_PMT, MODE_SINGLE_PMT, MODE_HLS}) public @interface Mode {} - /** - * Behave as defined in ISO/IEC 13818-1. - */ + /** Behave as defined in ISO/IEC 13818-1. */ public static final int MODE_MULTI_PMT = 0; - /** - * Assume only one PMT will be contained in the stream, even if more are declared by the PAT. - */ + /** Assume only one PMT will be contained in the stream, even if more are declared by the PAT. */ public static final int MODE_SINGLE_PMT = 1; /** * Enable single PMT mode, map {@link TrackOutput}s by their type (instead of PID) and ignore @@ -256,16 +252,23 @@ public void seek(long position, long timeUs) { int timestampAdjustersCount = timestampAdjusters.size(); for (int i = 0; i < timestampAdjustersCount; i++) { TimestampAdjuster timestampAdjuster = timestampAdjusters.get(i); - boolean hasNotEncounteredFirstTimestamp = - timestampAdjuster.getTimestampOffsetUs() == C.TIME_UNSET; - if (hasNotEncounteredFirstTimestamp - || (timestampAdjuster.getTimestampOffsetUs() != 0 - && timestampAdjuster.getFirstSampleTimestampUs() != timeUs)) { - // - If a track in the TS stream has not encountered any sample, it's going to treat the - // first sample encountered as timestamp 0, which is incorrect. So we have to set the first - // sample timestamp for that track manually. - // - If the timestamp adjuster has its timestamp set manually before, and now we seek to a - // different position, we need to set the first sample timestamp manually again. + // If the timestamp adjuster has not yet established a timestamp offset, we need to reset its + // expected first sample timestamp to be the new seek position. Without this, the timestamp + // adjuster would incorrectly establish its timestamp offset assuming that the first sample + // after this seek corresponds to the start of the stream (or a previous seek position, if + // there was one). + boolean resetTimestampAdjuster = timestampAdjuster.getTimestampOffsetUs() == C.TIME_UNSET; + if (!resetTimestampAdjuster) { + long adjusterFirstSampleTimestampUs = timestampAdjuster.getFirstSampleTimestampUs(); + // Also reset the timestamp adjuster if its offset was calculated based on a non-zero + // position in the stream (other than the position being seeked to), since in this case the + // offset may not be accurate. + resetTimestampAdjuster = + adjusterFirstSampleTimestampUs != C.TIME_UNSET + && adjusterFirstSampleTimestampUs != 0 + && adjusterFirstSampleTimestampUs != timeUs; + } + if (resetTimestampAdjuster) { timestampAdjuster.reset(timeUs); } } @@ -447,7 +450,8 @@ private int findEndOfFirstTsPacketInBuffer() throws ParserException { if (endOfPacket > limit) { bytesSinceLastSync += syncBytePosition - searchStart; if (mode == MODE_HLS && bytesSinceLastSync > TS_PACKET_SIZE * 2) { - throw new ParserException("Cannot find sync byte. Most likely not a Transport Stream."); + throw ParserException.createForMalformedContainer( + "Cannot find sync byte. Most likely not a Transport Stream.", /* cause= */ null); } } else { // We have found a packet within the buffer. @@ -475,9 +479,7 @@ private void resetPayloadReaders() { id3Reader = null; } - /** - * Parses Program Association Table data. - */ + /** Parses Program Association Table data. */ private class PatReader implements SectionPayloadReader { private final ParsableBitArray patScratch; @@ -487,7 +489,9 @@ public PatReader() { } @Override - public void init(TimestampAdjuster timestampAdjuster, ExtractorOutput extractorOutput, + public void init( + TimestampAdjuster timestampAdjuster, + ExtractorOutput extractorOutput, TrackIdGenerator idGenerator) { // Do nothing. } @@ -528,12 +532,9 @@ public void consume(ParsableByteArray sectionData) { tsPayloadReaders.remove(TS_PAT_PID); } } - } - /** - * Parses Program Map Table. - */ + /** Parses Program Map Table. */ private class PmtReader implements SectionPayloadReader { private static final int TS_PMT_DESC_REGISTRATION = 0x05; @@ -560,7 +561,9 @@ public PmtReader(int pid) { } @Override - public void init(TimestampAdjuster timestampAdjuster, ExtractorOutput extractorOutput, + public void init( + TimestampAdjuster timestampAdjuster, + ExtractorOutput extractorOutput, TrackIdGenerator idGenerator) { // Do nothing. } @@ -577,8 +580,8 @@ public void consume(ParsableByteArray sectionData) { if (mode == MODE_SINGLE_PMT || mode == MODE_HLS || remainingPmts == 1) { timestampAdjuster = timestampAdjusters.get(0); } else { - timestampAdjuster = new TimestampAdjuster( - timestampAdjusters.get(0).getFirstSampleTimestampUs()); + timestampAdjuster = + new TimestampAdjuster(timestampAdjusters.get(0).getFirstSampleTimestampUs()); timestampAdjusters.add(timestampAdjuster); } @@ -615,7 +618,9 @@ public void consume(ParsableByteArray sectionData) { // appears intermittently during playback. See [Internal: b/20261500]. EsInfo id3EsInfo = new EsInfo(TS_STREAM_TYPE_ID3, null, null, Util.EMPTY_BYTE_ARRAY); id3Reader = payloadReaderFactory.createPayloadReader(TS_STREAM_TYPE_ID3, id3EsInfo); - id3Reader.init(timestampAdjuster, output, + id3Reader.init( + timestampAdjuster, + output, new TrackIdGenerator(programNumber, TS_STREAM_TYPE_ID3, MAX_PID_PLUS_ONE)); } @@ -661,7 +666,9 @@ public void consume(ParsableByteArray sectionData) { @Nullable TsPayloadReader reader = trackIdToReaderScratch.valueAt(i); if (reader != null) { if (reader != id3Reader) { - reader.init(timestampAdjuster, output, + reader.init( + timestampAdjuster, + output, new TrackIdGenerator(programNumber, trackId, MAX_PID_PLUS_ONE)); } tsPayloadReaders.put(trackPid, reader); @@ -741,8 +748,8 @@ private EsInfo readEsInfo(ParsableByteArray data, int length) { int dvbSubtitlingType = data.readUnsignedByte(); byte[] initializationData = new byte[4]; data.readBytes(initializationData, 0, 4); - dvbSubtitleInfos.add(new DvbSubtitleInfo(dvbLanguage, dvbSubtitlingType, - initializationData)); + dvbSubtitleInfos.add( + new DvbSubtitleInfo(dvbLanguage, dvbSubtitlingType, initializationData)); } } else if (descriptorTag == TS_PMT_DESC_AIT) { streamType = TS_STREAM_TYPE_AIT; @@ -757,7 +764,5 @@ private EsInfo readEsInfo(ParsableByteArray data, int length) { dvbSubtitleInfos, Arrays.copyOfRange(data.getData(), descriptorsStartPosition, descriptorsEndPosition)); } - } - } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/TsPayloadReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/TsPayloadReader.java index 581f4ec4eab..34405a7a1a2 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/TsPayloadReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/TsPayloadReader.java @@ -32,15 +32,13 @@ /** Parses TS packet payload data. */ public interface TsPayloadReader { - /** - * Factory of {@link TsPayloadReader} instances. - */ + /** Factory of {@link TsPayloadReader} instances. */ interface Factory { /** * Returns the initial mapping from PIDs to payload readers. - *

    - * This method allows the injection of payload readers for reserved PIDs, excluding PID 0. + * + *

    This method allows the injection of payload readers for reserved PIDs, excluding PID 0. * * @return A {@link SparseArray} that maps PIDs to payload readers. */ @@ -59,9 +57,7 @@ interface Factory { TsPayloadReader createPayloadReader(int streamType, EsInfo esInfo); } - /** - * Holds information associated with a PMT entry. - */ + /** Holds information associated with a PMT entry. */ final class EsInfo { public final int streamType; @@ -89,7 +85,6 @@ public EsInfo( : Collections.unmodifiableList(dvbSubtitleInfos); this.descriptorBytes = descriptorBytes; } - } /** @@ -111,12 +106,9 @@ public DvbSubtitleInfo(String language, int type, byte[] initializationData) { this.type = type; this.initializationData = initializationData; } - } - /** - * Generates track ids for initializing {@link TsPayloadReader}s' {@link TrackOutput}s. - */ + /** Generates track ids for initializing {@link TsPayloadReader}s' {@link TrackOutput}s. */ final class TrackIdGenerator { private static final int ID_UNSET = Integer.MIN_VALUE; @@ -165,8 +157,7 @@ public int getTrackId() { * called after the first {@link #generateNewId()} call. * * @return The last generated format id, with the format {@code "programNumber/trackId"}. If no - * {@code programNumber} was provided, the {@code trackId} alone is used as - * format id. + * {@code programNumber} was provided, the {@code trackId} alone is used as format id. */ public String getFormatId() { maybeThrowUninitializedError(); @@ -178,7 +169,6 @@ private void maybeThrowUninitializedError() { throw new IllegalStateException("generateNewId() must be called before retrieving ids."); } } - } /** @@ -212,7 +202,9 @@ private void maybeThrowUninitializedError() { * @param idGenerator A {@link PesReader.TrackIdGenerator} that generates unique track ids for the * {@link TrackOutput}s. */ - void init(TimestampAdjuster timestampAdjuster, ExtractorOutput extractorOutput, + void init( + TimestampAdjuster timestampAdjuster, + ExtractorOutput extractorOutput, TrackIdGenerator idGenerator); /** diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/wav/WavExtractor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/wav/WavExtractor.java index bb4734f183c..c1dd2a6ddc5 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/wav/WavExtractor.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/wav/WavExtractor.java @@ -92,7 +92,8 @@ public int read(ExtractorInput input, PositionHolder seekPosition) throws IOExce WavHeader header = WavHeaderReader.peek(input); if (header == null) { // Should only happen if the media wasn't sniffed. - throw new ParserException("Unsupported or unrecognized wav header."); + throw ParserException.createForMalformedContainer( + "Unsupported or unrecognized wav header.", /* cause= */ null); } if (header.formatType == WavUtil.TYPE_IMA_ADPCM) { @@ -117,7 +118,8 @@ public int read(ExtractorInput input, PositionHolder seekPosition) throws IOExce @C.PcmEncoding int pcmEncoding = WavUtil.getPcmEncodingForType(header.formatType, header.bitsPerSample); if (pcmEncoding == C.ENCODING_INVALID) { - throw new ParserException("Unsupported WAV format type: " + header.formatType); + throw ParserException.createForUnsupportedContainerFeature( + "Unsupported WAV format type: " + header.formatType); } outputWriter = new PassthroughOutputWriter( @@ -217,8 +219,9 @@ public PassthroughOutputWriter( int bytesPerFrame = header.numChannels * header.bitsPerSample / 8; // Validate the header. Blocks are expected to correspond to single frames. if (header.blockSize != bytesPerFrame) { - throw new ParserException( - "Expected block size: " + bytesPerFrame + "; got: " + header.blockSize); + throw ParserException.createForMalformedContainer( + "Expected block size: " + bytesPerFrame + "; got: " + header.blockSize, + /* cause= */ null); } int constantBitrate = header.frameRateHz * bytesPerFrame * 8; @@ -351,8 +354,9 @@ public ImaAdPcmOutputWriter( int expectedFramesPerBlock = (((header.blockSize - (4 * numChannels)) * 8) / (header.bitsPerSample * numChannels)) + 1; if (framesPerBlock != expectedFramesPerBlock) { - throw new ParserException( - "Expected frames per block: " + expectedFramesPerBlock + "; got: " + framesPerBlock); + throw ParserException.createForMalformedContainer( + "Expected frames per block: " + expectedFramesPerBlock + "; got: " + framesPerBlock, + /* cause= */ null); } // Calculate the number of blocks we'll need to decode to obtain an output sample of the diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/wav/WavHeaderReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/wav/WavHeaderReader.java index af8ede69aa1..f794933d16c 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/wav/WavHeaderReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/wav/WavHeaderReader.java @@ -127,7 +127,8 @@ public static Pair skipToData(ExtractorInput input) throws IOExcepti bytesToSkip = ChunkHeader.SIZE_IN_BYTES + 4; } if (bytesToSkip > Integer.MAX_VALUE) { - throw new ParserException("Chunk is too large (~2GB+) to skip; id: " + chunkHeader.id); + throw ParserException.createForUnsupportedContainerFeature( + "Chunk is too large (~2GB+) to skip; id: " + chunkHeader.id); } input.skipFully((int) bytesToSkip); chunkHeader = ChunkHeader.peek(input, scratch); diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ConstantBitrateSeekMapTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ConstantBitrateSeekMapTest.java index 4d70fe3b691..bbf72027f78 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ConstantBitrateSeekMapTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ConstantBitrateSeekMapTest.java @@ -22,9 +22,11 @@ import com.google.android.exoplayer2.C; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link ConstantBitrateSeekMap}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class ConstantBitrateSeekMapTest { private ConstantBitrateSeekMap constantBitrateSeekMap; diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/DefaultExtractorInputTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/DefaultExtractorInputTest.java index 646c378eb43..550b7515e05 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/DefaultExtractorInputTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/DefaultExtractorInputTest.java @@ -31,9 +31,11 @@ import java.util.Arrays; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Test for {@link DefaultExtractorInput}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public class DefaultExtractorInputTest { private static final String TEST_URI = "http://www.google.com"; @@ -43,8 +45,7 @@ public class DefaultExtractorInputTest { @Test public void initialPosition() throws Exception { FakeDataSource testDataSource = buildDataSource(); - DefaultExtractorInput input = - new DefaultExtractorInput(testDataSource, 123, C.LENGTH_UNSET); + DefaultExtractorInput input = new DefaultExtractorInput(testDataSource, 123, C.LENGTH_UNSET); assertThat(input.getPosition()).isEqualTo(123); } @@ -608,7 +609,9 @@ public void resetAndPeekFullyPastEndOfStreamWithAllowEndOfInputFails() throws Ex private static FakeDataSource buildDataSource() throws Exception { FakeDataSource testDataSource = new FakeDataSource(); - testDataSource.getDataSet().newDefaultData() + testDataSource + .getDataSet() + .newDefaultData() .appendReadData(Arrays.copyOfRange(TEST_DATA, 0, 3)) .appendReadData(Arrays.copyOfRange(TEST_DATA, 3, 6)) .appendReadData(Arrays.copyOfRange(TEST_DATA, 6, 9)); @@ -625,7 +628,9 @@ private static FakeDataSource buildLargeDataSource() throws Exception { private static FakeDataSource buildFailingDataSource() throws Exception { FakeDataSource testDataSource = new FakeDataSource(); - testDataSource.getDataSet().newDefaultData() + testDataSource + .getDataSet() + .newDefaultData() .appendReadData(Arrays.copyOfRange(TEST_DATA, 0, 6)) .appendReadError(new IOException()) .appendReadData(Arrays.copyOfRange(TEST_DATA, 6, 9)); @@ -637,5 +642,4 @@ private static DefaultExtractorInput createDefaultExtractorInput() throws Except FakeDataSource testDataSource = buildDataSource(); return new DefaultExtractorInput(testDataSource, 0, C.LENGTH_UNSET); } - } diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/DefaultExtractorsFactoryTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/DefaultExtractorsFactoryTest.java index 1c6ce7b70c8..6ad0554d076 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/DefaultExtractorsFactoryTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/DefaultExtractorsFactoryTest.java @@ -42,9 +42,11 @@ import java.util.Map; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link DefaultExtractorsFactory}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class DefaultExtractorsFactoryTest { @Test diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ExtractorTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ExtractorTest.java index caf184a1198..4d3d8a74726 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ExtractorTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ExtractorTest.java @@ -21,9 +21,11 @@ import com.google.android.exoplayer2.C; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link Extractor}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class ExtractorTest { @Test @@ -34,5 +36,4 @@ public void constants() { assertThat(C.RESULT_END_OF_INPUT != Extractor.RESULT_CONTINUE).isTrue(); assertThat(C.RESULT_END_OF_INPUT != Extractor.RESULT_SEEK).isTrue(); } - } diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ExtractorUtilTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ExtractorUtilTest.java index 8959caa3232..6734face122 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ExtractorUtilTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ExtractorUtilTest.java @@ -27,9 +27,11 @@ import java.util.Arrays; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link ExtractorUtil}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public class ExtractorUtilTest { private static final String TEST_URI = "http://www.google.com"; diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/FlacFrameReaderTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/FlacFrameReaderTest.java index 75ef1a201e8..3f37e5ca7b8 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/FlacFrameReaderTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/FlacFrameReaderTest.java @@ -28,6 +28,7 @@ import java.io.IOException; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** * Unit tests for {@link FlacFrameReader}. @@ -36,6 +37,7 @@ * href="https://xiph.org/flac/documentation_tools_flac.html">flac command. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public class FlacFrameReaderTest { @Test diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/FlacMetadataReaderTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/FlacMetadataReaderTest.java index 1648d548d28..046b810a82a 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/FlacMetadataReaderTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/FlacMetadataReaderTest.java @@ -33,6 +33,7 @@ import java.util.ArrayList; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** * Unit tests for {@link FlacMetadataReader}. @@ -41,6 +42,7 @@ * href="https://xiph.org/flac/documentation_tools_metaflac.html">metaflac command. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public class FlacMetadataReaderTest { @Test diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/FlacStreamMetadataTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/FlacStreamMetadataTest.java index 9c6b63ee0ab..3a4d515d200 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/FlacStreamMetadataTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/FlacStreamMetadataTest.java @@ -27,9 +27,11 @@ import java.util.ArrayList; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link FlacStreamMetadata}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class FlacStreamMetadataTest { @Test diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/Id3PeekerTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/Id3PeekerTest.java index e0cf957a38d..4a252fa0974 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/Id3PeekerTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/Id3PeekerTest.java @@ -29,9 +29,11 @@ import java.io.IOException; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link Id3Peeker}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class Id3PeekerTest { @Test diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/VorbisBitArrayTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/VorbisBitArrayTest.java index 6d29af51275..567be685db7 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/VorbisBitArrayTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/VorbisBitArrayTest.java @@ -21,9 +21,11 @@ import com.google.android.exoplayer2.testutil.TestUtil; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link VorbisBitArray}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class VorbisBitArrayTest { @Test @@ -147,5 +149,4 @@ public void readBitsIllegalLengths() throws Exception { bitArray.readBit(); assertThat(bitArray.getPosition()).isEqualTo(1); } - } diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/VorbisUtilTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/VorbisUtilTest.java index 9f0d6e0ff2b..fb6892b3646 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/VorbisUtilTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/VorbisUtilTest.java @@ -28,9 +28,11 @@ import java.io.IOException; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link VorbisUtil}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class VorbisUtilTest { @Test @@ -103,15 +105,15 @@ public void readVorbisModes() throws IOException { @Test public void verifyVorbisHeaderCapturePattern_withValidHeader_returnsTrue() throws ParserException { - ParsableByteArray header = new ParsableByteArray( - new byte[] {0x01, 'v', 'o', 'r', 'b', 'i', 's'}); + ParsableByteArray header = + new ParsableByteArray(new byte[] {0x01, 'v', 'o', 'r', 'b', 'i', 's'}); assertThat(verifyVorbisHeaderCapturePattern(0x01, header, false)).isTrue(); } @Test public void verifyVorbisHeaderCapturePattern_withValidHeader_returnsFalse() { - ParsableByteArray header = new ParsableByteArray( - new byte[] {0x01, 'v', 'o', 'r', 'b', 'i', 's'}); + ParsableByteArray header = + new ParsableByteArray(new byte[] {0x01, 'v', 'o', 'r', 'b', 'i', 's'}); try { VorbisUtil.verifyVorbisHeaderCapturePattern(0x99, header, false); fail(); @@ -123,15 +125,15 @@ public void verifyVorbisHeaderCapturePattern_withValidHeader_returnsFalse() { @Test public void verifyVorbisHeaderCapturePattern_withInvalidHeaderQuite_returnsFalse() throws ParserException { - ParsableByteArray header = new ParsableByteArray( - new byte[] {0x01, 'v', 'o', 'r', 'b', 'i', 's'}); + ParsableByteArray header = + new ParsableByteArray(new byte[] {0x01, 'v', 'o', 'r', 'b', 'i', 's'}); assertThat(verifyVorbisHeaderCapturePattern(0x99, header, true)).isFalse(); } @Test public void verifyVorbisHeaderCapturePattern_withInvalidPattern_returnsFalse() { - ParsableByteArray header = new ParsableByteArray( - new byte[] {0x01, 'x', 'v', 'o', 'r', 'b', 'i', 's'}); + ParsableByteArray header = + new ParsableByteArray(new byte[] {0x01, 'x', 'v', 'o', 'r', 'b', 'i', 's'}); try { VorbisUtil.verifyVorbisHeaderCapturePattern(0x01, header, false); fail(); @@ -143,9 +145,8 @@ public void verifyVorbisHeaderCapturePattern_withInvalidPattern_returnsFalse() { @Test public void verifyVorbisHeaderCapturePatternQuite_withInvalidPatternQuite_returnsFalse() throws ParserException { - ParsableByteArray header = new ParsableByteArray( - new byte[] {0x01, 'x', 'v', 'o', 'r', 'b', 'i', 's'}); + ParsableByteArray header = + new ParsableByteArray(new byte[] {0x01, 'x', 'v', 'o', 'r', 'b', 'i', 's'}); assertThat(verifyVorbisHeaderCapturePattern(0x01, header, true)).isFalse(); } - } diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/amr/AmrExtractorNonParameterizedTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/amr/AmrExtractorNonParameterizedTest.java index 4c31858a41c..ea81846ceee 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/amr/AmrExtractorNonParameterizedTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/amr/AmrExtractorNonParameterizedTest.java @@ -35,6 +35,7 @@ import java.util.Random; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** * Tests for {@link AmrExtractor} that test specific behaviours and don't need to be parameterized. @@ -43,6 +44,7 @@ * AmrExtractorParameterizedTest}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class AmrExtractorNonParameterizedTest { private static final Random RANDOM = new Random(1234); diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/amr/AmrExtractorParameterizedTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/amr/AmrExtractorParameterizedTest.java index 1c28a143fa7..3fa8d8a7426 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/amr/AmrExtractorParameterizedTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/amr/AmrExtractorParameterizedTest.java @@ -22,6 +22,7 @@ import org.robolectric.ParameterizedRobolectricTestRunner; import org.robolectric.ParameterizedRobolectricTestRunner.Parameter; import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; +import org.robolectric.annotation.internal.DoNotInstrument; /** * Unit tests for {@link AmrExtractor} that use parameterization to test a range of behaviours. @@ -30,6 +31,7 @@ * AmrExtractorNonParameterizedTest}. */ @RunWith(ParameterizedRobolectricTestRunner.class) +@DoNotInstrument public final class AmrExtractorParameterizedTest { @Parameters(name = "{0}") @@ -71,7 +73,6 @@ public void extractingWideBandSamples_withSeeking() throws Exception { simulationConfig); } - private static ExtractorAsserts.ExtractorFactory createAmrExtractorFactory(boolean withSeeking) { return () -> { if (!withSeeking) { diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/amr/AmrExtractorSeekTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/amr/AmrExtractorSeekTest.java index 534cb2572f1..e4ce7d2c971 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/amr/AmrExtractorSeekTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/amr/AmrExtractorSeekTest.java @@ -32,9 +32,11 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit tests for {@link AmrExtractor} seeking behaviour. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class AmrExtractorSeekTest { private static final Random random = new Random(1234L); diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/flac/FlacExtractorSeekTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/flac/FlacExtractorSeekTest.java index 16f92e2b4bd..d89bcf49204 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/flac/FlacExtractorSeekTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/flac/FlacExtractorSeekTest.java @@ -32,9 +32,11 @@ import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Seeking tests for {@link FlacExtractor}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public class FlacExtractorSeekTest { private static final String TEST_FILE_SEEK_TABLE = "media/flac/bear.flac"; diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/flac/FlacExtractorTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/flac/FlacExtractorTest.java index 1d776b93551..9a283928b8c 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/flac/FlacExtractorTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/flac/FlacExtractorTest.java @@ -23,9 +23,11 @@ import org.robolectric.ParameterizedRobolectricTestRunner; import org.robolectric.ParameterizedRobolectricTestRunner.Parameter; import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit tests for {@link FlacExtractor}. */ @RunWith(ParameterizedRobolectricTestRunner.class) +@DoNotInstrument public class FlacExtractorTest { @Parameters(name = "{0}") diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/flv/FlvExtractorSeekTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/flv/FlvExtractorSeekTest.java index e03b7ec6d69..cb1b04b9b97 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/flv/FlvExtractorSeekTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/flv/FlvExtractorSeekTest.java @@ -34,9 +34,11 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Seeking tests for {@link FlvExtractor}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public class FlvExtractorSeekTest { private static final String TEST_FILE_KEY_FRAME_INDEX = diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/flv/FlvExtractorTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/flv/FlvExtractorTest.java index 5a7e0a5a3e9..f6e6b6f2a1c 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/flv/FlvExtractorTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/flv/FlvExtractorTest.java @@ -22,9 +22,11 @@ import org.robolectric.ParameterizedRobolectricTestRunner; import org.robolectric.ParameterizedRobolectricTestRunner.Parameter; import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link FlvExtractor}. */ @RunWith(ParameterizedRobolectricTestRunner.class) +@DoNotInstrument public final class FlvExtractorTest { @Parameters(name = "{0}") diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/jpeg/JpegExtractorTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/jpeg/JpegExtractorTest.java index 8e5556bf81c..fa493f44524 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/jpeg/JpegExtractorTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/jpeg/JpegExtractorTest.java @@ -20,9 +20,11 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.ParameterizedRobolectricTestRunner; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit tests for {@link JpegExtractor}. */ @RunWith(ParameterizedRobolectricTestRunner.class) +@DoNotInstrument public final class JpegExtractorTest { @ParameterizedRobolectricTestRunner.Parameters(name = "{0}") diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/jpeg/MotionPhotoDescriptionTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/jpeg/MotionPhotoDescriptionTest.java index 6c068d2587d..5c9635095d9 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/jpeg/MotionPhotoDescriptionTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/jpeg/MotionPhotoDescriptionTest.java @@ -24,9 +24,11 @@ import com.google.common.collect.ImmutableList; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link MotionPhotoDescription}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class MotionPhotoDescriptionTest { private static final long TEST_PRESENTATION_TIMESTAMP_US = 5L; diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mkv/DefaultEbmlReaderTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mkv/DefaultEbmlReaderTest.java index a8275fd64ce..3ba902ec882 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mkv/DefaultEbmlReaderTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mkv/DefaultEbmlReaderTest.java @@ -27,9 +27,11 @@ import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Tests {@link DefaultEbmlReader}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public class DefaultEbmlReaderTest { @Test @@ -104,8 +106,7 @@ public void stringElementEmpty() throws IOException { @Test public void floatElementFourBytes() throws IOException { - ExtractorInput input = - createTestInput(0x44, 0x89, 0x84, 0x3F, 0x80, 0x00, 0x00); + ExtractorInput input = createTestInput(0x44, 0x89, 0x84, 0x3F, 0x80, 0x00, 0x00); TestProcessor expected = new TestProcessor(); expected.floatElement(TestProcessor.ID_DURATION, 1.0); assertEvents(input, expected.events); @@ -206,8 +207,9 @@ public boolean isLevel1Element(int id) { @Override public void startMasterElement(int id, long contentPosition, long contentSize) { - events.add(formatEvent(id, "start contentPosition=" + contentPosition - + " contentSize=" + contentSize)); + events.add( + formatEvent( + id, "start contentPosition=" + contentPosition + " contentSize=" + contentSize)); } @Override @@ -240,7 +242,5 @@ public void binaryElement(int id, int contentSize, ExtractorInput input) throws private static String formatEvent(int id, String event) { return "[" + Integer.toHexString(id) + "] " + event; } - } - } diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractorTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractorTest.java index 64faff9a0ec..28e70575772 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractorTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractorTest.java @@ -22,9 +22,11 @@ import org.robolectric.ParameterizedRobolectricTestRunner; import org.robolectric.ParameterizedRobolectricTestRunner.Parameter; import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; +import org.robolectric.annotation.internal.DoNotInstrument; /** Tests for {@link MatroskaExtractor}. */ @RunWith(ParameterizedRobolectricTestRunner.class) +@DoNotInstrument public final class MatroskaExtractorTest { @Parameters(name = "{0}") diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mkv/VarintReaderTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mkv/VarintReaderTest.java index 7a3c73e4d5b..860bc009b21 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mkv/VarintReaderTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mkv/VarintReaderTest.java @@ -29,9 +29,11 @@ import java.io.IOException; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Tests for {@link VarintReader}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class VarintReaderTest { private static final byte MAX_BYTE = (byte) 0xFF; @@ -88,9 +90,7 @@ public final class VarintReaderTest { public void readVarintEndOfInputAtStart() throws IOException { VarintReader reader = new VarintReader(); // Build an input with no data. - ExtractorInput input = new FakeExtractorInput.Builder() - .setSimulateUnknownLength(true) - .build(); + ExtractorInput input = new FakeExtractorInput.Builder().setSimulateUnknownLength(true).build(); // End of input allowed. long result = reader.readUnsignedVarint(input, true, false, 8); assertThat(result).isEqualTo(RESULT_END_OF_INPUT); @@ -106,10 +106,11 @@ public void readVarintEndOfInputAtStart() throws IOException { @Test public void readVarintExceedsMaximumAllowedLength() throws IOException { VarintReader reader = new VarintReader(); - ExtractorInput input = new FakeExtractorInput.Builder() - .setData(DATA_8_BYTE_0) - .setSimulateUnknownLength(true) - .build(); + ExtractorInput input = + new FakeExtractorInput.Builder() + .setData(DATA_8_BYTE_0) + .setSimulateUnknownLength(true) + .build(); long result = reader.readUnsignedVarint(input, false, true, 4); assertThat(result).isEqualTo(RESULT_MAX_LENGTH_EXCEEDED); } @@ -191,10 +192,8 @@ public void readVarintFlaky() throws IOException { private static void testReadVarint( VarintReader reader, boolean removeMask, byte[] data, int expectedLength, long expectedValue) throws IOException { - ExtractorInput input = new FakeExtractorInput.Builder() - .setData(data) - .setSimulateUnknownLength(true) - .build(); + ExtractorInput input = + new FakeExtractorInput.Builder().setData(data).setSimulateUnknownLength(true).build(); long result = reader.readUnsignedVarint(input, false, removeMask, 8); assertThat(input.getPosition()).isEqualTo(expectedLength); assertThat(result).isEqualTo(expectedValue); @@ -203,12 +202,13 @@ private static void testReadVarint( private static void testReadVarintFlaky( VarintReader reader, boolean removeMask, byte[] data, int expectedLength, long expectedValue) throws IOException { - ExtractorInput input = new FakeExtractorInput.Builder() - .setData(data) - .setSimulateUnknownLength(true) - .setSimulateIOErrors(true) - .setSimulatePartialReads(true) - .build(); + ExtractorInput input = + new FakeExtractorInput.Builder() + .setData(data) + .setSimulateUnknownLength(true) + .setSimulateIOErrors(true) + .setSimulatePartialReads(true) + .build(); long result = -1; while (result == -1) { try { @@ -224,5 +224,4 @@ private static void testReadVarintFlaky( assertThat(input.getPosition()).isEqualTo(expectedLength); assertThat(result).isEqualTo(expectedValue); } - } diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp3/ConstantBitrateSeekerTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp3/ConstantBitrateSeekerTest.java index e3137a106dd..713a269185d 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp3/ConstantBitrateSeekerTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp3/ConstantBitrateSeekerTest.java @@ -34,9 +34,11 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Tests for {@link ConstantBitrateSeeker}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public class ConstantBitrateSeekerTest { private static final String CONSTANT_FRAME_SIZE_TEST_FILE = "media/mp3/bear-cbr-constant-frame-size-no-seek-table.mp3"; diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp3/IndexSeekerTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp3/IndexSeekerTest.java index 24530c12f17..679ee526bcf 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp3/IndexSeekerTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp3/IndexSeekerTest.java @@ -35,9 +35,11 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Tests for {@link IndexSeeker}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public class IndexSeekerTest { private static final String TEST_FILE_NO_SEEK_TABLE = "media/mp3/bear-vbr-no-seek-table.mp3"; diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp3/Mp3ExtractorTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp3/Mp3ExtractorTest.java index f209574de45..5d9e0380fb3 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp3/Mp3ExtractorTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp3/Mp3ExtractorTest.java @@ -23,9 +23,11 @@ import org.robolectric.ParameterizedRobolectricTestRunner; import org.robolectric.ParameterizedRobolectricTestRunner.Parameter; import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link Mp3Extractor}. */ @RunWith(ParameterizedRobolectricTestRunner.class) +@DoNotInstrument public final class Mp3ExtractorTest { @Parameters(name = "{0}") diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp3/XingSeekerTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp3/XingSeekerTest.java index 7c481831c22..b18f32edb33 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp3/XingSeekerTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp3/XingSeekerTest.java @@ -27,30 +27,27 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Tests for {@link XingSeeker}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class XingSeekerTest { // Xing header/payload from http://storage.googleapis.com/exoplayer-test-media-0/play.mp3. private static final int XING_FRAME_HEADER_DATA = 0xFFFB3000; - private static final byte[] XING_FRAME_PAYLOAD = Util.getBytesFromHexString( - "00000007000008dd000e7919000205080a0d0f1214171a1c1e212426292c2e303336383b3d404245484a4c4f5254" - + "575a5c5e616466696b6e707376787a7d808285878a8c8f929496999c9ea1a4a6a8abaeb0b3b5b8babdc0c2c4c7" - + "cacccfd2d4d6d9dcdee1e3e6e8ebeef0f2f5f8fafd"); + private static final byte[] XING_FRAME_PAYLOAD = + Util.getBytesFromHexString( + "00000007000008dd000e7919000205080a0d0f1214171a1c1e212426292c2e303336383b3d404245484a4c4f5254" + + "575a5c5e616466696b6e707376787a7d808285878a8c8f929496999c9ea1a4a6a8abaeb0b3b5b8babdc0c2c4c7" + + "cacccfd2d4d6d9dcdee1e3e6e8ebeef0f2f5f8fafd"); private static final int XING_FRAME_POSITION = 157; - /** - * Data size, as encoded in {@link #XING_FRAME_PAYLOAD}. - */ + /** Data size, as encoded in {@link #XING_FRAME_PAYLOAD}. */ private static final int DATA_SIZE_BYTES = 948505; - /** - * Duration of the audio stream in microseconds, encoded in {@link #XING_FRAME_PAYLOAD}. - */ + /** Duration of the audio stream in microseconds, encoded in {@link #XING_FRAME_PAYLOAD}. */ private static final int STREAM_DURATION_US = 59271836; - /** - * The length of the stream in bytes. - */ + /** The length of the stream in bytes. */ private static final int STREAM_LENGTH = XING_FRAME_POSITION + DATA_SIZE_BYTES; private XingSeeker seeker; @@ -61,10 +58,18 @@ public final class XingSeekerTest { public void setUp() throws Exception { MpegAudioUtil.Header xingFrameHeader = new MpegAudioUtil.Header(); xingFrameHeader.setForHeaderData(XING_FRAME_HEADER_DATA); - seeker = XingSeeker.create(C.LENGTH_UNSET, XING_FRAME_POSITION, xingFrameHeader, - new ParsableByteArray(XING_FRAME_PAYLOAD)); - seekerWithInputLength = XingSeeker.create(STREAM_LENGTH, - XING_FRAME_POSITION, xingFrameHeader, new ParsableByteArray(XING_FRAME_PAYLOAD)); + seeker = + XingSeeker.create( + C.LENGTH_UNSET, + XING_FRAME_POSITION, + xingFrameHeader, + new ParsableByteArray(XING_FRAME_PAYLOAD)); + seekerWithInputLength = + XingSeeker.create( + STREAM_LENGTH, + XING_FRAME_POSITION, + xingFrameHeader, + new ParsableByteArray(XING_FRAME_PAYLOAD)); xingFrameSize = xingFrameHeader.frameSize; } @@ -82,11 +87,8 @@ public void getTimeUsAtFirstAudioFrame() { @Test public void getTimeUsAtEndOfStream() { - assertThat(seeker.getTimeUs(STREAM_LENGTH)) - .isEqualTo(STREAM_DURATION_US); - assertThat( - seekerWithInputLength.getTimeUs(STREAM_LENGTH)) - .isEqualTo(STREAM_DURATION_US); + assertThat(seeker.getTimeUs(STREAM_LENGTH)).isEqualTo(STREAM_DURATION_US); + assertThat(seekerWithInputLength.getTimeUs(STREAM_LENGTH)).isEqualTo(STREAM_DURATION_US); } @Test @@ -125,5 +127,4 @@ public void getTimeForAllPositions() { assertThat(seekPoint.position).isEqualTo(position); } } - } diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/AtomParsersTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/AtomParsersTest.java index 651384094f3..226b40559b3 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/AtomParsersTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/AtomParsersTest.java @@ -19,32 +19,39 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.Util; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Tests for {@link AtomParsers}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class AtomParsersTest { private static final String ATOM_HEADER = "000000000000000000000000"; private static final String SAMPLE_COUNT = "00000004"; - private static final byte[] FOUR_BIT_STZ2 = Util.getBytesFromHexString(ATOM_HEADER + "00000004" - + SAMPLE_COUNT + "1234"); - private static final byte[] EIGHT_BIT_STZ2 = Util.getBytesFromHexString(ATOM_HEADER + "00000008" - + SAMPLE_COUNT + "01020304"); - private static final byte[] SIXTEEN_BIT_STZ2 = Util.getBytesFromHexString(ATOM_HEADER + "00000010" - + SAMPLE_COUNT + "0001000200030004"); + private static final byte[] FOUR_BIT_STZ2 = + Util.getBytesFromHexString(ATOM_HEADER + "00000004" + SAMPLE_COUNT + "1234"); + private static final byte[] EIGHT_BIT_STZ2 = + Util.getBytesFromHexString(ATOM_HEADER + "00000008" + SAMPLE_COUNT + "01020304"); + private static final byte[] SIXTEEN_BIT_STZ2 = + Util.getBytesFromHexString(ATOM_HEADER + "00000010" + SAMPLE_COUNT + "0001000200030004"); @Test - public void parseCommonEncryptionSinfFromParentIgnoresUnknownSchemeType() { - byte[] cencSinf = new byte[] { - 0, 0, 0, 24, 115, 105, 110, 102, // size (4), 'sinf' (4) - 0, 0, 0, 16, 115, 99, 104, 109, // size (4), 'schm' (4) - 0, 0, 0, 0, 88, 88, 88, 88}; // version (1), flags (3), 'xxxx' (4) - assertThat(AtomParsers.parseCommonEncryptionSinfFromParent( - new ParsableByteArray(cencSinf), 0, cencSinf.length)).isNull(); + public void parseCommonEncryptionSinfFromParentIgnoresUnknownSchemeType() throws ParserException { + byte[] cencSinf = + new byte[] { + 0, 0, 0, 24, 115, 105, 110, 102, // size (4), 'sinf' (4) + 0, 0, 0, 16, 115, 99, 104, 109, // size (4), 'schm' (4) + 0, 0, 0, 0, 88, 88, 88, 88 + }; // version (1), flags (3), 'xxxx' (4) + assertThat( + AtomParsers.parseCommonEncryptionSinfFromParent( + new ParsableByteArray(cencSinf), 0, cencSinf.length)) + .isNull(); } @Test @@ -70,5 +77,4 @@ private static void verifyStz2Parsing(Atom.LeafAtom stz2Atom) { assertThat(box.readNextSampleSize()).isEqualTo(i + 1); } } - } diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4ExtractorNoSniffingTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4ExtractorNoSniffingTest.java index 969c9b8d5a7..a4704570449 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4ExtractorNoSniffingTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4ExtractorNoSniffingTest.java @@ -25,11 +25,13 @@ import org.robolectric.ParameterizedRobolectricTestRunner; import org.robolectric.ParameterizedRobolectricTestRunner.Parameter; import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; +import org.robolectric.annotation.internal.DoNotInstrument; /** * Tests for {@link FragmentedMp4Extractor} that test behaviours where sniffing must not be tested. */ @RunWith(ParameterizedRobolectricTestRunner.class) +@DoNotInstrument public class FragmentedMp4ExtractorNoSniffingTest { @Parameters(name = "{0}") diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4ExtractorTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4ExtractorTest.java index a9d2397ca71..14783a27b03 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4ExtractorTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4ExtractorTest.java @@ -27,9 +27,11 @@ import org.robolectric.ParameterizedRobolectricTestRunner; import org.robolectric.ParameterizedRobolectricTestRunner.Parameter; import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; +import org.robolectric.annotation.internal.DoNotInstrument; /** Tests for {@link FragmentedMp4Extractor} that test behaviours where sniffing must be tested. */ @RunWith(ParameterizedRobolectricTestRunner.class) +@DoNotInstrument public final class FragmentedMp4ExtractorTest { @Parameters(name = "{0}") diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/MetadataUtilTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/MetadataUtilTest.java index 70e483457a5..471e654a096 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/MetadataUtilTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/MetadataUtilTest.java @@ -20,9 +20,11 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Test for {@link MetadataUtil}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class MetadataUtilTest { @Test diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/Mp4ExtractorTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/Mp4ExtractorTest.java index a270ee02a32..8d8bd0dfa12 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/Mp4ExtractorTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/Mp4ExtractorTest.java @@ -22,9 +22,11 @@ import org.robolectric.ParameterizedRobolectricTestRunner; import org.robolectric.ParameterizedRobolectricTestRunner.Parameter; import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; +import org.robolectric.annotation.internal.DoNotInstrument; /** Tests for {@link Mp4Extractor}. */ @RunWith(ParameterizedRobolectricTestRunner.class) +@DoNotInstrument public final class Mp4ExtractorTest { @Parameters(name = "{0}") @@ -96,4 +98,10 @@ public void mp4SampleWithMhm1Track() throws Exception { ExtractorAsserts.assertBehavior( Mp4Extractor::new, "media/mp4/sample_mpegh_mhm1.mp4", simulationConfig); } + + @Test + public void mp4SampleWithColorInfo() throws Exception { + ExtractorAsserts.assertBehavior( + Mp4Extractor::new, "media/mp4/sample_with_color_info.mp4", simulationConfig); + } } diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/PsshAtomUtilTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/PsshAtomUtilTest.java index cc5dd3cdd18..e526c9e3c88 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/PsshAtomUtilTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/PsshAtomUtilTest.java @@ -27,14 +27,16 @@ import java.util.UUID; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Tests for {@link PsshAtomUtil}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class PsshAtomUtilTest { @Test public void buildPsshAtom() { - byte[] schemeData = new byte[]{0, 1, 2, 3, 4, 5}; + byte[] schemeData = new byte[] {0, 1, 2, 3, 4, 5}; byte[] psshAtom = PsshAtomUtil.buildPsshAtom(C.WIDEVINE_UUID, schemeData); // Read the PSSH atom back and assert its content is as expected. ParsableByteArray parsablePsshAtom = new ParsableByteArray(psshAtom); @@ -50,5 +52,4 @@ public void buildPsshAtom() { parsablePsshAtom.readBytes(psshSchemeData, 0, schemeData.length); assertThat(psshSchemeData).isEqualTo(schemeData); } - } diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/SlowMotionDataTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/SlowMotionDataTest.java index 5b1c33303dd..c22220931f3 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/SlowMotionDataTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/SlowMotionDataTest.java @@ -24,9 +24,11 @@ import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link SlowMotionData} */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public class SlowMotionDataTest { @Test diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeekerTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeekerTest.java index e30f27713eb..1ee87d1b1db 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeekerTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeekerTest.java @@ -30,9 +30,11 @@ import java.util.Random; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link DefaultOggSeeker}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class DefaultOggSeekerTest { private final Random random = new Random(/* seed= */ 0); diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/OggExtractorNonParameterizedTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/OggExtractorNonParameterizedTest.java index d939d51b775..4131054775b 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/OggExtractorNonParameterizedTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/OggExtractorNonParameterizedTest.java @@ -28,6 +28,7 @@ import java.io.IOException; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** * Tests for {@link OggExtractor} that test specific behaviours and don't need to be parameterized. @@ -36,6 +37,7 @@ * OggExtractorParameterizedTest}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class OggExtractorNonParameterizedTest { @Test diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/OggExtractorParameterizedTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/OggExtractorParameterizedTest.java index 8cbe254f07f..48828b9b4a4 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/OggExtractorParameterizedTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/OggExtractorParameterizedTest.java @@ -22,6 +22,7 @@ import org.robolectric.ParameterizedRobolectricTestRunner; import org.robolectric.ParameterizedRobolectricTestRunner.Parameter; import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; +import org.robolectric.annotation.internal.DoNotInstrument; /** * Unit tests for {@link OggExtractor} that use parameterization to test a range of behaviours. @@ -29,6 +30,7 @@ *

    For non-parameterized tests see {@link OggExtractorNonParameterizedTest}. */ @RunWith(ParameterizedRobolectricTestRunner.class) +@DoNotInstrument public final class OggExtractorParameterizedTest { @Parameters(name = "{0}") diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/OggPacketTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/OggPacketTest.java index e74ecf7be05..d9bbe348f9c 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/OggPacketTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/OggPacketTest.java @@ -28,9 +28,11 @@ import java.util.Random; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link OggPacket}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class OggPacketTest { private static final String TEST_FILE = "media/ogg/bear.opus"; diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/OggPageHeaderTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/OggPageHeaderTest.java index c952c0b220f..89c83063422 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/OggPageHeaderTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/OggPageHeaderTest.java @@ -28,9 +28,11 @@ import java.util.Random; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link OggPageHeader}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class OggPageHeaderTest { private final Random random; @@ -172,4 +174,3 @@ private interface ThrowingSupplier { S get() throws E; } } - diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/VorbisReaderTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/VorbisReaderTest.java index 7db02d47890..e9387433793 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/VorbisReaderTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/VorbisReaderTest.java @@ -30,9 +30,11 @@ import java.io.IOException; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link VorbisReader}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class VorbisReaderTest { @Test @@ -62,8 +64,13 @@ public void readSetupHeaders_withIOExceptions_readSuccess() throws IOException { byte[] data = TestUtil.getByteArray( ApplicationProvider.getApplicationContext(), "media/binary/ogg/vorbis_header_pages"); - ExtractorInput input = new FakeExtractorInput.Builder().setData(data).setSimulateIOErrors(true) - .setSimulateUnknownLength(true).setSimulatePartialReads(true).build(); + ExtractorInput input = + new FakeExtractorInput.Builder() + .setData(data) + .setSimulateIOErrors(true) + .setSimulateUnknownLength(true) + .setSimulatePartialReads(true) + .build(); VorbisReader reader = new VorbisReader(); VorbisReader.VorbisSetup vorbisSetup = readSetupHeaders(reader, input); @@ -114,5 +121,4 @@ private static VorbisSetup readSetupHeaders(VorbisReader reader, ExtractorInput } } } - } diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/rawcc/RawCcExtractorTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/rawcc/RawCcExtractorTest.java index 3856f2b573b..5873bfc9b78 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/rawcc/RawCcExtractorTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/rawcc/RawCcExtractorTest.java @@ -22,9 +22,11 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.ParameterizedRobolectricTestRunner; +import org.robolectric.annotation.internal.DoNotInstrument; /** Tests for {@link RawCcExtractor}. */ @RunWith(ParameterizedRobolectricTestRunner.class) +@DoNotInstrument public final class RawCcExtractorTest { @ParameterizedRobolectricTestRunner.Parameters(name = "{0}") diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/Ac3ExtractorTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/Ac3ExtractorTest.java index 8b0ffef80d3..6f28ecde4a6 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/Ac3ExtractorTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/Ac3ExtractorTest.java @@ -22,9 +22,11 @@ import org.robolectric.ParameterizedRobolectricTestRunner; import org.robolectric.ParameterizedRobolectricTestRunner.Parameter; import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link Ac3Extractor}. */ @RunWith(ParameterizedRobolectricTestRunner.class) +@DoNotInstrument public final class Ac3ExtractorTest { @Parameters(name = "{0}") diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/Ac4ExtractorTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/Ac4ExtractorTest.java index 39ab1bb5347..50f04c43fc1 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/Ac4ExtractorTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/Ac4ExtractorTest.java @@ -22,9 +22,11 @@ import org.robolectric.ParameterizedRobolectricTestRunner; import org.robolectric.ParameterizedRobolectricTestRunner.Parameter; import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link Ac4Extractor}. */ @RunWith(ParameterizedRobolectricTestRunner.class) +@DoNotInstrument public final class Ac4ExtractorTest { @Parameters(name = "{0}") diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/AdtsExtractorSeekTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/AdtsExtractorSeekTest.java index 2770d4ef66b..59c5130050d 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/AdtsExtractorSeekTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/AdtsExtractorSeekTest.java @@ -32,9 +32,11 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link AdtsExtractor}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class AdtsExtractorSeekTest { private static final Random random = new Random(1234L); diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/AdtsExtractorTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/AdtsExtractorTest.java index 420d8d589b2..fb70fe603c6 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/AdtsExtractorTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/AdtsExtractorTest.java @@ -23,9 +23,11 @@ import org.robolectric.ParameterizedRobolectricTestRunner; import org.robolectric.ParameterizedRobolectricTestRunner.Parameter; import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link AdtsExtractor}. */ @RunWith(ParameterizedRobolectricTestRunner.class) +@DoNotInstrument public final class AdtsExtractorTest { @Parameters(name = "{0}") diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/AdtsReaderTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/AdtsReaderTest.java index 6869c0314c2..ed1726e50b1 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/AdtsReaderTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/AdtsReaderTest.java @@ -31,9 +31,11 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Test for {@link AdtsReader}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public class AdtsReaderTest { public static final byte[] ID3_DATA_1 = diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/PsDurationReaderTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/PsDurationReaderTest.java index 8c1805c5689..df79f0bba92 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/PsDurationReaderTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/PsDurationReaderTest.java @@ -27,9 +27,11 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link PsDurationReader}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class PsDurationReaderTest { private PsDurationReader tsDurationReader; diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/PsExtractorSeekTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/PsExtractorSeekTest.java index d2d76d6695b..9c8ee8687bb 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/PsExtractorSeekTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/PsExtractorSeekTest.java @@ -41,9 +41,11 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Seeking tests for {@link PsExtractor}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class PsExtractorSeekTest { private static final String PS_FILE_PATH = "media/ts/elephants_dream.mpg"; diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/PsExtractorTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/PsExtractorTest.java index 688cc318f18..7143ca07832 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/PsExtractorTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/PsExtractorTest.java @@ -22,9 +22,11 @@ import org.robolectric.ParameterizedRobolectricTestRunner; import org.robolectric.ParameterizedRobolectricTestRunner.Parameter; import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link PsExtractor}. */ @RunWith(ParameterizedRobolectricTestRunner.class) +@DoNotInstrument public final class PsExtractorTest { @Parameters(name = "{0}") diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/SectionReaderTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/SectionReaderTest.java index a023a32729b..7866e67d47a 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/SectionReaderTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/SectionReaderTest.java @@ -31,9 +31,11 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Test for {@link SectionReader}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class SectionReaderTest { private byte[] packetPayload; @@ -46,7 +48,9 @@ public void setUp() { Arrays.fill(packetPayload, (byte) 0xFF); payloadReader = new CustomSectionPayloadReader(); reader = new SectionReader(payloadReader); - reader.init(new TimestampAdjuster(0), new FakeExtractorOutput(), + reader.init( + new TimestampAdjuster(0), + new FakeExtractorOutput(), new TsPayloadReader.TrackIdGenerator(0, 1)); } @@ -157,10 +161,12 @@ public void seek() { @Test public void crcChecks() { - byte[] correctCrcPat = new byte[] { - (byte) 0x0, (byte) 0x0, (byte) 0xb0, (byte) 0xd, (byte) 0x0, (byte) 0x1, (byte) 0xc1, - (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x1, (byte) 0xe1, (byte) 0x0, (byte) 0xe8, - (byte) 0xf9, (byte) 0x5e, (byte) 0x7d}; + byte[] correctCrcPat = + new byte[] { + (byte) 0x0, (byte) 0x0, (byte) 0xb0, (byte) 0xd, (byte) 0x0, (byte) 0x1, (byte) 0xc1, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x1, (byte) 0xe1, (byte) 0x0, (byte) 0xe8, + (byte) 0xf9, (byte) 0x5e, (byte) 0x7d + }; byte[] incorrectCrcPat = Arrays.copyOf(correctCrcPat, correctCrcPat.length); // Crc field is incorrect, and should not be passed to the payload reader. incorrectCrcPat[16]--; @@ -192,7 +198,9 @@ private static final class CustomSectionPayloadReader implements SectionPayloadR List parsedTableIds; @Override - public void init(TimestampAdjuster timestampAdjuster, ExtractorOutput extractorOutput, + public void init( + TimestampAdjuster timestampAdjuster, + ExtractorOutput extractorOutput, TsPayloadReader.TrackIdGenerator idGenerator) { parsedTableIds = new ArrayList<>(); } @@ -201,7 +209,5 @@ public void init(TimestampAdjuster timestampAdjuster, ExtractorOutput extractorO public void consume(ParsableByteArray sectionData) { parsedTableIds.add(sectionData.readUnsignedByte()); } - } - } diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/TsDurationReaderTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/TsDurationReaderTest.java index 0e55d292b8c..97c74e4292b 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/TsDurationReaderTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/TsDurationReaderTest.java @@ -27,9 +27,11 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link TsDurationReader}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class TsDurationReaderTest { private TsDurationReader tsDurationReader; diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/TsExtractorSeekTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/TsExtractorSeekTest.java index a796f3c9940..1123e14a967 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/TsExtractorSeekTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/TsExtractorSeekTest.java @@ -36,9 +36,11 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Seeking tests for {@link TsExtractor}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public final class TsExtractorSeekTest { private static final String TEST_FILE = "media/ts/bbb_2500ms.ts"; diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/TsExtractorTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/TsExtractorTest.java index 87215d45ee8..f113efbfa5c 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/TsExtractorTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ts/TsExtractorTest.java @@ -42,9 +42,11 @@ import org.robolectric.ParameterizedRobolectricTestRunner; import org.robolectric.ParameterizedRobolectricTestRunner.Parameter; import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link TsExtractor}. */ @RunWith(ParameterizedRobolectricTestRunner.class) +@DoNotInstrument public final class TsExtractorTest { @Parameters(name = "{0}") diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/wav/WavExtractorTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/wav/WavExtractorTest.java index 4217a1528a3..cc35344b2a0 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/wav/WavExtractorTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/wav/WavExtractorTest.java @@ -21,9 +21,11 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.ParameterizedRobolectricTestRunner; +import org.robolectric.annotation.internal.DoNotInstrument; /** Unit test for {@link WavExtractor}. */ @RunWith(ParameterizedRobolectricTestRunner.class) +@DoNotInstrument public final class WavExtractorTest { @ParameterizedRobolectricTestRunner.Parameters(name = "{0}") diff --git a/library/hls/README.md b/library/hls/README.md index b7eecc1ff87..d8b86e18320 100644 --- a/library/hls/README.md +++ b/library/hls/README.md @@ -18,9 +18,9 @@ instances and pass them directly to the player. For advanced download use cases, ## Links ## -* [Developer Guide][]. -* [Javadoc][]: Classes matching `com.google.android.exoplayer2.source.hls.*` - belong to this module. +* [Developer Guide][]. +* [Javadoc][]: Classes matching `com.google.android.exoplayer2.source.hls.*` belong to + this module. [Developer Guide]: https://exoplayer.dev/hls.html [Javadoc]: https://exoplayer.dev/doc/reference/index.html diff --git a/library/hls/build.gradle b/library/hls/build.gradle index d31f1ce6a23..6c94d1d4441 100644 --- a/library/hls/build.gradle +++ b/library/hls/build.gradle @@ -32,7 +32,7 @@ dependencies { testImplementation project(modulePrefix + 'robolectricutils') testImplementation project(modulePrefix + 'testutils') testImplementation project(modulePrefix + 'testdata') - testImplementation 'com.squareup.okhttp3:mockwebserver:' + mockWebServerVersion + testImplementation 'com.squareup.okhttp3:mockwebserver:' + okhttpVersion testImplementation 'org.robolectric:robolectric:' + robolectricVersion } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/Aes128DataSource.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/Aes128DataSource.java index 11d68b1c089..617df277bf7 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/Aes128DataSource.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/Aes128DataSource.java @@ -96,9 +96,9 @@ public final long open(DataSpec dataSpec) throws IOException { } @Override - public final int read(byte[] buffer, int offset, int readLength) throws IOException { + public final int read(byte[] buffer, int offset, int length) throws IOException { Assertions.checkNotNull(cipherInputStream); - int bytesRead = cipherInputStream.read(buffer, offset, readLength); + int bytesRead = cipherInputStream.read(buffer, offset, length); if (bytesRead < 0) { return C.RESULT_END_OF_INPUT; } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/DefaultHlsDataSourceFactory.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/DefaultHlsDataSourceFactory.java index 5382e5f6e37..25c0e8c0e63 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/DefaultHlsDataSourceFactory.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/DefaultHlsDataSourceFactory.java @@ -22,9 +22,7 @@ public final class DefaultHlsDataSourceFactory implements HlsDataSourceFactory { private final DataSource.Factory dataSourceFactory; - /** - * @param dataSourceFactory The {@link DataSource.Factory} to use for all data types. - */ + /** @param dataSourceFactory The {@link DataSource.Factory} to use for all data types. */ public DefaultHlsDataSourceFactory(DataSource.Factory dataSourceFactory) { this.dataSourceFactory = dataSourceFactory; } @@ -33,5 +31,4 @@ public DefaultHlsDataSourceFactory(DataSource.Factory dataSourceFactory) { public DataSource createDataSource(int dataType) { return dataSourceFactory.createDataSource(); } - } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/DefaultHlsExtractorFactory.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/DefaultHlsExtractorFactory.java index 81798aa676b..77f301a241a 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/DefaultHlsExtractorFactory.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/DefaultHlsExtractorFactory.java @@ -94,7 +94,7 @@ public BundledHlsMediaChunkExtractor createExtractor( @Nullable List muxedCaptionFormats, TimestampAdjuster timestampAdjuster, Map> responseHeaders, - ExtractorInput extractorInput) + ExtractorInput sniffingExtractorInput) throws IOException { @FileTypes.Type int formatInferredFileType = FileTypes.inferFileTypeFromMimeType(format.sampleMimeType); @@ -115,13 +115,13 @@ public BundledHlsMediaChunkExtractor createExtractor( // Extractor to be used if the type is not recognized. @Nullable Extractor fallBackExtractor = null; - extractorInput.resetPeekPosition(); + sniffingExtractorInput.resetPeekPosition(); for (int i = 0; i < fileTypeOrder.size(); i++) { int fileType = fileTypeOrder.get(i); Extractor extractor = checkNotNull( createExtractorByFileType(fileType, format, muxedCaptionFormats, timestampAdjuster)); - if (sniffQuietly(extractor, extractorInput)) { + if (sniffQuietly(extractor, sniffingExtractorInput)) { return new BundledHlsMediaChunkExtractor(extractor, format, timestampAdjuster); } if (fallBackExtractor == null diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java index efc73779028..7c36d257b12 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java @@ -59,9 +59,7 @@ /** Source of Hls (possibly adaptive) chunks. */ /* package */ class HlsChunkSource { - /** - * Chunk holder that allows the scheduling of retries. - */ + /** Chunk holder that allows the scheduling of retries. */ public static final class HlsChunkHolder { public HlsChunkHolder() { @@ -71,17 +69,13 @@ public HlsChunkHolder() { /** The chunk to be loaded next. */ @Nullable public Chunk chunk; - /** - * Indicates that the end of the stream has been reached. - */ + /** Indicates that the end of the stream has been reached. */ public boolean endOfStream; /** Indicates that the chunk source is waiting for the referred playlist to be refreshed. */ @Nullable public Uri playlistUrl; - /** - * Clears the holder. - */ + /** Clears the holder. */ public void clear() { chunk = null; endOfStream = false; @@ -209,9 +203,7 @@ public void maybeThrowError() throws IOException { } } - /** - * Returns the track group exposed by the source. - */ + /** Returns the track group exposed by the source. */ public TrackGroup getTrackGroup() { return trackGroup; } @@ -230,9 +222,7 @@ public ExoTrackSelection getTrackSelection() { return trackSelection; } - /** - * Resets the source. - */ + /** Resets the source. */ public void reset() { fatalError = null; } @@ -554,7 +544,8 @@ public boolean onPlaylistError(Uri playlistUrl, long exclusionDurationMs) { } seenExpectedPlaylistError |= playlistUrl.equals(expectedPlaylistUrl); return exclusionDurationMs == C.TIME_UNSET - || trackSelection.blacklist(trackSelectionIndex, exclusionDurationMs); + || (trackSelection.blacklist(trackSelectionIndex, exclusionDurationMs) + && playlistTracker.excludeMediaPlaylist(playlistUrl, exclusionDurationMs)); } /** @@ -679,6 +670,11 @@ public boolean shouldCancelLoad( return Collections.unmodifiableList(segmentBases); } + /** Returns whether this chunk source obtains chunks for the playlist with the given url. */ + public boolean obtainsChunksForPlaylist(Uri playlistUrl) { + return Util.contains(playlistUrls, playlistUrl); + } + // Private methods. /** @@ -869,7 +865,6 @@ public int getSelectionReason() { public Object getSelectionData() { return null; } - } private static final class EncryptionKeyChunk extends DataChunk { @@ -883,8 +878,14 @@ public EncryptionKeyChunk( int trackSelectionReason, @Nullable Object trackSelectionData, byte[] scratchSpace) { - super(dataSource, dataSpec, C.DATA_TYPE_DRM, trackFormat, trackSelectionReason, - trackSelectionData, scratchSpace); + super( + dataSource, + dataSpec, + C.DATA_TYPE_DRM, + trackFormat, + trackSelectionReason, + trackSelectionData, + scratchSpace); } @Override @@ -897,7 +898,6 @@ protected void consume(byte[] data, int limit) { public byte[] getResult() { return result; } - } @VisibleForTesting diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsDataSourceFactory.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsDataSourceFactory.java index 7ec2f6c1f5e..499797c51a9 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsDataSourceFactory.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsDataSourceFactory.java @@ -29,5 +29,4 @@ public interface HlsDataSourceFactory { * @return A {@link DataSource} for the given data type. */ DataSource createDataSource(int dataType); - } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsManifest.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsManifest.java index cf908145a0c..ff2dcf0ba96 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsManifest.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsManifest.java @@ -21,13 +21,9 @@ /** Holds a master playlist along with a snapshot of one of its media playlists. */ public final class HlsManifest { - /** - * The master playlist of an HLS stream. - */ + /** The master playlist of an HLS stream. */ public final HlsMasterPlaylist masterPlaylist; - /** - * A snapshot of a media playlist referred to by {@link #masterPlaylist}. - */ + /** A snapshot of a media playlist referred to by {@link #masterPlaylist}. */ public final HlsMediaPlaylist mediaPlaylist; /** @@ -38,5 +34,4 @@ public final class HlsManifest { this.masterPlaylist = masterPlaylist; this.mediaPlaylist = mediaPlaylist; } - } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java index e6295cf82bb..930d497e74c 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java @@ -48,9 +48,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.RequiresNonNull; -/** - * An HLS {@link MediaChunk}. - */ +/** An HLS {@link MediaChunk}. */ /* package */ final class HlsMediaChunk extends MediaChunk { /** @@ -229,14 +227,10 @@ public static boolean shouldSpliceIn( private static final AtomicInteger uidSource = new AtomicInteger(); - /** - * A unique identifier for the chunk. - */ + /** A unique identifier for the chunk. */ public final int uid; - /** - * The discontinuity sequence number of the chunk. - */ + /** The discontinuity sequence number of the chunk. */ public final int discontinuitySequenceNumber; /** The url of the playlist from which this chunk was obtained. */ diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java index 66dd308e52e..785e7f1d36b 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java @@ -268,8 +268,8 @@ public long selectTracks( int[] streamChildIndices = new int[selections.length]; int[] selectionChildIndices = new int[selections.length]; for (int i = 0; i < selections.length; i++) { - streamChildIndices[i] = streams[i] == null ? C.INDEX_UNSET - : streamWrapperIndices.get(streams[i]); + streamChildIndices[i] = + streams[i] == null ? C.INDEX_UNSET : streamWrapperIndices.get(streams[i]); selectionChildIndices[i] = C.INDEX_UNSET; if (selections[i] != null) { TrackGroup trackGroup = selections[i].getTrackGroup(); @@ -297,8 +297,14 @@ public long selectTracks( childSelections[j] = selectionChildIndices[j] == i ? selections[j] : null; } HlsSampleStreamWrapper sampleStreamWrapper = sampleStreamWrappers[i]; - boolean wasReset = sampleStreamWrapper.selectTracks(childSelections, mayRetainStreamFlags, - childStreams, streamResetFlags, positionUs, forceReset); + boolean wasReset = + sampleStreamWrapper.selectTracks( + childSelections, + mayRetainStreamFlags, + childStreams, + streamResetFlags, + positionUs, + forceReset); boolean wrapperEnabled = false; for (int j = 0; j < selections.length; j++) { SampleStream childStream = childStreams[j]; @@ -320,7 +326,8 @@ public long selectTracks( // that the first wrapper will correspond to a variant, or else an audio rendition, or // else a text rendition, in that order. sampleStreamWrapper.setIsTimestampMaster(true); - if (wasReset || enabledSampleStreamWrappers.length == 0 + if (wasReset + || enabledSampleStreamWrappers.length == 0 || sampleStreamWrapper != enabledSampleStreamWrappers[0]) { // The wrapper responsible for initializing the timestamp adjusters was reset or // changed. We need to reset the timestamp adjuster provider and all other wrappers. @@ -458,10 +465,11 @@ public void onPlaylistChanged() { } @Override - public boolean onPlaylistError(Uri url, long exclusionDurationMs) { + public boolean onPlaylistError( + Uri url, LoadErrorHandlingPolicy.LoadErrorInfo loadErrorInfo, boolean forceRetry) { boolean exclusionSucceeded = true; for (HlsSampleStreamWrapper streamWrapper : sampleStreamWrappers) { - exclusionSucceeded &= streamWrapper.onPlaylistError(url, exclusionDurationMs); + exclusionSucceeded &= streamWrapper.onPlaylistError(url, loadErrorInfo, forceRetry); } callback.onContinueLoadingRequested(this); return exclusionSucceeded; @@ -620,9 +628,13 @@ private void buildAndPrepareMainSampleStreamWrapper( numberOfAudioCodecs <= 1 && numberOfVideoCodecs <= 1 && numberOfAudioCodecs + numberOfVideoCodecs > 0; + int trackType = + !useVideoVariantsOnly && numberOfAudioCodecs > 0 + ? C.TRACK_TYPE_AUDIO + : C.TRACK_TYPE_DEFAULT; HlsSampleStreamWrapper sampleStreamWrapper = buildSampleStreamWrapper( - C.TRACK_TYPE_DEFAULT, + trackType, selectedPlaylistUrls, selectedPlaylistFormats, masterPlaylist.muxedAudioFormat, @@ -866,5 +878,4 @@ private static Format deriveAudioFormat( .setLanguage(language) .build(); } - } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java index 86383a52cef..4b225d77437 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java @@ -451,17 +451,6 @@ private HlsMediaSource( this.useSessionKeys = useSessionKeys; } - /** - * @deprecated Use {@link #getMediaItem()} and {@link MediaItem.PlaybackProperties#tag} instead. - */ - @SuppressWarnings("deprecation") - @Deprecated - @Override - @Nullable - public Object getTag() { - return playbackProperties.tag; - } - @Override public MediaItem getMediaItem() { return mediaItem; @@ -513,24 +502,25 @@ protected void releaseSourceInternal() { } @Override - public void onPrimaryPlaylistRefreshed(HlsMediaPlaylist playlist) { + public void onPrimaryPlaylistRefreshed(HlsMediaPlaylist mediaPlaylist) { long windowStartTimeMs = - playlist.hasProgramDateTime ? C.usToMs(playlist.startTimeUs) : C.TIME_UNSET; + mediaPlaylist.hasProgramDateTime ? C.usToMs(mediaPlaylist.startTimeUs) : C.TIME_UNSET; // For playlist types EVENT and VOD we know segments are never removed, so the presentation // started at the same time as the window. Otherwise, we don't know the presentation start time. long presentationStartTimeMs = - playlist.playlistType == HlsMediaPlaylist.PLAYLIST_TYPE_EVENT - || playlist.playlistType == HlsMediaPlaylist.PLAYLIST_TYPE_VOD + mediaPlaylist.playlistType == HlsMediaPlaylist.PLAYLIST_TYPE_EVENT + || mediaPlaylist.playlistType == HlsMediaPlaylist.PLAYLIST_TYPE_VOD ? windowStartTimeMs : C.TIME_UNSET; // The master playlist is non-null because the first playlist has been fetched by now. HlsManifest manifest = - new HlsManifest(checkNotNull(playlistTracker.getMasterPlaylist()), playlist); + new HlsManifest(checkNotNull(playlistTracker.getMasterPlaylist()), mediaPlaylist); SinglePeriodTimeline timeline = playlistTracker.isLive() - ? createTimelineForLive(playlist, presentationStartTimeMs, windowStartTimeMs, manifest) + ? createTimelineForLive( + mediaPlaylist, presentationStartTimeMs, windowStartTimeMs, manifest) : createTimelineForOnDemand( - playlist, presentationStartTimeMs, windowStartTimeMs, manifest); + mediaPlaylist, presentationStartTimeMs, windowStartTimeMs, manifest); refreshSourceInfo(timeline); } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStream.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStream.java index 53d9b0cd9e3..a5906078502 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStream.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStream.java @@ -22,9 +22,7 @@ import com.google.android.exoplayer2.util.Assertions; import java.io.IOException; -/** - * {@link SampleStream} for a particular sample queue in HLS. - */ +/** {@link SampleStream} for a particular sample queue in HLS. */ /* package */ final class HlsSampleStream implements SampleStream { private final int trackGroupIndex; diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java index 6e16abc5194..05f7a7f8cca 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java @@ -17,6 +17,7 @@ import static com.google.android.exoplayer2.source.hls.HlsChunkSource.CHUNK_PUBLICATION_STATE_PUBLISHED; import static com.google.android.exoplayer2.source.hls.HlsChunkSource.CHUNK_PUBLICATION_STATE_REMOVED; +import static com.google.android.exoplayer2.trackselection.TrackSelectionUtil.createFallbackOptions; import static java.lang.Math.max; import static java.lang.Math.min; @@ -85,15 +86,17 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; /** - * Loads {@link HlsMediaChunk}s obtained from a {@link HlsChunkSource}, and provides - * {@link SampleStream}s from which the loaded media can be consumed. + * Loads {@link HlsMediaChunk}s obtained from a {@link HlsChunkSource}, and provides {@link + * SampleStream}s from which the loaded media can be consumed. */ -/* package */ final class HlsSampleStreamWrapper implements Loader.Callback, - Loader.ReleaseCallback, SequenceableLoader, ExtractorOutput, UpstreamFormatChangedListener { - - /** - * A callback to be notified of events. - */ +/* package */ final class HlsSampleStreamWrapper + implements Loader.Callback, + Loader.ReleaseCallback, + SequenceableLoader, + ExtractorOutput, + UpstreamFormatChangedListener { + + /** A callback to be notified of events. */ public interface Callback extends SequenceableLoader.Callback { /** @@ -235,10 +238,10 @@ public HlsSampleStreamWrapper( readOnlyMediaChunks = Collections.unmodifiableList(mediaChunks); hlsSampleStreams = new ArrayList<>(); // Suppressions are needed because `this` is not initialized here. - @SuppressWarnings("nullness:methodref.receiver.bound.invalid") + @SuppressWarnings("nullness:methodref.receiver.bound") Runnable maybeFinishPrepareRunnable = this::maybeFinishPrepare; this.maybeFinishPrepareRunnable = maybeFinishPrepareRunnable; - @SuppressWarnings("nullness:methodref.receiver.bound.invalid") + @SuppressWarnings("nullness:methodref.receiver.bound") Runnable onTracksEndedRunnable = this::onTracksEnded; this.onTracksEndedRunnable = onTracksEndedRunnable; handler = Util.createHandlerForCurrentLooper(); @@ -276,7 +279,8 @@ public void prepareWithMasterPlaylistInfo( public void maybeThrowPrepareError() throws IOException { maybeThrowError(); if (loadingFinished && !prepared) { - throw new ParserException("Loading finished before preparation is complete."); + throw ParserException.createForMalformedContainer( + "Loading finished before preparation is complete.", /* cause= */ null); } } @@ -551,7 +555,22 @@ public void setIsTimestampMaster(boolean isTimestampMaster) { chunkSource.setIsTimestampMaster(isTimestampMaster); } - public boolean onPlaylistError(Uri playlistUrl, long exclusionDurationMs) { + public boolean onPlaylistError(Uri playlistUrl, LoadErrorInfo loadErrorInfo, boolean forceRetry) { + if (!chunkSource.obtainsChunksForPlaylist(playlistUrl)) { + // Return early if the chunk source doesn't deliver chunks for the failing playlist. + return true; + } + long exclusionDurationMs = C.TIME_UNSET; + if (!forceRetry) { + @Nullable + LoadErrorHandlingPolicy.FallbackSelection fallbackSelection = + loadErrorHandlingPolicy.getFallbackSelectionFor( + createFallbackOptions(chunkSource.getTrackSelection()), loadErrorInfo); + if (fallbackSelection != null + && fallbackSelection.type == LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK) { + exclusionDurationMs = fallbackSelection.exclusionDurationMs; + } + } return chunkSource.onPlaylistError(playlistUrl, exclusionDurationMs); } @@ -659,8 +678,10 @@ public long getBufferedPositionUs() { } else { long bufferedPositionUs = lastSeekPositionUs; HlsMediaChunk lastMediaChunk = getLastMediaChunk(); - HlsMediaChunk lastCompletedMediaChunk = lastMediaChunk.isLoadCompleted() ? lastMediaChunk - : mediaChunks.size() > 1 ? mediaChunks.get(mediaChunks.size() - 2) : null; + HlsMediaChunk lastCompletedMediaChunk = + lastMediaChunk.isLoadCompleted() + ? lastMediaChunk + : mediaChunks.size() > 1 ? mediaChunks.get(mediaChunks.size() - 2) : null; if (lastCompletedMediaChunk != null) { bufferedPositionUs = max(bufferedPositionUs, lastCompletedMediaChunk.endTimeUs); } @@ -889,9 +910,14 @@ public LoadErrorAction onLoadError( LoadErrorInfo loadErrorInfo = new LoadErrorInfo(loadEventInfo, mediaLoadData, error, errorCount); LoadErrorAction loadErrorAction; - long exclusionDurationMs = loadErrorHandlingPolicy.getBlacklistDurationMsFor(loadErrorInfo); - if (exclusionDurationMs != C.TIME_UNSET) { - exclusionSucceeded = chunkSource.maybeExcludeTrack(loadable, exclusionDurationMs); + @Nullable + LoadErrorHandlingPolicy.FallbackSelection fallbackSelection = + loadErrorHandlingPolicy.getFallbackSelectionFor( + createFallbackOptions(chunkSource.getTrackSelection()), loadErrorInfo); + if (fallbackSelection != null + && fallbackSelection.type == LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK) { + exclusionSucceeded = + chunkSource.maybeExcludeTrack(loadable, fallbackSelection.exclusionDurationMs); } if (exclusionSucceeded) { @@ -1755,10 +1781,9 @@ public int sampleData( } @Override - public void sampleData( - ParsableByteArray buffer, int length, @SampleDataPart int sampleDataPart) { + public void sampleData(ParsableByteArray data, int length, @SampleDataPart int sampleDataPart) { ensureBufferCapacity(bufferPosition + length); - buffer.readBytes(this.buffer, bufferPosition, length); + data.readBytes(this.buffer, bufferPosition, length); bufferPosition += length; } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/TimestampAdjusterProvider.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/TimestampAdjusterProvider.java index 83d4c319245..54de6425e6f 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/TimestampAdjusterProvider.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/TimestampAdjusterProvider.java @@ -15,7 +15,10 @@ */ package com.google.android.exoplayer2.source.hls; +import static com.google.android.exoplayer2.util.TimestampAdjuster.MODE_SHARED; + import android.util.SparseArray; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.TimestampAdjuster; /** Provides {@link TimestampAdjuster} instances for use during HLS playbacks. */ @@ -30,26 +33,23 @@ public TimestampAdjusterProvider() { } /** - * Returns a {@link TimestampAdjuster} suitable for adjusting the pts timestamps contained in - * a chunk with a given discontinuity sequence. + * Returns a {@link TimestampAdjuster} suitable for adjusting the pts timestamps contained in a + * chunk with a given discontinuity sequence. * * @param discontinuitySequence The chunk's discontinuity sequence. * @return A {@link TimestampAdjuster}. */ public TimestampAdjuster getAdjuster(int discontinuitySequence) { - TimestampAdjuster adjuster = timestampAdjusters.get(discontinuitySequence); + @Nullable TimestampAdjuster adjuster = timestampAdjusters.get(discontinuitySequence); if (adjuster == null) { - adjuster = new TimestampAdjuster(TimestampAdjuster.DO_NOT_OFFSET); + adjuster = new TimestampAdjuster(MODE_SHARED); timestampAdjusters.put(discontinuitySequence, adjuster); } return adjuster; } - /** - * Resets the provider. - */ + /** Resets the provider. */ public void reset() { timestampAdjusters.clear(); } - } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/WebvttExtractor.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/WebvttExtractor.java index 832de00cf93..7a5771e208e 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/WebvttExtractor.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/WebvttExtractor.java @@ -115,8 +115,10 @@ public int read(ExtractorInput input, PositionHolder seekPosition) throws IOExce // Increase the size of sampleData if necessary. if (sampleSize == sampleData.length) { - sampleData = Arrays.copyOf(sampleData, - (currentFileSize != C.LENGTH_UNSET ? currentFileSize : sampleData.length) * 3 / 2); + sampleData = + Arrays.copyOf( + sampleData, + (currentFileSize != C.LENGTH_UNSET ? currentFileSize : sampleData.length) * 3 / 2); } // Consume to the input. @@ -151,11 +153,13 @@ private void processSample() throws ParserException { if (line.startsWith("X-TIMESTAMP-MAP")) { Matcher localTimestampMatcher = LOCAL_TIMESTAMP.matcher(line); if (!localTimestampMatcher.find()) { - throw new ParserException("X-TIMESTAMP-MAP doesn't contain local timestamp: " + line); + throw ParserException.createForMalformedContainer( + "X-TIMESTAMP-MAP doesn't contain local timestamp: " + line, /* cause= */ null); } Matcher mediaTimestampMatcher = MEDIA_TIMESTAMP.matcher(line); if (!mediaTimestampMatcher.find()) { - throw new ParserException("X-TIMESTAMP-MAP doesn't contain media timestamp: " + line); + throw ParserException.createForMalformedContainer( + "X-TIMESTAMP-MAP doesn't contain media timestamp: " + line, /* cause= */ null); } vttTimestampUs = WebvttParserUtil.parseTimestampUs( @@ -200,5 +204,4 @@ private TrackOutput buildTrackOutput(long subsampleOffsetUs) { output.endTracks(); return trackOutput; } - } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/offline/HlsDownloader.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/offline/HlsDownloader.java index 39462f3d061..e68ffcc7c91 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/offline/HlsDownloader.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/offline/HlsDownloader.java @@ -19,7 +19,6 @@ import androidx.annotation.Nullable; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.offline.SegmentDownloader; -import com.google.android.exoplayer2.offline.StreamKey; import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist; import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist; import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylist; @@ -65,14 +64,6 @@ */ public final class HlsDownloader extends SegmentDownloader { - /** @deprecated Use {@link #HlsDownloader(MediaItem, CacheDataSource.Factory)} instead. */ - @SuppressWarnings("deprecation") - @Deprecated - public HlsDownloader( - Uri playlistUri, List streamKeys, CacheDataSource.Factory cacheDataSourceFactory) { - this(playlistUri, streamKeys, cacheDataSourceFactory, Runnable::run); - } - /** * Creates a new instance. * @@ -84,21 +75,6 @@ public HlsDownloader(MediaItem mediaItem, CacheDataSource.Factory cacheDataSourc this(mediaItem, cacheDataSourceFactory, Runnable::run); } - /** - * @deprecated Use {@link #HlsDownloader(MediaItem, CacheDataSource.Factory, Executor)} instead. - */ - @Deprecated - public HlsDownloader( - Uri playlistUri, - List streamKeys, - CacheDataSource.Factory cacheDataSourceFactory, - Executor executor) { - this( - new MediaItem.Builder().setUri(playlistUri).setStreamKeys(streamKeys).build(), - cacheDataSourceFactory, - executor); - } - /** * Creates a new instance. * diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/DefaultHlsPlaylistTracker.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/DefaultHlsPlaylistTracker.java index 9ad1cb59349..05581051006 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/DefaultHlsPlaylistTracker.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/DefaultHlsPlaylistTracker.java @@ -44,9 +44,9 @@ import com.google.android.exoplayer2.util.Util; import com.google.common.collect.Iterables; import java.io.IOException; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; /** Default implementation for {@link HlsPlaylistTracker}. */ public final class DefaultHlsPlaylistTracker @@ -65,7 +65,7 @@ public final class DefaultHlsPlaylistTracker private final HlsPlaylistParserFactory playlistParserFactory; private final LoadErrorHandlingPolicy loadErrorHandlingPolicy; private final HashMap playlistBundles; - private final List listeners; + private final CopyOnWriteArrayList listeners; private final double playlistStuckTargetDurationCoefficient; @Nullable private EventDispatcher eventDispatcher; @@ -116,7 +116,7 @@ public DefaultHlsPlaylistTracker( this.playlistParserFactory = playlistParserFactory; this.loadErrorHandlingPolicy = loadErrorHandlingPolicy; this.playlistStuckTargetDurationCoefficient = playlistStuckTargetDurationCoefficient; - listeners = new ArrayList<>(); + listeners = new CopyOnWriteArrayList<>(); playlistBundles = new HashMap<>(); initialStartTimeUs = C.TIME_UNSET; } @@ -228,6 +228,15 @@ public boolean isLive() { return isLive; } + @Override + public boolean excludeMediaPlaylist(Uri playlistUrl, long exclusionDurationMs) { + @Nullable MediaPlaylistBundle bundle = playlistBundles.get(playlistUrl); + if (bundle != null) { + return !bundle.excludePlaylist(exclusionDurationMs); + } + return false; + } + // Loader.Callback implementation. @Override @@ -243,6 +252,8 @@ public void onLoadCompleted( } this.masterPlaylist = masterPlaylist; primaryMediaPlaylistUrl = masterPlaylist.variants.get(0).url; + // Add a temporary playlist listener for loading the first primary playlist. + listeners.add(new FirstPrimaryMediaPlaylistListener()); createBundles(masterPlaylist.mediaPlaylistUrls); LoadEventInfo loadEventInfo = new LoadEventInfo( @@ -407,17 +418,16 @@ private void onPlaylistUpdated(Uri url, HlsMediaPlaylist newSnapshot) { primaryMediaPlaylistSnapshot = newSnapshot; primaryPlaylistListener.onPrimaryPlaylistRefreshed(newSnapshot); } - int listenersSize = listeners.size(); - for (int i = 0; i < listenersSize; i++) { - listeners.get(i).onPlaylistChanged(); + for (PlaylistEventListener listener : listeners) { + listener.onPlaylistChanged(); } } - private boolean notifyPlaylistError(Uri playlistUrl, long exclusionDurationMs) { - int listenersSize = listeners.size(); + private boolean notifyPlaylistError( + Uri playlistUrl, LoadErrorInfo loadErrorInfo, boolean forceRetry) { boolean anyExclusionFailed = false; - for (int i = 0; i < listenersSize; i++) { - anyExclusionFailed |= !listeners.get(i).onPlaylistError(playlistUrl, exclusionDurationMs); + for (PlaylistEventListener listener : listeners) { + anyExclusionFailed |= !listener.onPlaylistError(playlistUrl, loadErrorInfo, forceRetry); } return anyExclusionFailed; } @@ -567,7 +577,9 @@ public void onLoadCompleted( processLoadedPlaylist((HlsMediaPlaylist) result, loadEventInfo); eventDispatcher.loadCompleted(loadEventInfo, C.DATA_TYPE_MANIFEST); } else { - playlistError = new ParserException("Loaded playlist has unexpected type."); + playlistError = + ParserException.createForMalformedManifest( + "Loaded playlist has unexpected type.", /* cause= */ null); eventDispatcher.loadError( loadEventInfo, C.DATA_TYPE_MANIFEST, playlistError, /* wasCanceled= */ true); } @@ -630,16 +642,9 @@ public LoadErrorAction onLoadError( MediaLoadData mediaLoadData = new MediaLoadData(loadable.type); LoadErrorInfo loadErrorInfo = new LoadErrorInfo(loadEventInfo, mediaLoadData, error, errorCount); - LoadErrorAction loadErrorAction; - long exclusionDurationMs = loadErrorHandlingPolicy.getBlacklistDurationMsFor(loadErrorInfo); - boolean shouldExclude = exclusionDurationMs != C.TIME_UNSET; - boolean exclusionFailed = - notifyPlaylistError(playlistUrl, exclusionDurationMs) || !shouldExclude; - if (shouldExclude) { - exclusionFailed |= excludePlaylist(exclusionDurationMs); - } - + notifyPlaylistError(playlistUrl, loadErrorInfo, /* forceRetry= */ false); + LoadErrorAction loadErrorAction; if (exclusionFailed) { long retryDelay = loadErrorHandlingPolicy.getRetryDelayMsFor(loadErrorInfo); loadErrorAction = @@ -692,7 +697,7 @@ private void loadPlaylistImmediately(Uri playlistRequestUri) { long elapsedRealtime = mediaPlaylistLoader.startLoading( mediaPlaylistLoadable, - this, + /* callback= */ this, loadErrorHandlingPolicy.getMinimumLoadableRetryCount(mediaPlaylistLoadable.type)); eventDispatcher.loadStarted( new LoadEventInfo( @@ -711,30 +716,31 @@ private void processLoadedPlaylist( lastSnapshotChangeMs = currentTimeMs; onPlaylistUpdated(playlistUrl, playlistSnapshot); } else if (!playlistSnapshot.hasEndTag) { + boolean forceRetry = false; + @Nullable IOException playlistError = null; if (loadedPlaylist.mediaSequence + loadedPlaylist.segments.size() < playlistSnapshot.mediaSequence) { // TODO: Allow customization of playlist resets handling. // The media sequence jumped backwards. The server has probably reset. We do not try // excluding in this case. + forceRetry = true; playlistError = new PlaylistResetException(playlistUrl); - notifyPlaylistError(playlistUrl, C.TIME_UNSET); } else if (currentTimeMs - lastSnapshotChangeMs > C.usToMs(playlistSnapshot.targetDurationUs) * playlistStuckTargetDurationCoefficient) { // TODO: Allow customization of stuck playlists handling. playlistError = new PlaylistStuckException(playlistUrl); - LoadErrorInfo loadErrorInfo = + } + if (playlistError != null) { + this.playlistError = playlistError; + notifyPlaylistError( + playlistUrl, new LoadErrorInfo( loadEventInfo, new MediaLoadData(C.DATA_TYPE_MANIFEST), playlistError, - /* errorCount= */ 1); - long exclusionDurationMs = - loadErrorHandlingPolicy.getBlacklistDurationMsFor(loadErrorInfo); - notifyPlaylistError(playlistUrl, exclusionDurationMs); - if (exclusionDurationMs != C.TIME_UNSET) { - excludePlaylist(exclusionDurationMs); - } + /* errorCount= */ 1), + forceRetry); } } long durationUntilNextLoadUs = 0L; @@ -798,4 +804,51 @@ private boolean excludePlaylist(long exclusionDurationMs) { return playlistUrl.equals(primaryMediaPlaylistUrl) && !maybeSelectNewPrimaryUrl(); } } + + /** + * Takes care of handling load errors of the first media playlist and applies exclusion according + * to the {@link LoadErrorHandlingPolicy} before the first media period has been created and + * prepared. + */ + private class FirstPrimaryMediaPlaylistListener implements PlaylistEventListener { + + @Override + public void onPlaylistChanged() { + // Remove the temporary playlist listener that is waiting for the first playlist only. + listeners.remove(this); + } + + @Override + public boolean onPlaylistError(Uri url, LoadErrorInfo loadErrorInfo, boolean forceRetry) { + if (primaryMediaPlaylistSnapshot == null) { + long nowMs = SystemClock.elapsedRealtime(); + int variantExclusionCounter = 0; + List variants = castNonNull(masterPlaylist).variants; + for (int i = 0; i < variants.size(); i++) { + @Nullable + MediaPlaylistBundle mediaPlaylistBundle = playlistBundles.get(variants.get(i).url); + if (mediaPlaylistBundle != null && nowMs < mediaPlaylistBundle.excludeUntilMs) { + variantExclusionCounter++; + } + } + LoadErrorHandlingPolicy.FallbackOptions fallbackOptions = + new LoadErrorHandlingPolicy.FallbackOptions( + /* numberOfLocations= */ 1, + /* numberOfExcludedLocations= */ 0, + /* numberOfTracks= */ masterPlaylist.variants.size(), + /* numberOfExcludedTracks= */ variantExclusionCounter); + @Nullable + LoadErrorHandlingPolicy.FallbackSelection fallbackSelection = + loadErrorHandlingPolicy.getFallbackSelectionFor(fallbackOptions, loadErrorInfo); + if (fallbackSelection != null + && fallbackSelection.type == LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK) { + @Nullable MediaPlaylistBundle mediaPlaylistBundle = playlistBundles.get(url); + if (mediaPlaylistBundle != null) { + mediaPlaylistBundle.excludePlaylist(fallbackSelection.exclusionDurationMs); + } + } + } + return false; + } + } } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMasterPlaylist.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMasterPlaylist.java index 72f6a361d70..2db9425a846 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMasterPlaylist.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMasterPlaylist.java @@ -145,7 +145,6 @@ public Rendition(@Nullable Uri url, Format format, String groupId, String name) this.groupId = groupId; this.name = name; } - } /** All of the media playlist URLs referenced by the playlist. */ @@ -214,8 +213,8 @@ public HlsMasterPlaylist( this.subtitles = Collections.unmodifiableList(subtitles); this.closedCaptions = Collections.unmodifiableList(closedCaptions); this.muxedAudioFormat = muxedAudioFormat; - this.muxedCaptionFormats = muxedCaptionFormats != null - ? Collections.unmodifiableList(muxedCaptionFormats) : null; + this.muxedCaptionFormats = + muxedCaptionFormats != null ? Collections.unmodifiableList(muxedCaptionFormats) : null; this.variableDefinitions = Collections.unmodifiableMap(variableDefinitions); this.sessionKeyDrmInitData = Collections.unmodifiableList(sessionKeyDrmInitData); } @@ -317,5 +316,4 @@ private static List copyStreams( } return copiedStreams; } - } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylist.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylist.java index 4149b5476a7..c0f867dc762 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylist.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylist.java @@ -344,7 +344,8 @@ private SegmentBase( @Override public int compareTo(Long relativeStartTimeUs) { return this.relativeStartTimeUs > relativeStartTimeUs - ? 1 : (this.relativeStartTimeUs < relativeStartTimeUs ? -1 : 0); + ? 1 + : (this.relativeStartTimeUs < relativeStartTimeUs ? -1 : 0); } } @@ -391,9 +392,7 @@ public RenditionReport(Uri playlistUri, long lastMediaSequence, int lastPartInde public static final int PLAYLIST_TYPE_VOD = 1; public static final int PLAYLIST_TYPE_EVENT = 2; - /** - * The type of the playlist. See {@link PlaylistType}. - */ + /** The type of the playlist. See {@link PlaylistType}. */ @PlaylistType public final int playlistType; /** * The start offset in microseconds from the beginning of the playlist, as defined by @@ -414,9 +413,7 @@ public RenditionReport(Uri playlistUri, long lastMediaSequence, int lastPartInde * playlist. */ public final long startTimeUs; - /** - * Whether the playlist contains the #EXT-X-DISCONTINUITY-SEQUENCE tag. - */ + /** Whether the playlist contains the #EXT-X-DISCONTINUITY-SEQUENCE tag. */ public final boolean hasDiscontinuitySequence; /** * The discontinuity sequence number of the first media segment in the playlist, as defined by @@ -428,13 +425,9 @@ public RenditionReport(Uri playlistUri, long lastMediaSequence, int lastPartInde * #EXT-X-MEDIA-SEQUENCE. */ public final long mediaSequence; - /** - * The compatibility version, as defined by #EXT-X-VERSION. - */ + /** The compatibility version, as defined by #EXT-X-VERSION. */ public final int version; - /** - * The target duration in microseconds, as defined by #EXT-X-TARGETDURATION. - */ + /** The target duration in microseconds, as defined by #EXT-X-TARGETDURATION. */ public final long targetDurationUs; /** * The target duration for segment parts, as defined by #EXT-X-PART-INF, or {@link C#TIME_UNSET} @@ -443,18 +436,14 @@ public RenditionReport(Uri playlistUri, long lastMediaSequence, int lastPartInde public final long partTargetDurationUs; /** Whether the playlist contains the #EXT-X-ENDLIST tag. */ public final boolean hasEndTag; - /** - * Whether the playlist contains a #EXT-X-PROGRAM-DATE-TIME tag. - */ + /** Whether the playlist contains a #EXT-X-PROGRAM-DATE-TIME tag. */ public final boolean hasProgramDateTime; /** * Contains the CDM protection schemes used by segments in this playlist. Does not contain any key * acquisition data. Null if none of the segments in the playlist is CDM-encrypted. */ @Nullable public final DrmInitData protectionSchemes; - /** - * The list of segments in the playlist. - */ + /** The list of segments in the playlist. */ public final List segments; /** * The list of parts at the end of the playlist for which the segment is not in the playlist yet. @@ -575,9 +564,7 @@ public boolean isNewerThan(@Nullable HlsMediaPlaylist other) { || (partCount == otherPartCount && hasEndTag && !other.hasEndTag); } - /** - * Returns the result of adding the duration of the playlist to its start time. - */ + /** Returns the result of adding the duration of the playlist to its start time. */ public long getEndTimeUs() { return startTimeUs + durationUs; } @@ -645,5 +632,4 @@ public HlsMediaPlaylist copyWithEndTag() { serverControl, renditionReports); } - } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylist.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylist.java index 9cec1cd33b9..17d31d4ceba 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylist.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylist.java @@ -22,13 +22,9 @@ /** Represents an HLS playlist. */ public abstract class HlsPlaylist implements FilterableManifest { - /** - * The base uri. Used to resolve relative paths. - */ + /** The base uri. Used to resolve relative paths. */ public final String baseUri; - /** - * The list of tags in the playlist. - */ + /** The list of tags in the playlist. */ public final List tags; /** * Whether the media is formed of independent segments, as defined by the @@ -46,5 +42,4 @@ protected HlsPlaylist(String baseUri, List tags, boolean hasIndependentS this.tags = Collections.unmodifiableList(tags); this.hasIndependentSegments = hasIndependentSegments; } - } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java index d781357480d..ce44211b31e 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java @@ -31,7 +31,6 @@ import com.google.android.exoplayer2.drm.DrmInitData.SchemeData; import com.google.android.exoplayer2.extractor.mp4.PsshAtomUtil; import com.google.android.exoplayer2.metadata.Metadata; -import com.google.android.exoplayer2.source.UnrecognizedInputFormatException; import com.google.android.exoplayer2.source.hls.HlsTrackMetadataEntry; import com.google.android.exoplayer2.source.hls.HlsTrackMetadataEntry.VariantInfo; import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.Rendition; @@ -140,14 +139,14 @@ public static final class DeltaUpdateException extends IOException {} private static final Pattern REGEX_CODECS = Pattern.compile("CODECS=\"(.+?)\""); private static final Pattern REGEX_RESOLUTION = Pattern.compile("RESOLUTION=(\\d+x\\d+)"); private static final Pattern REGEX_FRAME_RATE = Pattern.compile("FRAME-RATE=([\\d\\.]+)\\b"); - private static final Pattern REGEX_TARGET_DURATION = Pattern.compile(TAG_TARGET_DURATION - + ":(\\d+)\\b"); + private static final Pattern REGEX_TARGET_DURATION = + Pattern.compile(TAG_TARGET_DURATION + ":(\\d+)\\b"); private static final Pattern REGEX_ATTR_DURATION = Pattern.compile("DURATION=([\\d\\.]+)\\b"); private static final Pattern REGEX_PART_TARGET_DURATION = Pattern.compile("PART-TARGET=([\\d\\.]+)\\b"); private static final Pattern REGEX_VERSION = Pattern.compile(TAG_VERSION + ":(\\d+)\\b"); - private static final Pattern REGEX_PLAYLIST_TYPE = Pattern.compile(TAG_PLAYLIST_TYPE - + ":(.+)\\b"); + private static final Pattern REGEX_PLAYLIST_TYPE = + Pattern.compile(TAG_PLAYLIST_TYPE + ":(.+)\\b"); private static final Pattern REGEX_CAN_SKIP_UNTIL = Pattern.compile("CAN-SKIP-UNTIL=([\\d\\.]+)\\b"); private static final Pattern REGEX_CAN_SKIP_DATE_RANGES = @@ -159,17 +158,17 @@ public static final class DeltaUpdateException extends IOException {} Pattern.compile("PART-HOLD-BACK=([\\d\\.]+)\\b"); private static final Pattern REGEX_CAN_BLOCK_RELOAD = compileBooleanAttrPattern("CAN-BLOCK-RELOAD"); - private static final Pattern REGEX_MEDIA_SEQUENCE = Pattern.compile(TAG_MEDIA_SEQUENCE - + ":(\\d+)\\b"); - private static final Pattern REGEX_MEDIA_DURATION = Pattern.compile(TAG_MEDIA_DURATION - + ":([\\d\\.]+)\\b"); + private static final Pattern REGEX_MEDIA_SEQUENCE = + Pattern.compile(TAG_MEDIA_SEQUENCE + ":(\\d+)\\b"); + private static final Pattern REGEX_MEDIA_DURATION = + Pattern.compile(TAG_MEDIA_DURATION + ":([\\d\\.]+)\\b"); private static final Pattern REGEX_MEDIA_TITLE = Pattern.compile(TAG_MEDIA_DURATION + ":[\\d\\.]+\\b,(.+)"); private static final Pattern REGEX_LAST_MSN = Pattern.compile("LAST-MSN" + "=(\\d+)\\b"); private static final Pattern REGEX_LAST_PART = Pattern.compile("LAST-PART" + "=(\\d+)\\b"); private static final Pattern REGEX_TIME_OFFSET = Pattern.compile("TIME-OFFSET=(-?[\\d\\.]+)\\b"); - private static final Pattern REGEX_BYTERANGE = Pattern.compile(TAG_BYTERANGE - + ":(\\d+(?:@\\d+)?)\\b"); + private static final Pattern REGEX_BYTERANGE = + Pattern.compile(TAG_BYTERANGE + ":(\\d+(?:@\\d+)?)\\b"); private static final Pattern REGEX_ATTR_BYTERANGE = Pattern.compile("BYTERANGE=\"(\\d+(?:@\\d+)?)\\b\""); private static final Pattern REGEX_BYTERANGE_START = Pattern.compile("BYTERANGE-START=(\\d+)\\b"); @@ -194,8 +193,17 @@ public static final class DeltaUpdateException extends IOException {} Pattern.compile("KEYFORMATVERSIONS=\"(.+?)\""); private static final Pattern REGEX_URI = Pattern.compile("URI=\"(.+?)\""); private static final Pattern REGEX_IV = Pattern.compile("IV=([^,.*]+)"); - private static final Pattern REGEX_TYPE = Pattern.compile("TYPE=(" + TYPE_AUDIO + "|" + TYPE_VIDEO - + "|" + TYPE_SUBTITLES + "|" + TYPE_CLOSED_CAPTIONS + ")"); + private static final Pattern REGEX_TYPE = + Pattern.compile( + "TYPE=(" + + TYPE_AUDIO + + "|" + + TYPE_VIDEO + + "|" + + TYPE_SUBTITLES + + "|" + + TYPE_CLOSED_CAPTIONS + + ")"); private static final Pattern REGEX_PRELOAD_HINT_TYPE = Pattern.compile("TYPE=(" + TYPE_PART + "|" + TYPE_MAP + ")"); private static final Pattern REGEX_LANGUAGE = Pattern.compile("LANGUAGE=\"(.+?)\""); @@ -247,8 +255,8 @@ public HlsPlaylist parse(Uri uri, InputStream inputStream) throws IOException { String line; try { if (!checkPlaylistHeader(reader)) { - throw new UnrecognizedInputFormatException("Input does not start with the #EXTM3U header.", - uri); + throw ParserException.createForMalformedManifest( + /* message= */ "Input does not start with the #EXTM3U header.", /* cause= */ null); } while ((line = reader.readLine()) != null) { line = line.trim(); @@ -278,7 +286,8 @@ public HlsPlaylist parse(Uri uri, InputStream inputStream) throws IOException { } finally { Util.closeQuietly(reader); } - throw new ParserException("Failed to parse the playlist, could not identify any tags."); + throw ParserException.createForMalformedManifest( + "Failed to parse the playlist, could not identify any tags.", /* cause= */ null); } private static boolean checkPlaylistHeader(BufferedReader reader) throws IOException { @@ -396,7 +405,8 @@ private static HlsMasterPlaylist parseMasterPlaylist(LineIterator iterator, Stri uri = UriUtil.resolveToUri(baseUri, parseStringAttr(line, REGEX_URI, variableDefinitions)); } else if (!iterator.hasNext()) { - throw new ParserException("#EXT-X-STREAM-INF must be followed by another line"); + throw ParserException.createForMalformedManifest( + "#EXT-X-STREAM-INF must be followed by another line", /* cause= */ null); } else { // The following line contains #EXT-X-STREAM-INF's URI. line = replaceVariableReferences(iterator.next(), variableDefinitions); @@ -508,7 +518,7 @@ private static HlsMasterPlaylist parseMasterPlaylist(LineIterator iterator, Stri formatBuilder.setChannelCount(channelCount); if (MimeTypes.AUDIO_E_AC3.equals(sampleMimeType) && channelsString.endsWith("/JOC")) { sampleMimeType = MimeTypes.AUDIO_E_AC3_JOC; - formatBuilder.setCodecs(Ac3Util.E_AC_3_CODEC_STRING); + formatBuilder.setCodecs(Ac3Util.E_AC3_JOC_CODEC_STRING); } } formatBuilder.setSampleMimeType(sampleMimeType); @@ -712,9 +722,10 @@ private static HlsMediaPlaylist parseMediaPlaylist( } if (fullSegmentEncryptionKeyUri != null && fullSegmentEncryptionIV == null) { // See RFC 8216, Section 4.3.2.5. - throw new ParserException( - "The encryption IV attribute must be present when an initialization segment is " - + "encrypted with METHOD=AES-128."); + throw ParserException.createForMalformedManifest( + "The encryption IV attribute must be present when an initialization segment is" + + " encrypted with METHOD=AES-128.", + /* cause= */ null); } initializationSegment = new Segment( @@ -1191,7 +1202,8 @@ private static String parseStringAttr( if (value != null) { return value; } else { - throw new ParserException("Couldn't match " + pattern.pattern() + " in " + line); + throw ParserException.createForMalformedManifest( + "Couldn't match " + pattern.pattern() + " in " + line, /* cause= */ null); } } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistTracker.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistTracker.java index 0590361cc0e..8396c9c4099 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistTracker.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistTracker.java @@ -67,20 +67,19 @@ interface PrimaryPlaylistListener { /** Called on playlist loading events. */ interface PlaylistEventListener { - /** - * Called a playlist changes. - */ + /** Called a playlist changes. */ void onPlaylistChanged(); /** * Called if an error is encountered while loading a playlist. * * @param url The loaded url that caused the error. - * @param exclusionDurationMs The duration for which the playlist should be excluded. Or {@link - * C#TIME_UNSET} if the playlist should not be excluded. + * @param loadErrorInfo The load error info. + * @param forceRetry Whether retry should be forced without considering exclusion. * @return True if excluding did not encounter errors. False otherwise. */ - boolean onPlaylistError(Uri url, long exclusionDurationMs); + boolean onPlaylistError( + Uri url, LoadErrorHandlingPolicy.LoadErrorInfo loadErrorInfo, boolean forceRetry); } /** Thrown when a playlist is considered to be stuck due to a server side error. */ @@ -124,10 +123,12 @@ public PlaylistResetException(Uri url) { * @param initialPlaylistUri Uri of the HLS stream. Can point to a media playlist or a master * playlist. * @param eventDispatcher A dispatcher to notify of events. - * @param listener A callback for the primary playlist change events. + * @param primaryPlaylistListener A callback for the primary playlist change events. */ void start( - Uri initialPlaylistUri, EventDispatcher eventDispatcher, PrimaryPlaylistListener listener); + Uri initialPlaylistUri, + EventDispatcher eventDispatcher, + PrimaryPlaylistListener primaryPlaylistListener); /** * Stops the playlist tracker and releases any acquired resources. @@ -207,6 +208,15 @@ void start( */ void maybeThrowPlaylistRefreshError(Uri url) throws IOException; + /** + * Excludes the given media playlist for the given duration, in milliseconds. + * + * @param playlistUrl The URL of the media playlist. + * @param exclusionDurationMs The duration for which to exclude the playlist. + * @return Whether exclusion was successful. + */ + boolean excludeMediaPlaylist(Uri playlistUrl, long exclusionDurationMs); + /** * Requests a playlist refresh and removes it from the exclusion list. * diff --git a/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/Aes128DataSourceTest.java b/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/Aes128DataSourceTest.java index 3eef5c36d24..6630072eabf 100644 --- a/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/Aes128DataSourceTest.java +++ b/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/Aes128DataSourceTest.java @@ -109,7 +109,7 @@ public long open(DataSpec dataSpec) throws IOException { } @Override - public int read(byte[] buffer, int offset, int readLength) { + public int read(byte[] buffer, int offset, int length) { return C.RESULT_END_OF_INPUT; } diff --git a/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/HlsMediaSourceTest.java b/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/HlsMediaSourceTest.java index eefac102223..635c5615e14 100644 --- a/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/HlsMediaSourceTest.java +++ b/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/HlsMediaSourceTest.java @@ -21,7 +21,6 @@ import android.net.Uri; import android.os.SystemClock; -import androidx.annotation.Nullable; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.MediaItem; @@ -83,35 +82,6 @@ public void factorySetTag_nonNullMediaItemTag_doesNotOverrideMediaItemTag() { assertThat(hlsMediaItem.playbackProperties.tag).isEqualTo(mediaItemTag); } - // Tests backwards compatibility - @SuppressWarnings("deprecation") - @Test - public void factorySetTag_setsDeprecatedMediaSourceTag() { - Object tag = new Object(); - MediaItem mediaItem = MediaItem.fromUri("http://www.google.com"); - HlsMediaSource.Factory factory = - new HlsMediaSource.Factory(mock(DataSource.Factory.class)).setTag(tag); - - @Nullable Object mediaSourceTag = factory.createMediaSource(mediaItem).getTag(); - - assertThat(mediaSourceTag).isEqualTo(tag); - } - - // Tests backwards compatibility - @SuppressWarnings("deprecation") - @Test - public void factoryCreateMediaSource_setsDeprecatedMediaSourceTag() { - Object tag = new Object(); - MediaItem mediaItem = - new MediaItem.Builder().setUri("http://www.google.com").setTag(tag).build(); - HlsMediaSource.Factory factory = - new HlsMediaSource.Factory(mock(DataSource.Factory.class)).setTag(new Object()); - - @Nullable Object mediaSourceTag = factory.createMediaSource(mediaItem).getTag(); - - assertThat(mediaSourceTag).isEqualTo(tag); - } - // Tests backwards compatibility @SuppressWarnings("deprecation") @Test diff --git a/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/offline/HlsDownloaderTest.java b/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/offline/HlsDownloaderTest.java index 986ee4dedae..b8ff3680bfe 100644 --- a/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/offline/HlsDownloaderTest.java +++ b/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/offline/HlsDownloaderTest.java @@ -44,7 +44,7 @@ import com.google.android.exoplayer2.offline.DownloaderFactory; import com.google.android.exoplayer2.offline.StreamKey; import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist; -import com.google.android.exoplayer2.testutil.CacheAsserts.RequestSet; +import com.google.android.exoplayer2.testutil.CacheAsserts; import com.google.android.exoplayer2.testutil.FakeDataSet; import com.google.android.exoplayer2.testutil.FakeDataSource; import com.google.android.exoplayer2.testutil.TestUtil; @@ -136,7 +136,7 @@ public void downloadRepresentation() throws Exception { assertCachedData( cache, - new RequestSet(fakeDataSet) + new CacheAsserts.RequestSet(fakeDataSet) .subset( MASTER_PLAYLIST_URI, MEDIA_PLAYLIST_1_URI, @@ -194,7 +194,7 @@ public void downloadMediaPlaylist() throws Exception { assertCachedData( cache, - new RequestSet(fakeDataSet) + new CacheAsserts.RequestSet(fakeDataSet) .subset( MEDIA_PLAYLIST_1_URI, MEDIA_PLAYLIST_1_DIR + "fileSequence0.ts", diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/MediaDescription.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/MediaDescription.java index 6bda38e8d40..0a7d87436c4 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/MediaDescription.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/MediaDescription.java @@ -232,7 +232,6 @@ public MediaDescription build() { public final int bitrate; /** The assigned media title. */ @Nullable public final String mediaTitle; - // TODO(internal b/172331505) Parse the String representations into objects. /** The connection parameters. */ @Nullable public final String connection; /** The encryption parameter. */ @@ -301,7 +300,7 @@ public int hashCode() { * {@link MediaDescription} does not contain any FMTP attribute. * *

    FMTP format reference: RFC2327 Page 27. The spaces around the FMTP attribute delimiters are - * removed. For example, + * removed. */ public ImmutableMap getFmtpParametersAsMap() { @Nullable String fmtpAttributeValue = attributes.get(ATTR_FMTP); @@ -315,7 +314,8 @@ public ImmutableMap getFmtpParametersAsMap() { // Format of the parameter: RFC3640 Section 4.4.1: // =[; =]. - String[] parameters = Util.split(fmtpComponents[1], ";\\s?"); + // Split with an explicit limit of 0 to handle an optional trailing semicolon. + String[] parameters = fmtpComponents[1].split(";\\s?", /* limit= */ 0); ImmutableMap.Builder formatParametersBuilder = new ImmutableMap.Builder<>(); for (String parameter : parameters) { // The parameter values can bear equal signs, so splitAtFirst must be used. diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtpDataLoadable.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtpDataLoadable.java index 418b9c2ce6c..8f171ef44e8 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtpDataLoadable.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtpDataLoadable.java @@ -58,7 +58,6 @@ public interface EventListener { void onTransportReady(String transport, RtpDataChannel rtpDataChannel); } - /** The track ID associated with the Loadable. */ public final int trackId; /** The {@link RtspMediaTrack} to load. */ diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtpExtractor.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtpExtractor.java index 94c5902cd3e..f8c51b33f1d 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtpExtractor.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtpExtractor.java @@ -106,15 +106,15 @@ public void preSeek() { @Override public boolean sniff(ExtractorInput input) { - // TODO(b/172331505) Build sniff support. - return false; + throw new UnsupportedOperationException( + "RTP packets are transmitted in a packet stream do not support sniffing."); } @Override public void init(ExtractorOutput output) { payloadReader.createTracks(output, trackId); output.endTracks(); - // TODO(b/172331505) replace hardcoded unseekable seekmap. + // RTP does not embed duration or seek info. output.seekMap(new SeekMap.Unseekable(C.TIME_UNSET)); this.output = output; } diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtpPacketReorderingQueue.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtpPacketReorderingQueue.java index 1f1cb795957..3e92c7ef856 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtpPacketReorderingQueue.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtpPacketReorderingQueue.java @@ -36,8 +36,10 @@ private static final int MAX_SEQUENCE_NUMBER = RtpPacket.MAX_SEQUENCE_NUMBER; + /** Queue size threshold for resetting the queue. 5000 packets equate about 7MB in buffer size. */ + private static final int QUEUE_SIZE_THRESHOLD_FOR_RESET = 5000; + // Use set to eliminate duplicating packets. - // TODO(b/172331505) Set a upper limit on packetQueue to mitigate out of memory error. @GuardedBy("this") private final TreeSet packetQueue; @@ -86,6 +88,11 @@ public synchronized void reset() { * returns {@code true}). */ public synchronized boolean offer(RtpPacket packet, long receivedTimestampMs) { + if (packetQueue.size() >= QUEUE_SIZE_THRESHOLD_FOR_RESET) { + throw new IllegalStateException( + "Queue size limit of " + QUEUE_SIZE_THRESHOLD_FOR_RESET + " reached."); + } + int packetSequenceNumber = packet.sequenceNumber; if (!started) { reset(); diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspAuthenticationInfo.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspAuthenticationInfo.java index 82d15e7a7c2..3b591aaa9ba 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspAuthenticationInfo.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspAuthenticationInfo.java @@ -95,7 +95,8 @@ public String getAuthorizationHeaderValue( case DIGEST: return getDigestAuthorizationHeaderValue(authUserInfo, uri, requestMethod); default: - throw new ParserException(new UnsupportedOperationException()); + throw ParserException.createForManifestWithUnsupportedFeature( + /* message= */ null, new UnsupportedOperationException()); } } @@ -136,7 +137,7 @@ private String getDigestAuthorizationHeaderValue( DIGEST_FORMAT_WITH_OPAQUE, authUserInfo.username, realm, nonce, uri, response, opaque); } } catch (NoSuchAlgorithmException e) { - throw new ParserException(e); + throw ParserException.createForManifestWithUnsupportedFeature(/* message= */ null, e); } } } diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspClient.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspClient.java index b2624a041c9..0c4cff64463 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspClient.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspClient.java @@ -444,7 +444,8 @@ private void handleRtspMessage(List message) { @Nullable String wwwAuthenticateHeader = response.headers.get(RtspHeaders.WWW_AUTHENTICATE); if (wwwAuthenticateHeader == null) { - throw new ParserException("Missing WWW-Authenticate header in a 401 response."); + throw ParserException.createForMalformedManifest( + "Missing WWW-Authenticate header in a 401 response.", /* cause= */ null); } rtspAuthenticationInfo = RtspMessageUtil.parseWwwAuthenticateHeader(wwwAuthenticateHeader); @@ -479,7 +480,8 @@ private void handleRtspMessage(List message) { @Nullable String sessionHeaderString = response.headers.get(RtspHeaders.SESSION); @Nullable String transportHeaderString = response.headers.get(RtspHeaders.TRANSPORT); if (sessionHeaderString == null || transportHeaderString == null) { - throw new ParserException(); + throw ParserException.createForMalformedManifest( + "Missing mandatory session or transport header", /* cause= */ null); } RtspSessionHeader sessionHeader = @@ -541,20 +543,27 @@ private void onOptionsResponseReceived(RtspOptionsResponse response) { } private void onDescribeResponseReceived(RtspDescribeResponse response) { + RtspSessionTiming sessionTiming = RtspSessionTiming.DEFAULT; @Nullable String sessionRangeAttributeString = response.sessionDescription.attributes.get(SessionDescription.ATTR_RANGE); + if (sessionRangeAttributeString != null) { + try { + sessionTiming = RtspSessionTiming.parseTiming(sessionRangeAttributeString); + } catch (ParserException e) { + sessionInfoListener.onSessionTimelineRequestFailed("SDP format error.", /* cause= */ e); + return; + } + } - try { - sessionInfoListener.onSessionTimelineUpdated( - sessionRangeAttributeString != null - ? RtspSessionTiming.parseTiming(sessionRangeAttributeString) - : RtspSessionTiming.DEFAULT, - buildTrackList(response.sessionDescription, uri)); - hasUpdatedTimelineAndTracks = true; - } catch (ParserException e) { - sessionInfoListener.onSessionTimelineRequestFailed("SDP format error.", /* cause= */ e); + ImmutableList tracks = buildTrackList(response.sessionDescription, uri); + if (tracks.isEmpty()) { + sessionInfoListener.onSessionTimelineRequestFailed("No playable track.", /* cause= */ null); + return; } + + sessionInfoListener.onSessionTimelineUpdated(sessionTiming, tracks); + hasUpdatedTimelineAndTracks = true; } private void onSetupResponseReceived(RtspSetupResponse response) { diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspHeaders.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspHeaders.java index 6b56b7b5ce1..12c980a1a31 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspHeaders.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspHeaders.java @@ -34,37 +34,40 @@ */ /* package */ final class RtspHeaders { - public static final String ACCEPT = "accept"; - public static final String ALLOW = "allow"; - public static final String AUTHORIZATION = "authorization"; - public static final String BANDWIDTH = "bandwidth"; - public static final String BLOCKSIZE = "blocksize"; - public static final String CACHE_CONTROL = "cache-control"; - public static final String CONNECTION = "connection"; - public static final String CONTENT_BASE = "content-base"; - public static final String CONTENT_ENCODING = "content-encoding"; - public static final String CONTENT_LANGUAGE = "content-language"; - public static final String CONTENT_LENGTH = "content-length"; - public static final String CONTENT_LOCATION = "content-location"; - public static final String CONTENT_TYPE = "content-type"; - public static final String CSEQ = "cseq"; - public static final String DATE = "date"; - public static final String EXPIRES = "expires"; - public static final String PROXY_AUTHENTICATE = "proxy-authenticate"; - public static final String PROXY_REQUIRE = "proxy-require"; - public static final String PUBLIC = "public"; - public static final String RANGE = "range"; - public static final String RTP_INFO = "rtp-info"; - public static final String RTCP_INTERVAL = "rtcp-interval"; - public static final String SCALE = "scale"; - public static final String SESSION = "session"; - public static final String SPEED = "speed"; - public static final String SUPPORTED = "supported"; - public static final String TIMESTAMP = "timestamp"; - public static final String TRANSPORT = "transport"; - public static final String USER_AGENT = "user-agent"; - public static final String VIA = "via"; - public static final String WWW_AUTHENTICATE = "www-authenticate"; + public static final String ACCEPT = "Accept"; + public static final String ALLOW = "Allow"; + public static final String AUTHORIZATION = "Authorization"; + public static final String BANDWIDTH = "Bandwidth"; + public static final String BLOCKSIZE = "Blocksize"; + public static final String CACHE_CONTROL = "Cache-Control"; + public static final String CONNECTION = "Connection"; + public static final String CONTENT_BASE = "Content-Base"; + public static final String CONTENT_ENCODING = "Content-Encoding"; + public static final String CONTENT_LANGUAGE = "Content-Language"; + public static final String CONTENT_LENGTH = "Content-Length"; + public static final String CONTENT_LOCATION = "Content-Location"; + public static final String CONTENT_TYPE = "Content-Type"; + public static final String CSEQ = "CSeq"; + public static final String DATE = "Date"; + public static final String EXPIRES = "Expires"; + public static final String PROXY_AUTHENTICATE = "Proxy-Authenticate"; + public static final String PROXY_REQUIRE = "Proxy-Require"; + public static final String PUBLIC = "Public"; + public static final String RANGE = "Range"; + public static final String RTP_INFO = "RTP-Info"; + public static final String RTCP_INTERVAL = "RTCP-Interval"; + public static final String SCALE = "Scale"; + public static final String SESSION = "Session"; + public static final String SPEED = "Speed"; + public static final String SUPPORTED = "Supported"; + public static final String TIMESTAMP = "Timestamp"; + public static final String TRANSPORT = "Transport"; + public static final String USER_AGENT = "User-Agent"; + public static final String VIA = "Via"; + public static final String WWW_AUTHENTICATE = "WWW-Authenticate"; + + /** An empty header object. */ + public static final RtspHeaders EMPTY = new RtspHeaders.Builder().build(); /** Builds {@link RtspHeaders} instances. */ public static final class Builder { @@ -75,6 +78,16 @@ public Builder() { namesAndValuesBuilder = new ImmutableListMultimap.Builder<>(); } + /** + * Creates a new instance to build upon the provided {@link RtspHeaders}. + * + * @param namesAndValuesBuilder A {@link ImmutableListMultimap.Builder} that this builder builds + * upon. + */ + private Builder(ImmutableListMultimap.Builder namesAndValuesBuilder) { + this.namesAndValuesBuilder = namesAndValuesBuilder; + } + /** * Adds a header name and header value pair. * @@ -83,7 +96,7 @@ public Builder() { * @return This builder. */ public Builder add(String headerName, String headerValue) { - namesAndValuesBuilder.put(Ascii.toLowerCase(headerName.trim()), headerValue.trim()); + namesAndValuesBuilder.put(convertToStandardHeaderName(headerName.trim()), headerValue.trim()); return this; } @@ -130,6 +143,31 @@ public RtspHeaders build() { private final ImmutableListMultimap namesAndValues; + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof RtspHeaders)) { + return false; + } + RtspHeaders headers = (RtspHeaders) obj; + return namesAndValues.equals(headers.namesAndValues); + } + + @Override + public int hashCode() { + return namesAndValues.hashCode(); + } + + /** Returns a {@link Builder} initialized with the values of this instance. */ + public Builder buildUpon() { + ImmutableListMultimap.Builder namesAndValuesBuilder = + new ImmutableListMultimap.Builder<>(); + namesAndValuesBuilder.putAll(namesAndValues); + return new Builder(namesAndValuesBuilder); + } + /** * Returns a map that associates header names to the list of values associated with the * corresponding header name. @@ -156,10 +194,77 @@ public String get(String headerName) { * list is empty if the header name is not recorded. */ public ImmutableList values(String headerName) { - return namesAndValues.get(Ascii.toLowerCase(headerName)); + return namesAndValues.get(convertToStandardHeaderName(headerName)); } private RtspHeaders(Builder builder) { this.namesAndValues = builder.namesAndValuesBuilder.build(); } + + private static String convertToStandardHeaderName(String messageHeaderName) { + if (Ascii.equalsIgnoreCase(messageHeaderName, ACCEPT)) { + return ACCEPT; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, ALLOW)) { + return ALLOW; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, AUTHORIZATION)) { + return AUTHORIZATION; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, BANDWIDTH)) { + return BANDWIDTH; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, BLOCKSIZE)) { + return BLOCKSIZE; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, CACHE_CONTROL)) { + return CACHE_CONTROL; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, CONNECTION)) { + return CONNECTION; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, CONTENT_BASE)) { + return CONTENT_BASE; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, CONTENT_ENCODING)) { + return CONTENT_ENCODING; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, CONTENT_LANGUAGE)) { + return CONTENT_LANGUAGE; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, CONTENT_LENGTH)) { + return CONTENT_LENGTH; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, CONTENT_LOCATION)) { + return CONTENT_LOCATION; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, CONTENT_TYPE)) { + return CONTENT_TYPE; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, CSEQ)) { + return CSEQ; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, DATE)) { + return DATE; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, EXPIRES)) { + return EXPIRES; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, PROXY_AUTHENTICATE)) { + return PROXY_AUTHENTICATE; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, PROXY_REQUIRE)) { + return PROXY_REQUIRE; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, PUBLIC)) { + return PUBLIC; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, RANGE)) { + return RANGE; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, RTP_INFO)) { + return RTP_INFO; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, RTCP_INTERVAL)) { + return RTCP_INTERVAL; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, SCALE)) { + return SCALE; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, SESSION)) { + return SESSION; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, SPEED)) { + return SPEED; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, SUPPORTED)) { + return SUPPORTED; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, TIMESTAMP)) { + return TIMESTAMP; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, TRANSPORT)) { + return TRANSPORT; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, USER_AGENT)) { + return USER_AGENT; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, VIA)) { + return VIA; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, WWW_AUTHENTICATE)) { + return WWW_AUTHENTICATE; + } + return messageHeaderName; + } } diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMediaPeriod.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMediaPeriod.java index db72bc0637a..14bcdfceb6f 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMediaPeriod.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMediaPeriod.java @@ -419,12 +419,12 @@ public TrackOutput track(int id, int type) { @Override public void endTracks() { - // TODO(b/172331505) Implement this method. + handler.post(RtspMediaPeriod.this::maybeFinishPrepare); } @Override public void seekMap(SeekMap seekMap) { - // TODO(b/172331505) Implement this method. + // RTSP does not support seek map. } // Loadable.Callback implementation. @@ -465,16 +465,6 @@ public Loader.LoadErrorAction onLoadError( long loadDurationMs, IOException error, int errorCount) { - /* TODO(b/172331505) Sort out the retry policy. - Three cases for IOException: - - Socket open failure for RTP or RTCP. - - RETRY for the RTCP open failure. - - ExtractorInput read IOException (socket timeout, etc) - - Keep retrying unless playback is stopped. - - RtpPayloadReader consume ParserException (mal-formatted RTP packet) - - Don't retry? (if a packet is distorted on the fly, the packet is likely discarded by the - system, i.e. the server's sent a mal-formatted packet). - */ if (!prepared) { preparationError = error; } else { @@ -514,13 +504,13 @@ public void onRtspSetupCompleted() { public void onPlaybackStarted( long startPositionUs, ImmutableList trackTimingList) { // Validate that the trackTimingList contains timings for the selected tracks. - ArrayList trackUrisWithTiming = new ArrayList<>(trackTimingList.size()); + ArrayList trackUrisWithTiming = new ArrayList<>(trackTimingList.size()); for (int i = 0; i < trackTimingList.size(); i++) { - trackUrisWithTiming.add(trackTimingList.get(i).uri); + trackUrisWithTiming.add(checkNotNull(trackTimingList.get(i).uri.getPath())); } for (int i = 0; i < selectedLoadInfos.size(); i++) { RtpLoadInfo loadInfo = selectedLoadInfos.get(i); - if (!trackUrisWithTiming.contains(loadInfo.getTrackUri())) { + if (!trackUrisWithTiming.contains(loadInfo.getTrackUri().getPath())) { playbackException = new RtspPlaybackException( "Server did not provide timing for track " + loadInfo.getTrackUri()); @@ -560,8 +550,8 @@ public void onSessionTimelineUpdated( RtspMediaTrack rtspMediaTrack = tracks.get(i); RtspLoaderWrapper loaderWrapper = new RtspLoaderWrapper(rtspMediaTrack, /* trackId= */ i, rtpDataChannelFactory); - loaderWrapper.startLoading(); rtspLoaderWrappers.add(loaderWrapper); + loaderWrapper.startLoading(); } listener.onSourceInfoRefreshed(timing); diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMediaSource.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMediaSource.java index b6799e8b67f..89cbaeddb38 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMediaSource.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMediaSource.java @@ -22,6 +22,7 @@ import android.net.Uri; import androidx.annotation.IntRange; import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlayerLibraryInfo; import com.google.android.exoplayer2.MediaItem; @@ -214,7 +215,8 @@ public RtspPlaybackException(String message, Throwable e) { private boolean timelineIsLive; private boolean timelineIsPlaceholder; - private RtspMediaSource( + @VisibleForTesting + /* package */ RtspMediaSource( MediaItem mediaItem, RtpDataChannel.Factory rtpDataChannelFactory, String userAgent) { this.mediaItem = mediaItem; this.rtpDataChannelFactory = rtpDataChannelFactory; @@ -250,7 +252,7 @@ public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long star allocator, rtpDataChannelFactory, uri, - (timing) -> { + /* listener= */ timing -> { timelineDurationUs = C.msToUs(timing.getDurationMs()); timelineIsSeekable = !timing.isLive(); timelineIsLive = timing.isLive(); diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMessageChannel.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMessageChannel.java index d45af667dcb..526f5089538 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMessageChannel.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMessageChannel.java @@ -279,7 +279,6 @@ public void cancelLoad() { @Override public void load() throws IOException { while (!loadCanceled) { - // TODO(internal b/172331505) Use a buffered read. byte firstByte = dataInputStream.readByte(); if (firstByte == INTERLEAVED_MESSAGE_MARKER) { handleInterleavedBinaryData(); diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMessageUtil.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMessageUtil.java index a6636effee6..c8ffff25747 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMessageUtil.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMessageUtil.java @@ -92,9 +92,9 @@ public RtspAuthUserInfo(String username, String password) { private static final Pattern CONTENT_LENGTH_HEADER_PATTERN = Pattern.compile("Content-Length:\\s?(\\d+)", CASE_INSENSITIVE); - // Session header pattern, see RFC2326 Section 12.37. + // Session header pattern, see RFC2326 Sections 3.4 and 12.37. private static final Pattern SESSION_HEADER_PATTERN = - Pattern.compile("(\\w+)(?:;\\s?timeout=(\\d+))?"); + Pattern.compile("([\\w$-_.+]+)(?:;\\s?timeout=(\\d+))?"); // WWW-Authenticate header pattern, see RFC2068 Sections 14.46 and RFC2069. private static final Pattern WWW_AUTHENTICATION_HEADER_DIGEST_PATTERN = @@ -347,7 +347,7 @@ public static long parseContentLengthHeader(String line) throws ParserException return C.LENGTH_UNSET; } } catch (NumberFormatException e) { - throw new ParserException(e); + throw ParserException.createForMalformedManifest(line, e); } } @@ -386,7 +386,7 @@ public static ImmutableList parsePublicHeader(@Nullable String publicHe public static RtspSessionHeader parseSessionHeader(String headerValue) throws ParserException { Matcher matcher = SESSION_HEADER_PATTERN.matcher(headerValue); if (!matcher.matches()) { - throw new ParserException(headerValue); + throw ParserException.createForMalformedManifest(headerValue, /* cause= */ null); } String sessionId = checkNotNull(matcher.group(1)); @@ -397,7 +397,7 @@ public static RtspSessionHeader parseSessionHeader(String headerValue) throws Pa try { timeoutMs = Integer.parseInt(timeoutString) * C.MILLIS_PER_SECOND; } catch (NumberFormatException e) { - throw new ParserException(e); + throw ParserException.createForMalformedManifest(headerValue, e); } } @@ -434,7 +434,8 @@ public static RtspAuthenticationInfo parseWwwAuthenticateHeader(String headerVal /* nonce= */ "", /* opaque= */ ""); } - throw new ParserException("Invalid WWW-Authenticate header " + headerValue); + throw ParserException.createForMalformedManifest( + "Invalid WWW-Authenticate header " + headerValue, /* cause= */ null); } private static String getRtspStatusReasonPhrase(int statusCode) { @@ -476,7 +477,7 @@ public static int parseInt(String intString) throws ParserException { try { return Integer.parseInt(intString); } catch (NumberFormatException e) { - throw new ParserException(e); + throw ParserException.createForMalformedManifest(intString, e); } } diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspOptionsResponse.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspOptionsResponse.java index 989303b461f..6a3403c7975 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspOptionsResponse.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspOptionsResponse.java @@ -19,8 +19,6 @@ import java.util.List; /** Represents an RTSP OPTIONS response. */ -// TODO(b/180434754) Move all classes under message to the parent rtsp package, and change the -// visibility. /* package */ final class RtspOptionsResponse { /** The response's status code. */ public final int status; diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspResponse.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspResponse.java index 7d56f1c580f..ec15fa75560 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspResponse.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspResponse.java @@ -18,9 +18,6 @@ /** Represents an RTSP Response. */ /* package */ final class RtspResponse { - // TODO(b/172331505) Move this constant to MimeTypes. - /** The MIME type associated with Session Description Protocol (RFC4566). */ - public static final String SDP_MIME_TYPE = "application/sdp"; /** The status code of this response, as defined in RFC 2326 section 11. */ public final int status; @@ -41,4 +38,14 @@ public RtspResponse(int status, RtspHeaders headers, String messageBody) { this.headers = headers; this.messageBody = messageBody; } + + /** + * Creates a new instance with an empty {@link #messageBody}. + * + * @param status The status code of this response, as defined in RFC 2326 section 11. + * @param headers The headers of this response. + */ + public RtspResponse(int status, RtspHeaders headers) { + this(status, headers, /* messageBody= */ ""); + } } diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspSessionTiming.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspSessionTiming.java index 73276d34467..6e2186f5dbc 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspSessionTiming.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspSessionTiming.java @@ -61,7 +61,7 @@ public static RtspSessionTiming parseTiming(String sdpRangeAttribute) throws Par try { stopTimeMs = (long) (Float.parseFloat(stopTimeString) * C.MILLIS_PER_SECOND); } catch (NumberFormatException e) { - throw new ParserException(e); + throw ParserException.createForMalformedManifest(stopTimeString, e); } checkArgument(stopTimeMs > startTimeMs); } else { diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspSetupResponse.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspSetupResponse.java index 03d1698b8b7..5f4cf51b4b9 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspSetupResponse.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspSetupResponse.java @@ -16,8 +16,6 @@ package com.google.android.exoplayer2.source.rtsp; /** Represents an RTSP SETUP response. */ -// TODO(b/180434754) Move all classes under message to the parent rtsp package, and change the -// visibility. /* package */ final class RtspSetupResponse { /** The response's status code. */ diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspTrackTiming.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspTrackTiming.java index 37c6f9ed49b..3e6d34038e5 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspTrackTiming.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspTrackTiming.java @@ -25,8 +25,6 @@ /** * Represents an RTSP track's timing info, included as {@link RtspHeaders#RTP_INFO} in an RTSP PLAY * response (RFC2326 Section 12.33). - * - *

    The fields {@link #rtpTimestamp} and {@link #sequenceNumber} will not both be {@code null}. */ /* package */ final class RtspTrackTiming { @@ -80,17 +78,17 @@ public static ImmutableList parseTrackTiming(String rtpInfoStri rtpTime = Long.parseLong(attributeValue); break; default: - throw new ParserException(); + throw ParserException.createForMalformedManifest(attributeName, /* cause= */ null); } } catch (Exception e) { - throw new ParserException(attributePair, e); + throw ParserException.createForMalformedManifest(attributePair, e); } } if (uri == null || uri.getScheme() == null // Checks if the URI is a URL. || (sequenceNumber == C.INDEX_UNSET && rtpTime == C.TIME_UNSET)) { - throw new ParserException(perTrackTimingString); + throw ParserException.createForMalformedManifest(perTrackTimingString, /* cause= */ null); } listBuilder.add(new RtspTrackTiming(rtpTime, sequenceNumber, uri)); @@ -98,9 +96,17 @@ public static ImmutableList parseTrackTiming(String rtpInfoStri return listBuilder.build(); } - /** The timestamp of the next RTP packet, {@link C#TIME_UNSET} if not present. */ + /** + * The timestamp of the next RTP packet, {@link C#TIME_UNSET} if not present. + * + *

    Cannot be {@link C#TIME_UNSET} if {@link #sequenceNumber} is {@link C#INDEX_UNSET}. + */ public final long rtpTimestamp; - /** The sequence number of the next RTP packet, {@link C#INDEX_UNSET} if not present. */ + /** + * The sequence number of the next RTP packet, {@link C#INDEX_UNSET} if not present. + * + *

    Cannot be {@link C#INDEX_UNSET} if {@link #rtpTimestamp} is {@link C#TIME_UNSET}. + */ public final int sequenceNumber; /** The {@link Uri} that identifies a matching {@link RtspMediaTrack}. */ public final Uri uri; diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/SessionDescription.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/SessionDescription.java index 770709b1b12..33df3d6d1e7 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/SessionDescription.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/SessionDescription.java @@ -238,7 +238,6 @@ public SessionDescription build() { public final ImmutableList mediaDescriptionList; /** The name of a session. */ public final String sessionName; - // TODO(internal b/172331505) Parse the String representations into objects. /** The origin sender info. */ public final String origin; /** The timing info. */ diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/SessionDescriptionParser.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/SessionDescriptionParser.java index cb47251b717..6d37b12c891 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/SessionDescriptionParser.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/SessionDescriptionParser.java @@ -76,7 +76,8 @@ public static SessionDescription parse(String sdpString) throws ParserException Matcher matcher = SDP_LINE_PATTERN.matcher(line); if (!matcher.matches()) { - throw new ParserException("Malformed SDP line: " + line); + throw ParserException.createForMalformedManifest( + "Malformed SDP line: " + line, /* cause= */ null); } String sdpType = checkNotNull(matcher.group(1)); @@ -85,7 +86,8 @@ public static SessionDescription parse(String sdpString) throws ParserException switch (sdpType) { case VERSION_TYPE: if (!SUPPORTED_SDP_VERSION.equals(sdpValue)) { - throw new ParserException(String.format("SDP version %s is not supported.", sdpValue)); + throw ParserException.createForMalformedManifest( + String.format("SDP version %s is not supported.", sdpValue), /* cause= */ null); } break; @@ -153,7 +155,8 @@ public static SessionDescription parse(String sdpString) throws ParserException case ATTRIBUTE_TYPE: matcher = ATTRIBUTE_PATTERN.matcher(sdpValue); if (!matcher.matches()) { - throw new ParserException("Malformed Attribute line: " + line); + throw ParserException.createForMalformedManifest( + "Malformed Attribute line: " + line, /* cause= */ null); } String attributeName = checkNotNull(matcher.group(1)); @@ -187,7 +190,7 @@ public static SessionDescription parse(String sdpString) throws ParserException try { return sessionDescriptionBuilder.build(); } catch (IllegalArgumentException | IllegalStateException e) { - throw new ParserException(e); + throw ParserException.createForMalformedManifest(/* message= */ null, e); } } @@ -198,7 +201,7 @@ private static void addMediaDescriptionToSession( try { sessionDescriptionBuilder.addMediaDescription(mediaDescriptionBuilder.build()); } catch (IllegalArgumentException | IllegalStateException e) { - throw new ParserException(e); + throw ParserException.createForMalformedManifest(/* message= */ null, e); } } @@ -206,7 +209,8 @@ private static MediaDescription.Builder parseMediaDescriptionLine(String line) throws ParserException { Matcher matcher = MEDIA_DESCRIPTION_PATTERN.matcher(line); if (!matcher.matches()) { - throw new ParserException("Malformed SDP media description line: " + line); + throw ParserException.createForMalformedManifest( + "Malformed SDP media description line: " + line, /* cause= */ null); } String mediaType = checkNotNull(matcher.group(1)); String portString = checkNotNull(matcher.group(2)); @@ -220,7 +224,8 @@ private static MediaDescription.Builder parseMediaDescriptionLine(String line) transportProtocol, Integer.parseInt(payloadTypeString)); } catch (NumberFormatException e) { - throw new ParserException("Malformed SDP media description line: " + line, e); + throw ParserException.createForMalformedManifest( + "Malformed SDP media description line: " + line, e); } } diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/TransferRtpDataChannel.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/TransferRtpDataChannel.java index bd036d9f1c3..c96a3ea7256 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/TransferRtpDataChannel.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/TransferRtpDataChannel.java @@ -88,14 +88,14 @@ public Uri getUri() { } @Override - public int read(byte[] target, int offset, int length) { + public int read(byte[] buffer, int offset, int length) { if (length == 0) { return 0; } int bytesRead = 0; int bytesToRead = min(length, unreadData.length); - System.arraycopy(unreadData, /* srcPos= */ 0, target, offset, bytesToRead); + System.arraycopy(unreadData, /* srcPos= */ 0, buffer, offset, bytesToRead); bytesRead += bytesToRead; unreadData = Arrays.copyOfRange(unreadData, bytesToRead, unreadData.length); @@ -115,7 +115,7 @@ public int read(byte[] target, int offset, int length) { } bytesToRead = min(length - bytesRead, data.length); - System.arraycopy(data, /* srcPos= */ 0, target, offset + bytesRead, bytesToRead); + System.arraycopy(data, /* srcPos= */ 0, buffer, offset + bytesRead, bytesToRead); if (bytesToRead < data.length) { unreadData = Arrays.copyOfRange(data, bytesToRead, data.length); } diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/UdpDataSourceRtpDataChannel.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/UdpDataSourceRtpDataChannel.java index 95bf5027cad..44331f524b0 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/UdpDataSourceRtpDataChannel.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/UdpDataSourceRtpDataChannel.java @@ -21,13 +21,13 @@ import android.net.Uri; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.TransferListener; import com.google.android.exoplayer2.upstream.UdpDataSource; import com.google.android.exoplayer2.util.Util; import com.google.common.primitives.Ints; import java.io.IOException; -import java.net.SocketTimeoutException; /** An {@link RtpDataChannel} for UDP transport. */ /* package */ final class UdpDataSourceRtpDataChannel implements RtpDataChannel { @@ -94,11 +94,11 @@ public void close() { } @Override - public int read(byte[] target, int offset, int length) throws IOException { + public int read(byte[] buffer, int offset, int length) throws IOException { try { - return dataSource.read(target, offset, length); + return dataSource.read(buffer, offset, length); } catch (UdpDataSource.UdpDataSourceException e) { - if (e.getCause() instanceof SocketTimeoutException) { + if (e.reason == PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT) { return C.RESULT_END_OF_INPUT; } else { throw e; diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/reader/RtpAacReader.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/reader/RtpAacReader.java index fe393a9eb54..ec747fa1e21 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/reader/RtpAacReader.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/reader/RtpAacReader.java @@ -86,7 +86,7 @@ public void onReceivingFirstPacket(long timestamp, int sequenceNumber) { @Override public void consume( - ParsableByteArray data, long timestamp, int sequenceNumber, boolean isFrameBoundary) { + ParsableByteArray data, long timestamp, int sequenceNumber, boolean rtpMarker) { /* AAC as RTP payload (RFC3640): +---------+-----------+-----------+---------------+ @@ -120,7 +120,7 @@ Access Unit(AU) Header section // Outputs all the received data, whether fragmented or not. trackOutput.sampleData(data, data.bytesLeft()); - if (isFrameBoundary) { + if (rtpMarker) { outputSampleMetadata(trackOutput, sampleTimeUs, auSize); } } else { diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/reader/RtpAc3Reader.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/reader/RtpAc3Reader.java index ba520f841bf..33ab218a537 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/reader/RtpAc3Reader.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/reader/RtpAc3Reader.java @@ -73,7 +73,7 @@ public void onReceivingFirstPacket(long timestamp, int sequenceNumber) { @Override public void consume( - ParsableByteArray data, long timestamp, int sequenceNumber, boolean isFrameBoundary) { + ParsableByteArray data, long timestamp, int sequenceNumber, boolean rtpMarker) { /* AC-3 payload as an RTP payload (RFC4184). +-+-+-+-+-+-+-+-+-+-+-+-+-+- .. +-+-+-+-+-+-+-+ @@ -115,7 +115,7 @@ public void consume( // Falls through. case AC3_FRAME_TYPE_NON_INITIAL_FRAGMENT: // The content of an AC3 frame is split into multiple RTP packets. - processFragmentedPacket(data, isFrameBoundary, frameType, sampleTimeUs); + processFragmentedPacket(data, rtpMarker, frameType, sampleTimeUs); break; default: diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/reader/RtpH264Reader.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/reader/RtpH264Reader.java index ef1855c95b1..e3b7bd51a7e 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/reader/RtpH264Reader.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/reader/RtpH264Reader.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.source.rtsp.reader; +import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull; import static com.google.android.exoplayer2.util.Util.castNonNull; @@ -35,10 +36,6 @@ /* package */ final class RtpH264Reader implements RtpPayloadReader { private static final String TAG = "RtpH264Reader"; - // TODO(b/172331505) Move NAL related constants to NalUnitUtil. - private static final ParsableByteArray NAL_START_CODE = - new ParsableByteArray(NalUnitUtil.NAL_START_CODE); - private static final int NAL_START_CODE_LENGTH = NalUnitUtil.NAL_START_CODE.length; private static final long MEDIA_CLOCK_FREQUENCY = 90_000; /** Offset of payload data within a FU type A payload. */ @@ -55,6 +52,9 @@ /** Scratch for Fragmentation Unit RTP packets. */ private final ParsableByteArray fuScratchBuffer; + private final ParsableByteArray nalStartCodeArray = + new ParsableByteArray(NalUnitUtil.NAL_START_CODE); + private final RtpPayloadFormat payloadFormat; private @MonotonicNonNull TrackOutput trackOutput; @@ -86,8 +86,7 @@ public void createTracks(ExtractorOutput extractorOutput, int trackId) { public void onReceivingFirstPacket(long timestamp, int sequenceNumber) {} @Override - public void consume( - ParsableByteArray data, long timestamp, int sequenceNumber, boolean isAuBoundary) + public void consume(ParsableByteArray data, long timestamp, int sequenceNumber, boolean rtpMarker) throws ParserException { int rtpH264PacketMode; @@ -95,7 +94,7 @@ public void consume( // RFC6184 Section 5.6, 5.7 and 5.8. rtpH264PacketMode = data.getData()[0] & 0x1F; } catch (IndexOutOfBoundsException e) { - throw new ParserException(e); + throw ParserException.createForMalformedManifest(/* message= */ null, e); } checkStateNotNull(trackOutput); @@ -106,11 +105,12 @@ public void consume( } else if (rtpH264PacketMode == RTP_PACKET_TYPE_FU_A) { processFragmentationUnitPacket(data, sequenceNumber); } else { - throw new ParserException( - String.format("RTP H264 packetization mode [%d] not supported.", rtpH264PacketMode)); + throw ParserException.createForMalformedManifest( + String.format("RTP H264 packetization mode [%d] not supported.", rtpH264PacketMode), + /* cause= */ null); } - if (isAuBoundary) { + if (rtpMarker) { if (firstReceivedTimestamp == C.TIME_UNSET) { firstReceivedTimestamp = timestamp; } @@ -159,7 +159,7 @@ private void processSingleNalUnitPacket(ParsableByteArray data) { // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ int numBytesInData = data.bytesLeft(); - fragmentedSampleSizeBytes += writeStartCode(trackOutput); + fragmentedSampleSizeBytes += writeStartCode(); trackOutput.sampleData(data, numBytesInData); fragmentedSampleSizeBytes += numBytesInData; @@ -202,13 +202,12 @@ private void processSingleTimeAggregationPacket(ParsableByteArray data) { int nalUnitLength; while (data.bytesLeft() > 4) { nalUnitLength = data.readUnsignedShort(); - fragmentedSampleSizeBytes += writeStartCode(trackOutput); + fragmentedSampleSizeBytes += writeStartCode(); trackOutput.sampleData(data, nalUnitLength); fragmentedSampleSizeBytes += nalUnitLength; } // Treat Aggregated NAL units as non key frames. - // TODO(internal b/172331505) examine whether STAP mode carries keyframes. bufferFlags = 0; } @@ -251,7 +250,7 @@ private void processFragmentationUnitPacket(ParsableByteArray data, int packetSe if (isFirstFuPacket) { // Prepends starter code. - fragmentedSampleSizeBytes += writeStartCode(trackOutput); + fragmentedSampleSizeBytes += writeStartCode(); // The bytes needed is 1 (NALU header) + payload size. The original data array has size 2 (FU // indicator/header) + payload size. Thus setting the correct header and set position to 1. @@ -285,6 +284,13 @@ private void processFragmentationUnitPacket(ParsableByteArray data, int packetSe } } + private int writeStartCode() { + nalStartCodeArray.setPosition(/* position= */ 0); + int bytesWritten = nalStartCodeArray.bytesLeft(); + checkNotNull(trackOutput).sampleData(nalStartCodeArray, bytesWritten); + return bytesWritten; + } + private static long toSampleUs( long startTimeOffsetUs, long rtpTimestamp, long firstReceivedRtpTimestamp) { return startTimeOffsetUs @@ -294,12 +300,6 @@ private static long toSampleUs( /* divisor= */ MEDIA_CLOCK_FREQUENCY); } - private static int writeStartCode(TrackOutput trackOutput) { - trackOutput.sampleData(NAL_START_CODE, NAL_START_CODE_LENGTH); - NAL_START_CODE.setPosition(/* position= */ 0); - return NAL_START_CODE_LENGTH; - } - @C.BufferFlags private static int getBufferFlagsFromNalType(int nalType) { return nalType == NAL_UNIT_TYPE_IDR ? C.BUFFER_FLAG_KEY_FRAME : 0; diff --git a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtpPacketStreamDump.java b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtpPacketStreamDump.java index 2b04c087117..47584942734 100644 --- a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtpPacketStreamDump.java +++ b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtpPacketStreamDump.java @@ -83,7 +83,7 @@ public static RtpPacketStreamDump parse(String jsonString) throws ParserExceptio mediaDescription, packetsBuilder.build()); } catch (JSONException e) { - throw new ParserException(e); + throw ParserException.createForMalformedManifest(/* message= */ null, e); } } diff --git a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtpPacketTransmitter.java b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtpPacketTransmitter.java new file mode 100644 index 00000000000..dfaaf016911 --- /dev/null +++ b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtpPacketTransmitter.java @@ -0,0 +1,91 @@ +/* + * 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 com.google.android.exoplayer2.source.rtsp; + +import com.google.android.exoplayer2.source.rtsp.RtspMessageChannel.InterleavedBinaryDataListener; +import com.google.android.exoplayer2.util.Clock; +import com.google.android.exoplayer2.util.HandlerWrapper; +import com.google.android.exoplayer2.util.Util; +import com.google.common.collect.ImmutableList; + +/** Transmits media RTP packets periodically. */ +/* package */ final class RtpPacketTransmitter { + + private static final byte[] END_OF_STREAM = new byte[0]; + + private final ImmutableList packets; + private final HandlerWrapper transmissionHandler; + private final long transmissionIntervalMs; + + private RtspMessageChannel.InterleavedBinaryDataListener binaryDataListener; + private int packetIndex; + private volatile boolean isTransmitting; + + /** + * Creates a new instance. + * + * @param rtpPacketStreamDump The {@link RtpPacketStreamDump} to provide RTP packets. + * @param clock The {@link Clock} to use. + */ + public RtpPacketTransmitter(RtpPacketStreamDump rtpPacketStreamDump, Clock clock) { + this.packets = ImmutableList.copyOf(rtpPacketStreamDump.packets); + this.transmissionHandler = + clock.createHandler(Util.getCurrentOrMainLooper(), /* callback= */ null); + this.transmissionIntervalMs = rtpPacketStreamDump.transmissionIntervalMs; + } + + /** + * Starts transmitting binary data to the {@link InterleavedBinaryDataListener}. + * + *

    Calling this method after starting the transmission has no effect. + */ + public void startTransmitting(InterleavedBinaryDataListener binaryDataListener) { + if (isTransmitting) { + return; + } + + this.binaryDataListener = binaryDataListener; + packetIndex = 0; + isTransmitting = true; + transmissionHandler.post(this::transmitNextPacket); + } + + /** Stops transmitting, if transmitting has started. */ + private void stopTransmitting() { + if (!isTransmitting) { + return; + } + + signalEndOfStream(); + transmissionHandler.removeCallbacksAndMessages(/* token= */ null); + isTransmitting = false; + } + + private void transmitNextPacket() { + if (packetIndex == packets.size()) { + stopTransmitting(); + return; + } + + byte[] data = Util.getBytesFromHexString(packets.get(packetIndex++)); + binaryDataListener.onInterleavedBinaryDataReceived(data); + transmissionHandler.postDelayed(this::transmitNextPacket, transmissionIntervalMs); + } + + private void signalEndOfStream() { + binaryDataListener.onInterleavedBinaryDataReceived(END_OF_STREAM); + } +} diff --git a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspClientTest.java b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspClientTest.java index 5e5f3085ed1..129871c584d 100644 --- a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspClientTest.java +++ b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspClientTest.java @@ -15,21 +15,20 @@ */ package com.google.android.exoplayer2.source.rtsp; -import static com.google.android.exoplayer2.util.Assertions.checkNotNull; +import static com.google.common.truth.Truth.assertThat; import android.net.Uri; import androidx.annotation.Nullable; -import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.robolectric.RobolectricUtil; import com.google.android.exoplayer2.source.rtsp.RtspClient.PlaybackEventListener; import com.google.android.exoplayer2.source.rtsp.RtspClient.SessionInfoListener; import com.google.android.exoplayer2.source.rtsp.RtspMediaSource.RtspPlaybackException; -import com.google.android.exoplayer2.testutil.TestUtil; import com.google.android.exoplayer2.util.Util; import com.google.common.collect.ImmutableList; import java.util.concurrent.atomic.AtomicBoolean; -import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import java.util.concurrent.atomic.AtomicReference; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -39,16 +38,37 @@ @RunWith(AndroidJUnit4.class) public final class RtspClientTest { - private @MonotonicNonNull RtspClient rtspClient; - private @MonotonicNonNull RtspServer rtspServer; + private static final String SESSION_DESCRIPTION = + "v=0\r\n" + + "o=- 1606776316530225 1 IN IP4 127.0.0.1\r\n" + + "s=Exoplayer test\r\n" + + "t=0 0\r\n" + + "a=range:npt=0-50.46\r\n"; + private static final RtspClient.PlaybackEventListener EMPTY_PLAYBACK_LISTENER = + new PlaybackEventListener() { + @Override + public void onRtspSetupCompleted() {} + + @Override + public void onPlaybackStarted( + long startPositionUs, ImmutableList trackTimingList) {} + + @Override + public void onPlaybackError(RtspPlaybackException error) {} + }; + + private ImmutableList rtpPacketStreamDumps; + private RtspClient rtspClient; + private RtspServer rtspServer; @Before public void setUp() throws Exception { - rtspServer = - new RtspServer( - RtpPacketStreamDump.parse( - TestUtil.getString( - ApplicationProvider.getApplicationContext(), "media/rtsp/aac-dump.json"))); + rtpPacketStreamDumps = + ImmutableList.of( + RtspTestUtils.readRtpPacketStreamDump("media/rtsp/h264-dump.json"), + RtspTestUtils.readRtpPacketStreamDump("media/rtsp/aac-dump.json"), + // MP4A-LATM is not supported at the moment. + RtspTestUtils.readRtpPacketStreamDump("media/rtsp/mp4a-latm-dump.json")); } @After @@ -58,40 +78,173 @@ public void tearDown() { } @Test - public void connectServerAndClient_withServerSupportsDescribe_updatesSessionTimeline() + public void connectServerAndClient_serverSupportsDescribe_updatesSessionTimeline() throws Exception { - int serverRtspPortNumber = checkNotNull(rtspServer).startAndGetPortNumber(); + class ResponseProvider implements RtspServer.ResponseProvider { + @Override + public RtspResponse getOptionsResponse() { + return new RtspResponse( + /* status= */ 200, + new RtspHeaders.Builder().add(RtspHeaders.PUBLIC, "OPTIONS, DESCRIBE").build()); + } + + @Override + public RtspResponse getDescribeResponse(Uri requestedUri) { + return RtspTestUtils.newDescribeResponseWithSdpMessage( + SESSION_DESCRIPTION, rtpPacketStreamDumps, requestedUri); + } + } + rtspServer = new RtspServer(new ResponseProvider()); - AtomicBoolean sessionTimelineUpdateEventReceived = new AtomicBoolean(); + AtomicReference> tracksInSession = new AtomicReference<>(); rtspClient = new RtspClient( new SessionInfoListener() { @Override public void onSessionTimelineUpdated( RtspSessionTiming timing, ImmutableList tracks) { - sessionTimelineUpdateEventReceived.set(!tracks.isEmpty()); + tracksInSession.set(tracks); } @Override public void onSessionTimelineRequestFailed( String message, @Nullable Throwable cause) {} }, - new PlaybackEventListener() { + EMPTY_PLAYBACK_LISTENER, + /* userAgent= */ "ExoPlayer:RtspClientTest", + RtspTestUtils.getTestUri(rtspServer.startAndGetPortNumber())); + rtspClient.start(); + RobolectricUtil.runMainLooperUntil(() -> tracksInSession.get() != null); + + assertThat(tracksInSession.get()).hasSize(2); + } + + @Test + public void + connectServerAndClient_serverSupportsDescribeNoHeaderInOptions_updatesSessionTimeline() + throws Exception { + class ResponseProvider implements RtspServer.ResponseProvider { + @Override + public RtspResponse getOptionsResponse() { + return new RtspResponse(/* status= */ 200, RtspHeaders.EMPTY); + } + + @Override + public RtspResponse getDescribeResponse(Uri requestedUri) { + return RtspTestUtils.newDescribeResponseWithSdpMessage( + SESSION_DESCRIPTION, rtpPacketStreamDumps, requestedUri); + } + } + rtspServer = new RtspServer(new ResponseProvider()); + + AtomicReference> tracksInSession = new AtomicReference<>(); + rtspClient = + new RtspClient( + new SessionInfoListener() { @Override - public void onRtspSetupCompleted() {} + public void onSessionTimelineUpdated( + RtspSessionTiming timing, ImmutableList tracks) { + tracksInSession.set(tracks); + } @Override - public void onPlaybackStarted( - long startPositionUs, ImmutableList trackTimingList) {} + public void onSessionTimelineRequestFailed( + String message, @Nullable Throwable cause) {} + }, + EMPTY_PLAYBACK_LISTENER, + /* userAgent= */ "ExoPlayer:RtspClientTest", + RtspTestUtils.getTestUri(rtspServer.startAndGetPortNumber())); + rtspClient.start(); + RobolectricUtil.runMainLooperUntil(() -> tracksInSession.get() != null); + + assertThat(tracksInSession.get()).hasSize(2); + } + + @Test + public void connectServerAndClient_serverDoesNotSupportDescribe_doesNotUpdateTimeline() + throws Exception { + AtomicBoolean clientHasSentDescribeRequest = new AtomicBoolean(); + + class ResponseProvider implements RtspServer.ResponseProvider { + @Override + public RtspResponse getOptionsResponse() { + return new RtspResponse( + /* status= */ 200, + new RtspHeaders.Builder().add(RtspHeaders.PUBLIC, "OPTIONS").build()); + } + @Override + public RtspResponse getDescribeResponse(Uri requestedUri) { + clientHasSentDescribeRequest.set(true); + return RtspTestUtils.RTSP_ERROR_METHOD_NOT_ALLOWED; + } + } + rtspServer = new RtspServer(new ResponseProvider()); + + AtomicReference failureMessage = new AtomicReference<>(); + rtspClient = + new RtspClient( + new SessionInfoListener() { + @Override + public void onSessionTimelineUpdated( + RtspSessionTiming timing, ImmutableList tracks) {} + + @Override + public void onSessionTimelineRequestFailed( + String message, @Nullable Throwable cause) { + failureMessage.set(message); + } + }, + EMPTY_PLAYBACK_LISTENER, + /* userAgent= */ "ExoPlayer:RtspClientTest", + RtspTestUtils.getTestUri(rtspServer.startAndGetPortNumber())); + rtspClient.start(); + RobolectricUtil.runMainLooperUntil(() -> failureMessage.get() != null); + + assertThat(failureMessage.get()).contains("DESCRIBE not supported."); + assertThat(clientHasSentDescribeRequest.get()).isFalse(); + } + + @Test + public void connectServerAndClient_malformedSdpInDescribeResponse_doesNotUpdateTimeline() + throws Exception { + class ResponseProvider implements RtspServer.ResponseProvider { + @Override + public RtspResponse getOptionsResponse() { + return new RtspResponse( + /* status= */ 200, + new RtspHeaders.Builder().add(RtspHeaders.PUBLIC, "OPTIONS, DESCRIBE").build()); + } + + @Override + public RtspResponse getDescribeResponse(Uri requestedUri) { + // This session description misses required the o, t and s tags. + return RtspTestUtils.newDescribeResponseWithSdpMessage( + /* sessionDescription= */ "v=0\r\n", rtpPacketStreamDumps, requestedUri); + } + } + rtspServer = new RtspServer(new ResponseProvider()); + + AtomicReference failureCause = new AtomicReference<>(); + rtspClient = + new RtspClient( + new SessionInfoListener() { @Override - public void onPlaybackError(RtspPlaybackException error) {} + public void onSessionTimelineUpdated( + RtspSessionTiming timing, ImmutableList tracks) {} + + @Override + public void onSessionTimelineRequestFailed( + String message, @Nullable Throwable cause) { + failureCause.set(cause); + } }, + EMPTY_PLAYBACK_LISTENER, /* userAgent= */ "ExoPlayer:RtspClientTest", - /* uri= */ Uri.parse( - Util.formatInvariant("rtsp://localhost:%d/test", serverRtspPortNumber))); + RtspTestUtils.getTestUri(rtspServer.startAndGetPortNumber())); rtspClient.start(); - RobolectricUtil.runMainLooperUntil(sessionTimelineUpdateEventReceived::get); + RobolectricUtil.runMainLooperUntil(() -> failureCause.get() != null); + assertThat(failureCause.get()).hasCauseThat().isInstanceOf(ParserException.class); } } diff --git a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspHeadersTest.java b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspHeadersTest.java index b8b8cbc5dd8..9c642729c6b 100644 --- a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspHeadersTest.java +++ b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspHeadersTest.java @@ -64,6 +64,31 @@ public void build_withHeaderLinesAsMap() { assertThat(headers.get("Transport")).isEqualTo("RTP/AVP;unicast;client_port=65458-65459"); } + @Test + public void buildUpon_createEqualHeaders() { + RtspHeaders headers = + new RtspHeaders.Builder() + .addAll( + ImmutableMap.of( + "Content-Length", "707", + "Transport", "RTP/AVP;unicast;client_port=65458-65459\r\n")) + .build(); + + assertThat(headers.buildUpon().build()).isEqualTo(headers); + } + + @Test + public void buildUpon_buildsUponExistingHeaders() { + RtspHeaders headers = new RtspHeaders.Builder().add("Content-Length", "707").build(); + + assertThat(headers.buildUpon().add("Content-Encoding", "utf-8").build()) + .isEqualTo( + new RtspHeaders.Builder() + .add("Content-Length", "707") + .add("Content-Encoding", "utf-8") + .build()); + } + @Test public void get_getsHeaderValuesCaseInsensitively() { RtspHeaders headers = @@ -135,14 +160,15 @@ public void asMultiMap_withoutValuesMappedToTheSameName_getsTheMappedValuesInAdd .build(); assertThat(headers.asMultiMap()) .containsExactly( - "accept", "application/sdp", - "cseq", "3", - "content-length", "707", - "transport", "RTP/AVP;unicast;client_port=65458-65459"); + "Accept", "application/sdp", + "CSeq", "3", + "Content-Length", "707", + "Transport", "RTP/AVP;unicast;client_port=65458-65459"); } @Test - public void asMap_withMultipleValuesMappedToTheSameName_getsTheMappedValuesInAdditionOrder() { + public void + asMultiMap_withMultipleValuesMappedToTheSameName_getsTheMappedValuesInAdditionOrder() { RtspHeaders headers = new RtspHeaders.Builder() .addAll( @@ -156,14 +182,16 @@ public void asMap_withMultipleValuesMappedToTheSameName_getsTheMappedValuesInAdd .build(); ListMultimap headersMap = headers.asMultiMap(); - assertThat(headersMap.keySet()).containsExactly("accept", "cseq", "transport").inOrder(); + assertThat(headersMap.keySet()) + .containsExactly(RtspHeaders.ACCEPT, RtspHeaders.CSEQ, RtspHeaders.TRANSPORT) + .inOrder(); assertThat(headersMap) - .valuesForKey("accept") + .valuesForKey(RtspHeaders.ACCEPT) .containsExactly("application/sdp", "application/sip") .inOrder(); - assertThat(headersMap).valuesForKey("cseq").containsExactly("3", "5").inOrder(); + assertThat(headersMap).valuesForKey(RtspHeaders.CSEQ).containsExactly("3", "5").inOrder(); assertThat(headersMap) - .valuesForKey("transport") + .valuesForKey(RtspHeaders.TRANSPORT) .containsExactly( "RTP/AVP;unicast;client_port=65456-65457", "RTP/AVP;unicast;client_port=65458-65459") .inOrder(); diff --git a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMediaPeriodTest.java b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMediaPeriodTest.java new file mode 100644 index 00000000000..90721039584 --- /dev/null +++ b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMediaPeriodTest.java @@ -0,0 +1,106 @@ +/* + * 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 com.google.android.exoplayer2.source.rtsp; + +import static com.google.common.truth.Truth.assertThat; + +import android.net.Uri; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.robolectric.RobolectricUtil; +import com.google.android.exoplayer2.source.MediaPeriod; +import com.google.android.exoplayer2.upstream.DefaultAllocator; +import com.google.android.exoplayer2.util.Util; +import com.google.common.collect.ImmutableList; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** Tests the {@link RtspMediaPeriod} using the {@link RtspServer}. */ +@RunWith(AndroidJUnit4.class) +public final class RtspMediaPeriodTest { + + private static final long DEFAULT_TIMEOUT_MS = 8000; + + private RtspMediaPeriod mediaPeriod; + private RtspServer rtspServer; + + @After + public void tearDown() { + Util.closeQuietly(rtspServer); + } + + @Test + public void prepareMediaPeriod_refreshesSourceInfoAndCallsOnPrepared() throws Exception { + RtpPacketStreamDump rtpPacketStreamDump = + RtspTestUtils.readRtpPacketStreamDump("media/rtsp/aac-dump.json"); + + rtspServer = + new RtspServer( + new RtspServer.ResponseProvider() { + @Override + public RtspResponse getOptionsResponse() { + return new RtspResponse( + /* status= */ 200, + new RtspHeaders.Builder().add(RtspHeaders.PUBLIC, "OPTIONS, DESCRIBE").build()); + } + + @Override + public RtspResponse getDescribeResponse(Uri requestedUri) { + return RtspTestUtils.newDescribeResponseWithSdpMessage( + "v=0\r\n" + + "o=- 1606776316530225 1 IN IP4 127.0.0.1\r\n" + + "s=Exoplayer test\r\n" + + "t=0 0\r\n" + // The session is 50.46s long. + + "a=range:npt=0-50.46\r\n", + ImmutableList.of(rtpPacketStreamDump), + requestedUri); + } + }); + + AtomicBoolean prepareCallbackCalled = new AtomicBoolean(); + AtomicLong refreshedSourceDurationMs = new AtomicLong(); + + mediaPeriod = + new RtspMediaPeriod( + new DefaultAllocator(/* trimOnReset= */ true, C.DEFAULT_BUFFER_SEGMENT_SIZE), + new TransferRtpDataChannelFactory(DEFAULT_TIMEOUT_MS), + RtspTestUtils.getTestUri(rtspServer.startAndGetPortNumber()), + /* listener= */ timing -> refreshedSourceDurationMs.set(timing.getDurationMs()), + /* userAgent= */ "ExoPlayer:RtspPeriodTest"); + + mediaPeriod.prepare( + new MediaPeriod.Callback() { + @Override + public void onPrepared(MediaPeriod mediaPeriod) { + prepareCallbackCalled.set(true); + } + + @Override + public void onContinueLoadingRequested(MediaPeriod source) { + source.continueLoading(/* positionUs= */ 0); + } + }, + /* positionUs= */ 0); + RobolectricUtil.runMainLooperUntil(prepareCallbackCalled::get); + mediaPeriod.release(); + + assertThat(refreshedSourceDurationMs.get()).isEqualTo(50_460); + } +} diff --git a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMediaTrackTest.java b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMediaTrackTest.java index 363533536e6..7a24183084b 100644 --- a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMediaTrackTest.java +++ b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMediaTrackTest.java @@ -80,6 +80,48 @@ public void generatePayloadFormat_withH264MediaDescription_succeeds() { assertThat(format).isEqualTo(expectedFormat); } + @Test + public void generatePayloadFormat_withFmtpTrailingSemicolon_succeeds() { + MediaDescription mediaDescription = + new MediaDescription.Builder( + MEDIA_TYPE_VIDEO, /* port= */ 0, RTP_AVP_PROFILE, /* payloadType= */ 96) + .setConnection("IN IP4 0.0.0.0") + .setBitrate(500_000) + .addAttribute(ATTR_RTPMAP, "96 H264/90000") + .addAttribute( + ATTR_FMTP, + "96 packetization-mode=1;profile-level-id=64001F;sprop-parameter-sets=Z2QAH6zZQPARabIAAAMACAAAAwGcHjBjLA==,aOvjyyLA;") + .addAttribute(ATTR_CONTROL, "track1") + .build(); + + RtpPayloadFormat format = RtspMediaTrack.generatePayloadFormat(mediaDescription); + RtpPayloadFormat expectedFormat = + new RtpPayloadFormat( + new Format.Builder() + .setSampleMimeType(MimeTypes.VIDEO_H264) + .setAverageBitrate(500_000) + .setPixelWidthHeightRatio(1.0f) + .setHeight(544) + .setWidth(960) + .setCodecs("avc1.64001F") + .setInitializationData( + ImmutableList.of( + new byte[] { + 0, 0, 0, 1, 103, 100, 0, 31, -84, -39, 64, -16, 17, 105, -78, 0, 0, 3, 0, + 8, 0, 0, 3, 1, -100, 30, 48, 99, 44 + }, + new byte[] {0, 0, 0, 1, 104, -21, -29, -53, 34, -64})) + .build(), + /* rtpPayloadType= */ 96, + /* clockRate= */ 90_000, + /* fmtpParameters= */ ImmutableMap.of( + "packetization-mode", "1", + "profile-level-id", "64001F", + "sprop-parameter-sets", "Z2QAH6zZQPARabIAAAMACAAAAwGcHjBjLA==,aOvjyyLA")); + + assertThat(format).isEqualTo(expectedFormat); + } + @Test public void generatePayloadFormat_withAacMediaDescription_succeeds() { MediaDescription mediaDescription = diff --git a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMessageChannelTest.java b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMessageChannelTest.java index cc2f4d24a32..7e559b31a94 100644 --- a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMessageChannelTest.java +++ b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMessageChannelTest.java @@ -53,8 +53,7 @@ public void rtspMessageChannelReceive_threeRtspMessagesAndTwoInterleavedBinary_p new RtspHeaders.Builder() .add(RtspHeaders.CSEQ, "2") .add(RtspHeaders.PUBLIC, "OPTIONS") - .build(), - ""); + .build()); RtspResponse describeResponse = new RtspResponse( @@ -82,8 +81,7 @@ public void rtspMessageChannelReceive_threeRtspMessagesAndTwoInterleavedBinary_p new RtspHeaders.Builder() .add(RtspHeaders.CSEQ, "5") .add(RtspHeaders.TRANSPORT, "RTP/AVP/TCP;unicast;interleaved=0-1") - .build(), - ""); + .build()); // Channel: 0, size: 5, data: 01 02 03 04 05. byte[] interleavedData1 = Util.getBytesFromHexString("0000050102030405"); @@ -151,26 +149,26 @@ public void rtspMessageChannelReceive_threeRtspMessagesAndTwoInterleavedBinary_p assertThat(receivedRtspResponses) .containsExactly( /* optionsResponse */ - ImmutableList.of("RTSP/1.0 200 OK", "cseq: 2", "public: OPTIONS", ""), + ImmutableList.of("RTSP/1.0 200 OK", "CSeq: 2", "Public: OPTIONS", ""), /* describeResponse */ ImmutableList.of( "RTSP/1.0 200 OK", - "cseq: 3", - "content-type: application/sdp", - "content-length: 28", + "CSeq: 3", + "Content-Type: application/sdp", + "Content-Length: 28", "", "v=安卓アンドロイド"), /* describeResponse2 */ ImmutableList.of( "RTSP/1.0 200 OK", - "cseq: 4", - "content-type: application/sdp", - "content-length: 73", + "CSeq: 4", + "Content-Type: application/sdp", + "Content-Length: 73", "", "v=安卓アンドロイド\n" + "o=test 2890844526 2890842807 IN IP4 127.0.0.1"), /* setupResponse */ ImmutableList.of( - "RTSP/1.0 200 OK", "cseq: 5", "transport: RTP/AVP/TCP;unicast;interleaved=0-1", "")) + "RTSP/1.0 200 OK", "CSeq: 5", "Transport: RTP/AVP/TCP;unicast;interleaved=0-1", "")) .inOrder(); assertThat(receivedInterleavedData) .containsExactly( diff --git a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMessageUtilTest.java b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMessageUtilTest.java index c0611dddca6..92463f30855 100644 --- a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMessageUtilTest.java +++ b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMessageUtilTest.java @@ -147,10 +147,12 @@ public void parseResponse_with401DescribeResponse_succeeds() { assertThat(response.status).isEqualTo(401); - assertThat(headersMap.keySet()).containsExactly("cseq", "www-authenticate").inOrder(); - assertThat(headersMap).valuesForKey("cseq").containsExactly("3"); + assertThat(headersMap.keySet()) + .containsExactly(RtspHeaders.CSEQ, RtspHeaders.WWW_AUTHENTICATE) + .inOrder(); + assertThat(headersMap).valuesForKey(RtspHeaders.CSEQ).containsExactly("3"); assertThat(headersMap) - .valuesForKey("www-authenticate") + .valuesForKey(RtspHeaders.WWW_AUTHENTICATE) .containsExactly("BASIC realm=\"wow\"", "DIGEST realm=\"wow\", nonce=\"nonce\"") .inOrder(); @@ -221,14 +223,14 @@ public void serialize_setupRequest_succeeds() { List expectedLines = Arrays.asList( "SETUP rtsp://127.0.0.1/test.mkv/track1 RTSP/1.0", - "cseq: 4", - "transport: RTP/AVP;unicast;client_port=65458-65459", + "CSeq: 4", + "Transport: RTP/AVP;unicast;client_port=65458-65459", "", ""); String expectedRtspMessage = "SETUP rtsp://127.0.0.1/test.mkv/track1 RTSP/1.0\r\n" - + "cseq: 4\r\n" - + "transport: RTP/AVP;unicast;client_port=65458-65459\r\n" + + "CSeq: 4\r\n" + + "Transport: RTP/AVP;unicast;client_port=65458-65459\r\n" + "\r\n"; assertThat(messageLines).isEqualTo(expectedLines); @@ -248,21 +250,20 @@ public void serialize_setupResponse_succeeds() { "4", RtspHeaders.TRANSPORT, "RTP/AVP;unicast;client_port=65458-65459;server_port=5354-5355")) - .build(), - /* messageBody= */ ""); + .build()); List messageLines = RtspMessageUtil.serializeResponse(response); List expectedLines = Arrays.asList( "RTSP/1.0 200 OK", - "cseq: 4", - "transport: RTP/AVP;unicast;client_port=65458-65459;server_port=5354-5355", + "CSeq: 4", + "Transport: RTP/AVP;unicast;client_port=65458-65459;server_port=5354-5355", "", ""); String expectedRtspMessage = "RTSP/1.0 200 OK\r\n" - + "cseq: 4\r\n" - + "transport: RTP/AVP;unicast;client_port=65458-65459;server_port=5354-5355\r\n" + + "CSeq: 4\r\n" + + "Transport: RTP/AVP;unicast;client_port=65458-65459;server_port=5354-5355\r\n" + "\r\n"; assertThat(messageLines).isEqualTo(expectedLines); assertThat(RtspMessageUtil.convertMessageToByteArray(messageLines)) @@ -297,10 +298,10 @@ public void serialize_describeResponse_succeeds() { List expectedLines = Arrays.asList( "RTSP/1.0 200 OK", - "cseq: 4", - "content-base: rtsp://127.0.0.1/test.mkv/", - "content-type: application/sdp", - "content-length: 707", + "CSeq: 4", + "Content-Base: rtsp://127.0.0.1/test.mkv/", + "Content-Type: application/sdp", + "Content-Length: 707", "", "v=0\r\n" + "o=- 1606776316530225 1 IN IP4 192.168.2.176\r\n" @@ -314,10 +315,10 @@ public void serialize_describeResponse_succeeds() { String expectedRtspMessage = "RTSP/1.0 200 OK\r\n" - + "cseq: 4\r\n" - + "content-base: rtsp://127.0.0.1/test.mkv/\r\n" - + "content-type: application/sdp\r\n" - + "content-length: 707\r\n" + + "CSeq: 4\r\n" + + "Content-Base: rtsp://127.0.0.1/test.mkv/\r\n" + + "Content-Type: application/sdp\r\n" + + "Content-Length: 707\r\n" + "\r\n" + "v=0\r\n" + "o=- 1606776316530225 1 IN IP4 192.168.2.176\r\n" @@ -338,19 +339,26 @@ public void serialize_describeResponse_succeeds() { public void serialize_failedResponse_succeeds() { RtspResponse response = new RtspResponse( - /* status= */ 454, - new RtspHeaders.Builder().add(RtspHeaders.CSEQ, "4").build(), - /* messageBody= */ ""); + /* status= */ 454, new RtspHeaders.Builder().add(RtspHeaders.CSEQ, "4").build()); List messageLines = RtspMessageUtil.serializeResponse(response); - List expectedLines = Arrays.asList("RTSP/1.0 454 Session Not Found", "cseq: 4", "", ""); - String expectedRtspMessage = "RTSP/1.0 454 Session Not Found\r\n" + "cseq: 4\r\n" + "\r\n"; + List expectedLines = Arrays.asList("RTSP/1.0 454 Session Not Found", "CSeq: 4", "", ""); + String expectedRtspMessage = "RTSP/1.0 454 Session Not Found\r\n" + "CSeq: 4\r\n" + "\r\n"; assertThat(RtspMessageUtil.serializeResponse(response)).isEqualTo(expectedLines); assertThat(RtspMessageUtil.convertMessageToByteArray(messageLines)) .isEqualTo(expectedRtspMessage.getBytes(RtspMessageChannel.CHARSET)); } + @Test + public void parseSessionHeader_withSessionIdContainingSpecialCharacters_succeeds() + throws Exception { + String sessionHeaderString = "610a63df-9b57.4856_97ac$665f+56e9c04"; + RtspMessageUtil.RtspSessionHeader sessionHeader = + RtspMessageUtil.parseSessionHeader(sessionHeaderString); + assertThat(sessionHeader.sessionId).isEqualTo("610a63df-9b57.4856_97ac$665f+56e9c04"); + } + @Test public void removeUserInfo_withUserInfo() { Uri uri = Uri.parse("rtsp://user:pass@foo.bar/foo.mkv"); diff --git a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspPlaybackTest.java b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspPlaybackTest.java new file mode 100644 index 00000000000..e46737d3d72 --- /dev/null +++ b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspPlaybackTest.java @@ -0,0 +1,308 @@ +/* + * 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 com.google.android.exoplayer2.source.rtsp; + +import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull; +import static com.google.common.truth.Truth.assertThat; +import static java.lang.Math.min; + +import android.content.Context; +import android.net.Uri; +import androidx.annotation.Nullable; +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.PlaybackException; +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.Player.Listener; +import com.google.android.exoplayer2.SimpleExoPlayer; +import com.google.android.exoplayer2.robolectric.PlaybackOutput; +import com.google.android.exoplayer2.robolectric.RobolectricUtil; +import com.google.android.exoplayer2.robolectric.ShadowMediaCodecConfig; +import com.google.android.exoplayer2.robolectric.TestPlayerRunHelper; +import com.google.android.exoplayer2.testutil.CapturingRenderersFactory; +import com.google.android.exoplayer2.testutil.DumpFileAsserts; +import com.google.android.exoplayer2.testutil.FakeClock; +import com.google.android.exoplayer2.upstream.BaseDataSource; +import com.google.android.exoplayer2.upstream.DataSpec; +import com.google.android.exoplayer2.util.Clock; +import com.google.android.exoplayer2.util.Util; +import com.google.common.collect.ImmutableList; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicReference; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; + +/** Playback testing for RTSP. */ +@Config(sdk = 29) +@RunWith(AndroidJUnit4.class) +public final class RtspPlaybackTest { + + private static final String SESSION_DESCRIPTION = + "v=0\r\n" + + "o=- 1606776316530225 1 IN IP4 127.0.0.1\r\n" + + "s=Exoplayer test\r\n" + + "t=0 0\r\n"; + + private final Context applicationContext; + private final CapturingRenderersFactory capturingRenderersFactory; + private final Clock clock; + private final FakeUdpDataSourceRtpDataChannel fakeRtpDataChannel; + private final RtpDataChannel.Factory rtpDataChannelFactory; + + private RtpPacketStreamDump aacRtpPacketStreamDump; + // ExoPlayer does not support extracting MP4A-LATM RTP payload at the moment. + private RtpPacketStreamDump mp4aLatmRtpPacketStreamDump; + + /** Creates a new instance. */ + public RtspPlaybackTest() { + applicationContext = ApplicationProvider.getApplicationContext(); + capturingRenderersFactory = new CapturingRenderersFactory(applicationContext); + clock = new FakeClock(/* isAutoAdvancing= */ true); + fakeRtpDataChannel = new FakeUdpDataSourceRtpDataChannel(); + rtpDataChannelFactory = (trackId) -> fakeRtpDataChannel; + } + + @Rule + public ShadowMediaCodecConfig mediaCodecConfig = + ShadowMediaCodecConfig.forAllSupportedMimeTypes(); + + @Before + public void setUp() throws Exception { + aacRtpPacketStreamDump = RtspTestUtils.readRtpPacketStreamDump("media/rtsp/aac-dump.json"); + mp4aLatmRtpPacketStreamDump = + RtspTestUtils.readRtpPacketStreamDump("media/rtsp/mp4a-latm-dump.json"); + } + + @Test + public void prepare_withSupportedTrack_playsTrackUntilEnded() throws Exception { + ResponseProvider responseProvider = + new ResponseProvider( + clock, + ImmutableList.of(aacRtpPacketStreamDump, mp4aLatmRtpPacketStreamDump), + fakeRtpDataChannel); + + try (RtspServer rtspServer = new RtspServer(responseProvider)) { + SimpleExoPlayer player = + createSimpleExoPlayer(rtspServer.startAndGetPortNumber(), rtpDataChannelFactory); + + PlaybackOutput playbackOutput = PlaybackOutput.register(player, capturingRenderersFactory); + player.prepare(); + player.play(); + TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_ENDED); + player.release(); + + // Only setup the supported track (aac). + assertThat(responseProvider.getDumpsForSetUpTracks()).containsExactly(aacRtpPacketStreamDump); + DumpFileAsserts.assertOutput( + applicationContext, playbackOutput, "playbackdumps/rtsp/aac.dump"); + } + } + + @Test + public void prepare_noSupportedTrack_throwsPreparationError() throws Exception { + + try (RtspServer rtspServer = + new RtspServer( + new ResponseProvider( + clock, ImmutableList.of(mp4aLatmRtpPacketStreamDump), fakeRtpDataChannel))) { + SimpleExoPlayer player = + createSimpleExoPlayer(rtspServer.startAndGetPortNumber(), rtpDataChannelFactory); + + AtomicReference playbackError = new AtomicReference<>(); + player.prepare(); + player.addListener( + new Listener() { + @Override + public void onPlayerError(PlaybackException error) { + playbackError.set(error); + } + }); + RobolectricUtil.runMainLooperUntil(() -> playbackError.get() != null); + player.release(); + + assertThat(playbackError.get()) + .hasCauseThat() + .hasMessageThat() + .contains("No playable track."); + } + } + + private SimpleExoPlayer createSimpleExoPlayer( + int serverRtspPortNumber, RtpDataChannel.Factory rtpDataChannelFactory) { + SimpleExoPlayer player = + new SimpleExoPlayer.Builder(applicationContext, capturingRenderersFactory) + .setClock(clock) + .build(); + player.setMediaSource( + new RtspMediaSource( + MediaItem.fromUri(RtspTestUtils.getTestUri(serverRtspPortNumber)), + rtpDataChannelFactory, + "ExoPlayer:PlaybackTest")); + return player; + } + + private static final class ResponseProvider implements RtspServer.ResponseProvider { + + private static final String SESSION_ID = "00000000"; + + private final Clock clock; + private final ArrayList dumpsForSetUpTracks; + private final ImmutableList rtpPacketStreamDumps; + private final RtspMessageChannel.InterleavedBinaryDataListener binaryDataListener; + + private RtpPacketTransmitter packetTransmitter; + + /** + * Creates a new instance. + * + * @param clock The {@link Clock} used in the test. + * @param rtpPacketStreamDumps A list of {@link RtpPacketStreamDump}. + * @param binaryDataListener A {@link RtspMessageChannel.InterleavedBinaryDataListener} to send + * RTP data. + */ + public ResponseProvider( + Clock clock, + List rtpPacketStreamDumps, + RtspMessageChannel.InterleavedBinaryDataListener binaryDataListener) { + this.clock = clock; + this.rtpPacketStreamDumps = ImmutableList.copyOf(rtpPacketStreamDumps); + this.binaryDataListener = binaryDataListener; + dumpsForSetUpTracks = new ArrayList<>(); + } + + /** Returns a list of the received SETUP requests' corresponding {@link RtpPacketStreamDump}. */ + public ImmutableList getDumpsForSetUpTracks() { + return ImmutableList.copyOf(dumpsForSetUpTracks); + } + + // RtspServer.ResponseProvider implementation. Called on the main thread. + + @Override + public RtspResponse getOptionsResponse() { + return new RtspResponse( + /* status= */ 200, + new RtspHeaders.Builder() + .add(RtspHeaders.PUBLIC, "OPTIONS, DESCRIBE, SETUP, PLAY, TEARDOWN") + .build()); + } + + @Override + public RtspResponse getDescribeResponse(Uri requestedUri) { + return RtspTestUtils.newDescribeResponseWithSdpMessage( + SESSION_DESCRIPTION, rtpPacketStreamDumps, requestedUri); + } + + @Override + public RtspResponse getSetupResponse(Uri requestedUri, RtspHeaders headers) { + for (RtpPacketStreamDump rtpPacketStreamDump : rtpPacketStreamDumps) { + if (requestedUri.toString().contains(rtpPacketStreamDump.trackName)) { + dumpsForSetUpTracks.add(rtpPacketStreamDump); + packetTransmitter = new RtpPacketTransmitter(rtpPacketStreamDump, clock); + } + } + + return new RtspResponse( + /* status= */ 200, headers.buildUpon().add(RtspHeaders.SESSION, SESSION_ID).build()); + } + + @Override + public RtspResponse getPlayResponse() { + checkStateNotNull(packetTransmitter); + packetTransmitter.startTransmitting(binaryDataListener); + + return new RtspResponse( + /* status= */ 200, + new RtspHeaders.Builder() + .add(RtspHeaders.RTP_INFO, RtspTestUtils.getRtpInfoForDumps(rtpPacketStreamDumps)) + .build()); + } + } + + private static final class FakeUdpDataSourceRtpDataChannel extends BaseDataSource + implements RtpDataChannel, RtspMessageChannel.InterleavedBinaryDataListener { + + private static final int LOCAL_PORT = 40000; + + private final ConcurrentLinkedQueue packetQueue; + + public FakeUdpDataSourceRtpDataChannel() { + super(/* isNetwork= */ false); + packetQueue = new ConcurrentLinkedQueue<>(); + } + + @Override + public String getTransport() { + return Util.formatInvariant("RTP/AVP;unicast;client_port=%d-%d", LOCAL_PORT, LOCAL_PORT + 1); + } + + @Override + public int getLocalPort() { + return LOCAL_PORT; + } + + @Override + public RtspMessageChannel.InterleavedBinaryDataListener getInterleavedBinaryDataListener() { + return this; + } + + @Override + public void onInterleavedBinaryDataReceived(byte[] data) { + packetQueue.add(data); + } + + @Override + public long open(DataSpec dataSpec) { + return C.LENGTH_UNSET; + } + + @Nullable + @Override + public Uri getUri() { + return null; + } + + @Override + public void close() {} + + @Override + public int read(byte[] buffer, int offset, int length) { + if (length == 0) { + return 0; + } + + @Nullable byte[] data = packetQueue.poll(); + if (data == null) { + return 0; + } + + if (data.length == 0) { + // Empty data signals the end of a packet stream. + return C.RESULT_END_OF_INPUT; + } + + int byteToRead = min(length, data.length); + System.arraycopy(data, /* srcPos= */ 0, buffer, offset, byteToRead); + return byteToRead; + } + } +} diff --git a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspServer.java b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspServer.java index 89c28533544..fe537fc7209 100644 --- a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspServer.java +++ b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspServer.java @@ -17,13 +17,15 @@ import static com.google.android.exoplayer2.source.rtsp.RtspRequest.METHOD_DESCRIBE; import static com.google.android.exoplayer2.source.rtsp.RtspRequest.METHOD_OPTIONS; +import static com.google.android.exoplayer2.source.rtsp.RtspRequest.METHOD_PLAY; +import static com.google.android.exoplayer2.source.rtsp.RtspRequest.METHOD_SETUP; +import static com.google.android.exoplayer2.source.rtsp.RtspRequest.METHOD_TEARDOWN; import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import android.net.Uri; import android.os.Handler; import android.os.Looper; import com.google.android.exoplayer2.util.Util; -import com.google.common.collect.ImmutableMap; import java.io.Closeable; import java.io.IOException; import java.net.InetAddress; @@ -31,31 +33,43 @@ import java.net.Socket; import java.net.SocketException; import java.util.List; -import java.util.Map; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** The RTSP server. */ public final class RtspServer implements Closeable { - private static final String PUBLIC_SUPPORTED_METHODS = "OPTIONS, DESCRIBE"; + /** Provides RTSP response. */ + public interface ResponseProvider { - /** RTSP error Method Not Allowed (RFC2326 Section 7.1.1). */ - private static final int STATUS_OK = 200; + /** Returns an RTSP OPTIONS {@link RtspResponse response}. */ + RtspResponse getOptionsResponse(); - private static final int STATUS_METHOD_NOT_ALLOWED = 405; + /** Returns an RTSP DESCRIBE {@link RtspResponse response}. */ + default RtspResponse getDescribeResponse(Uri requestedUri) { + return RtspTestUtils.RTSP_ERROR_METHOD_NOT_ALLOWED; + } - private static final String SESSION_DESCRIPTION = - "v=0\r\n" - + "o=- 1606776316530225 1 IN IP4 127.0.0.1\r\n" - + "s=Exoplayer test\r\n" - + "t=0 0\r\n" - + "a=range:npt=0-50.46\r\n"; + /** Returns an RTSP SETUP {@link RtspResponse response}. */ + default RtspResponse getSetupResponse(Uri requestedUri, RtspHeaders headers) { + return RtspTestUtils.RTSP_ERROR_METHOD_NOT_ALLOWED; + } + + /** Returns an RTSP PLAY {@link RtspResponse response}. */ + default RtspResponse getPlayResponse() { + return RtspTestUtils.RTSP_ERROR_METHOD_NOT_ALLOWED; + } + + /** Returns an RTSP TEARDOWN {@link RtspResponse response}. */ + default RtspResponse getTearDownResponse() { + return new RtspResponse(/* status= */ 200, RtspHeaders.EMPTY); + } + } private final Thread listenerThread; /** Runs on the thread on which the constructor was called. */ private final Handler mainHandler; - private final RtpPacketStreamDump rtpPacketStreamDump; + private final ResponseProvider responseProvider; private @MonotonicNonNull ServerSocket serverSocket; private @MonotonicNonNull RtspMessageChannel connectedClient; @@ -66,12 +80,14 @@ public final class RtspServer implements Closeable { * Creates a new instance. * *

    The constructor must be called on a {@link Looper} thread. + * + * @param responseProvider A {@link ResponseProvider}. */ - public RtspServer(RtpPacketStreamDump rtpPacketStreamDump) { - this.rtpPacketStreamDump = rtpPacketStreamDump; + public RtspServer(ResponseProvider responseProvider) { listenerThread = new Thread(this::listenToIncomingRtspConnection, "ExoPlayerTest:RtspConnectionMonitor"); mainHandler = Util.createHandlerForCurrentLooper(); + this.responseProvider = responseProvider; } /** @@ -123,54 +139,37 @@ private void handleRtspMessage(List message) { String cSeq = checkNotNull(request.headers.get(RtspHeaders.CSEQ)); switch (request.method) { case METHOD_OPTIONS: - onOptionsRequestReceived(cSeq); + sendResponse(responseProvider.getOptionsResponse(), cSeq); break; case METHOD_DESCRIBE: - onDescribeRequestReceived(request.uri, cSeq); + sendResponse(responseProvider.getDescribeResponse(request.uri), cSeq); break; - default: - sendErrorResponse(STATUS_METHOD_NOT_ALLOWED, cSeq); - } - } + case METHOD_SETUP: + sendResponse(responseProvider.getSetupResponse(request.uri, request.headers), cSeq); + break; - private void onOptionsRequestReceived(String cSeq) { - sendResponseWithCommonHeaders( - /* status= */ STATUS_OK, - /* cSeq= */ cSeq, - /* additionalHeaders= */ ImmutableMap.of(RtspHeaders.PUBLIC, PUBLIC_SUPPORTED_METHODS), - /* messageBody= */ ""); - } + case METHOD_PLAY: + sendResponse(responseProvider.getPlayResponse(), cSeq); + break; - private void onDescribeRequestReceived(Uri requestedUri, String cSeq) { - String sdpMessage = SESSION_DESCRIPTION + rtpPacketStreamDump.mediaDescription + "\r\n"; - sendResponseWithCommonHeaders( - /* status= */ STATUS_OK, - /* cSeq= */ cSeq, - /* additionalHeaders= */ ImmutableMap.of( - RtspHeaders.CONTENT_BASE, requestedUri.toString(), - RtspHeaders.CONTENT_TYPE, "application/sdp", - RtspHeaders.CONTENT_LENGTH, String.valueOf(sdpMessage.length())), - /* messageBody= */ sdpMessage); - } + case METHOD_TEARDOWN: + sendResponse(responseProvider.getTearDownResponse(), cSeq); + break; - private void sendErrorResponse(int status, String cSeq) { - sendResponseWithCommonHeaders( - status, cSeq, /* additionalHeaders= */ ImmutableMap.of(), /* messageBody= */ ""); + default: + sendResponse(RtspTestUtils.RTSP_ERROR_METHOD_NOT_ALLOWED, cSeq); + } } - private void sendResponseWithCommonHeaders( - int status, String cSeq, Map additionalHeaders, String messageBody) { - RtspHeaders.Builder headerBuilder = new RtspHeaders.Builder(); - headerBuilder.add(RtspHeaders.CSEQ, cSeq); - headerBuilder.addAll(additionalHeaders); + private void sendResponse(RtspResponse response, String cSeq) { connectedClient.send( RtspMessageUtil.serializeResponse( new RtspResponse( - /* status= */ status, - /* headers= */ headerBuilder.build(), - /* messageBody= */ messageBody))); + response.status, + response.headers.buildUpon().add(RtspHeaders.CSEQ, cSeq).build(), + response.messageBody))); } } diff --git a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspTestUtils.java b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspTestUtils.java new file mode 100644 index 00000000000..ce0f0c232d4 --- /dev/null +++ b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspTestUtils.java @@ -0,0 +1,87 @@ +/* + * 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 com.google.android.exoplayer2.source.rtsp; + +import android.net.Uri; +import androidx.test.core.app.ApplicationProvider; +import com.google.android.exoplayer2.testutil.TestUtil; +import com.google.android.exoplayer2.util.Util; +import com.google.common.base.Joiner; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** Utility methods for RTSP tests. */ +/* package */ final class RtspTestUtils { + + private static final String TEST_BASE_URI = "rtsp://localhost:%d/test"; + private static final String RTP_TIME_FORMAT = "url=rtsp://localhost/test/%s;seq=%d;rtptime=%d"; + + /** RTSP error Method Not Allowed (RFC2326 Section 7.1.1). */ + public static final RtspResponse RTSP_ERROR_METHOD_NOT_ALLOWED = + new RtspResponse(454, RtspHeaders.EMPTY); + + /** + * Parses and returns an {@link RtpPacketStreamDump} from the file identified by {@code filepath}. + * + *

    See {@link RtpPacketStreamDump#parse} for details on the dump file format. + */ + public static RtpPacketStreamDump readRtpPacketStreamDump(String filepath) throws IOException { + return RtpPacketStreamDump.parse( + TestUtil.getString(ApplicationProvider.getApplicationContext(), filepath)); + } + + /** Returns an {@link RtspResponse} with a SDP message body. */ + public static RtspResponse newDescribeResponseWithSdpMessage( + String sessionDescription, List rtpPacketStreamDumps, Uri requestedUri) { + + StringBuilder sdpMessageBuilder = new StringBuilder(sessionDescription); + for (RtpPacketStreamDump rtpPacketStreamDump : rtpPacketStreamDumps) { + sdpMessageBuilder.append(rtpPacketStreamDump.mediaDescription).append("\r\n"); + } + String sdpMessage = sdpMessageBuilder.toString(); + + return new RtspResponse( + 200, + new RtspHeaders.Builder() + .add(RtspHeaders.CONTENT_BASE, requestedUri.toString()) + .add( + RtspHeaders.CONTENT_LENGTH, + String.valueOf(sdpMessage.getBytes(RtspMessageChannel.CHARSET).length)) + .build(), + /* messageBody= */ sdpMessage); + } + + /** Returns the test RTSP {@link Uri}. */ + public static Uri getTestUri(int serverRtspPortNumber) { + return Uri.parse(Util.formatInvariant(TEST_BASE_URI, serverRtspPortNumber)); + } + + public static String getRtpInfoForDumps(List rtpPacketStreamDumps) { + ArrayList rtpInfos = new ArrayList<>(rtpPacketStreamDumps.size()); + for (RtpPacketStreamDump rtpPacketStreamDump : rtpPacketStreamDumps) { + rtpInfos.add( + Util.formatInvariant( + RTP_TIME_FORMAT, + rtpPacketStreamDump.trackName, + rtpPacketStreamDump.firstSequenceNumber, + rtpPacketStreamDump.firstTimestamp)); + } + return Joiner.on(",").join(rtpInfos); + } + + private RtspTestUtils() {} +} diff --git a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultSsChunkSource.java b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultSsChunkSource.java index b35dc98608e..dd3ad568b43 100644 --- a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultSsChunkSource.java +++ b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultSsChunkSource.java @@ -15,6 +15,8 @@ */ package com.google.android.exoplayer2.source.smoothstreaming; +import static com.google.android.exoplayer2.trackselection.TrackSelectionUtil.createFallbackOptions; + import android.net.Uri; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; @@ -37,6 +39,8 @@ import com.google.android.exoplayer2.trackselection.ExoTrackSelection; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSpec; +import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy; +import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.FallbackSelection; import com.google.android.exoplayer2.upstream.LoaderErrorThrower; import com.google.android.exoplayer2.upstream.TransferListener; import com.google.android.exoplayer2.util.Assertions; @@ -58,7 +62,7 @@ public Factory(DataSource.Factory dataSourceFactory) { public SsChunkSource createChunkSource( LoaderErrorThrower manifestLoaderErrorThrower, SsManifest manifest, - int elementIndex, + int streamElementIndex, ExoTrackSelection trackSelection, @Nullable TransferListener transferListener) { DataSource dataSource = dataSourceFactory.createDataSource(); @@ -66,9 +70,8 @@ public SsChunkSource createChunkSource( dataSource.addTransferListener(transferListener); } return new DefaultSsChunkSource( - manifestLoaderErrorThrower, manifest, elementIndex, trackSelection, dataSource); + manifestLoaderErrorThrower, manifest, streamElementIndex, trackSelection, dataSource); } - } private final LoaderErrorThrower manifestLoaderErrorThrower; @@ -112,9 +115,19 @@ public DefaultSsChunkSource( ? Assertions.checkNotNull(manifest.protectionElement).trackEncryptionBoxes : null; int nalUnitLengthFieldLength = streamElement.type == C.TRACK_TYPE_VIDEO ? 4 : 0; - Track track = new Track(manifestTrackIndex, streamElement.type, streamElement.timescale, - C.TIME_UNSET, manifest.durationUs, format, Track.TRANSFORMATION_NONE, - trackEncryptionBoxes, nalUnitLengthFieldLength, null, null); + Track track = + new Track( + manifestTrackIndex, + streamElement.type, + streamElement.timescale, + C.TIME_UNSET, + manifest.durationUs, + format, + Track.TRANSFORMATION_NONE, + trackEncryptionBoxes, + nalUnitLengthFieldLength, + null, + null); FragmentedMp4Extractor extractor = new FragmentedMp4Extractor( FragmentedMp4Extractor.FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME @@ -146,8 +159,9 @@ public void updateManifest(SsManifest newManifest) { // There's no overlap between the old and new elements because at least one is empty. currentManifestChunkOffset += currentElementChunkCount; } else { - long currentElementEndTimeUs = currentElement.getStartTimeUs(currentElementChunkCount - 1) - + currentElement.getChunkDurationUs(currentElementChunkCount - 1); + long currentElementEndTimeUs = + currentElement.getStartTimeUs(currentElementChunkCount - 1) + + currentElement.getChunkDurationUs(currentElementChunkCount - 1); long newElementStartTimeUs = newElement.getStartTimeUs(0); if (currentElementEndTimeUs <= newElementStartTimeUs) { // There's no overlap between the old and new elements. @@ -272,10 +286,19 @@ public void onChunkLoadCompleted(Chunk chunk) { @Override public boolean onChunkLoadError( - Chunk chunk, boolean cancelable, Exception e, long exclusionDurationMs) { + Chunk chunk, + boolean cancelable, + LoadErrorHandlingPolicy.LoadErrorInfo loadErrorInfo, + LoadErrorHandlingPolicy loadErrorHandlingPolicy) { + @Nullable + FallbackSelection fallbackSelection = + loadErrorHandlingPolicy.getFallbackSelectionFor( + createFallbackOptions(trackSelection), loadErrorInfo); return cancelable - && exclusionDurationMs != C.TIME_UNSET - && trackSelection.blacklist(trackSelection.indexOf(chunk.trackFormat), exclusionDurationMs); + && fallbackSelection != null + && fallbackSelection.type == LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK + && trackSelection.blacklist( + trackSelection.indexOf(chunk.trackFormat), fallbackSelection.exclusionDurationMs); } @Override @@ -325,8 +348,9 @@ private long resolveTimeToLiveEdgeUs(long playbackPositionUs) { StreamElement currentElement = manifest.streamElements[streamElementIndex]; int lastChunkIndex = currentElement.chunkCount - 1; - long lastChunkEndTimeUs = currentElement.getStartTimeUs(lastChunkIndex) - + currentElement.getChunkDurationUs(lastChunkIndex); + long lastChunkEndTimeUs = + currentElement.getStartTimeUs(lastChunkIndex) + + currentElement.getChunkDurationUs(lastChunkIndex); return lastChunkEndTimeUs - playbackPositionUs; } diff --git a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSource.java b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSource.java index da2ffe9006e..cab77cb0725 100644 --- a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSource.java +++ b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSource.java @@ -361,9 +361,7 @@ public int[] getSupportedTypes() { */ public static final long DEFAULT_LIVE_PRESENTATION_DELAY_MS = 30_000; - /** - * The minimum period between manifest refreshes. - */ + /** The minimum period between manifest refreshes. */ private static final int MINIMUM_MANIFEST_REFRESH_PERIOD_MS = 5000; /** * The minimum default start position for live streams, relative to the start of the live window. @@ -426,17 +424,6 @@ private SsMediaSource( // MediaSource implementation. - /** - * @deprecated Use {@link #getMediaItem()} and {@link MediaItem.PlaybackProperties#tag} instead. - */ - @SuppressWarnings("deprecation") - @Deprecated - @Override - @Nullable - public Object getTag() { - return playbackProperties.tag; - } - @Override public MediaItem getMediaItem() { return mediaItem; @@ -484,9 +471,9 @@ public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long star } @Override - public void releasePeriod(MediaPeriod period) { - ((SsMediaPeriod) period).release(); - mediaPeriods.remove(period); + public void releasePeriod(MediaPeriod mediaPeriod) { + ((SsMediaPeriod) mediaPeriod).release(); + mediaPeriods.remove(mediaPeriod); } @Override @@ -636,8 +623,8 @@ private void processManifest() { manifest, mediaItem); } else { - long durationUs = manifest.durationUs != C.TIME_UNSET ? manifest.durationUs - : endTimeUs - startTimeUs; + long durationUs = + manifest.durationUs != C.TIME_UNSET ? manifest.durationUs : endTimeUs - startTimeUs; timeline = new SinglePeriodTimeline( startTimeUs + durationUs, @@ -666,8 +653,9 @@ private void startLoadingManifest() { if (manifestLoader.hasFatalError()) { return; } - ParsingLoadable loadable = new ParsingLoadable<>(manifestDataSource, - manifestUri, C.DATA_TYPE_MANIFEST, manifestParser); + ParsingLoadable loadable = + new ParsingLoadable<>( + manifestDataSource, manifestUri, C.DATA_TYPE_MANIFEST, manifestParser); long elapsedRealtimeMs = manifestLoader.startLoading( loadable, this, loadErrorHandlingPolicy.getMinimumLoadableRetryCount(loadable.type)); @@ -675,5 +663,4 @@ private void startLoadingManifest() { new LoadEventInfo(loadable.loadTaskId, loadable.dataSpec, elapsedRealtimeMs), loadable.type); } - } diff --git a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/manifest/SsManifest.java b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/manifest/SsManifest.java index b91bfc8f675..97e155b379a 100644 --- a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/manifest/SsManifest.java +++ b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/manifest/SsManifest.java @@ -52,9 +52,7 @@ public ProtectionElement(UUID uuid, byte[] data, TrackEncryptionBox[] trackEncry } } - /** - * Represents a StreamIndex element. - */ + /** Represents a StreamIndex element. */ public static class StreamElement { private static final String URL_PLACEHOLDER_START_TIME_1 = "{start time}"; @@ -156,9 +154,22 @@ private StreamElement( * @throws IndexOutOfBoundsException If a key has an invalid index. */ public StreamElement copy(Format[] formats) { - return new StreamElement(baseUri, chunkTemplate, type, subType, timescale, name, maxWidth, - maxHeight, displayWidth, displayHeight, language, formats, chunkStartTimes, - chunkStartTimesUs, lastChunkDurationUs); + return new StreamElement( + baseUri, + chunkTemplate, + type, + subType, + timescale, + name, + maxWidth, + maxHeight, + displayWidth, + displayHeight, + language, + formats, + chunkStartTimes, + chunkStartTimesUs, + lastChunkDurationUs); } /** @@ -188,7 +199,8 @@ public long getStartTimeUs(int chunkIndex) { * @return The duration of the chunk, in microseconds. */ public long getChunkDurationUs(int chunkIndex) { - return (chunkIndex == chunkCount - 1) ? lastChunkDurationUs + return (chunkIndex == chunkCount - 1) + ? lastChunkDurationUs : chunkStartTimesUs[chunkIndex + 1] - chunkStartTimesUs[chunkIndex]; } @@ -205,11 +217,12 @@ public Uri buildRequestUri(int track, int chunkIndex) { Assertions.checkState(chunkIndex < chunkStartTimes.size()); String bitrateString = Integer.toString(formats[track].bitrate); String startTimeString = chunkStartTimes.get(chunkIndex).toString(); - String chunkUrl = chunkTemplate - .replace(URL_PLACEHOLDER_BITRATE_1, bitrateString) - .replace(URL_PLACEHOLDER_BITRATE_2, bitrateString) - .replace(URL_PLACEHOLDER_START_TIME_1, startTimeString) - .replace(URL_PLACEHOLDER_START_TIME_2, startTimeString); + String chunkUrl = + chunkTemplate + .replace(URL_PLACEHOLDER_BITRATE_1, bitrateString) + .replace(URL_PLACEHOLDER_BITRATE_2, bitrateString) + .replace(URL_PLACEHOLDER_START_TIME_1, startTimeString) + .replace(URL_PLACEHOLDER_START_TIME_2, startTimeString); return UriUtil.resolveToUri(baseUri, chunkUrl); } } diff --git a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/manifest/SsManifestParser.java b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/manifest/SsManifestParser.java index 05eb8acc0db..b26e2d41d8d 100644 --- a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/manifest/SsManifestParser.java +++ b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/manifest/SsManifestParser.java @@ -74,24 +74,23 @@ public SsManifest parse(Uri uri, InputStream inputStream) throws IOException { new SmoothStreamingMediaParser(null, uri.toString()); return (SsManifest) smoothStreamingMediaParser.parse(xmlParser); } catch (XmlPullParserException e) { - throw new ParserException(e); + throw ParserException.createForMalformedManifest(/* message= */ null, /* cause= */ e); } } - /** - * Thrown if a required field is missing. - */ + /** Thrown if a required field is missing. */ public static class MissingFieldException extends ParserException { public MissingFieldException(String fieldName) { - super("Missing required field: " + fieldName); + super( + "Missing required field: " + fieldName, + /* cause= */ null, + /* contentIsMalformed= */ true, + C.DATA_TYPE_MANIFEST); } - } - /** - * A base class for parsers that parse components of a smooth streaming manifest. - */ + /** A base class for parsers that parse components of a smooth streaming manifest. */ private abstract static class ElementParser { private final String baseUri; @@ -193,7 +192,7 @@ protected final void putNormalizedAttribute(String key, @Nullable Object value) * provided name, the parent element parser will be queried, and so on up the chain. * * @param key The name of the attribute. - * @return The stashed value, or null if the attribute was not be found. + * @return The stashed value, or null if the attribute was not found. */ @Nullable protected final Object getNormalizedAttribute(String key) { @@ -224,23 +223,17 @@ protected void parseStartTag(XmlPullParser xmlParser) throws ParserException { // Do nothing. } - /** - * @param xmlParser The underlying {@link XmlPullParser} - */ + /** @param xmlParser The underlying {@link XmlPullParser} */ protected void parseText(XmlPullParser xmlParser) { // Do nothing. } - /** - * @param xmlParser The underlying {@link XmlPullParser} - */ + /** @param xmlParser The underlying {@link XmlPullParser} */ protected void parseEndTag(XmlPullParser xmlParser) { // Do nothing. } - /** - * @param parsedChild A parsed child object. - */ + /** @param parsedChild A parsed child object. */ protected void addChild(Object parsedChild) { // Do nothing. } @@ -264,7 +257,7 @@ protected final int parseInt(XmlPullParser parser, String key, int defaultValue) try { return Integer.parseInt(value); } catch (NumberFormatException e) { - throw new ParserException(e); + throw ParserException.createForMalformedManifest(/* message= */ null, /* cause= */ e); } } else { return defaultValue; @@ -277,7 +270,7 @@ protected final int parseRequiredInt(XmlPullParser parser, String key) throws Pa try { return Integer.parseInt(value); } catch (NumberFormatException e) { - throw new ParserException(e); + throw ParserException.createForMalformedManifest(/* message= */ null, /* cause= */ e); } } else { throw new MissingFieldException(key); @@ -291,7 +284,7 @@ protected final long parseLong(XmlPullParser parser, String key, long defaultVal try { return Long.parseLong(value); } catch (NumberFormatException e) { - throw new ParserException(e); + throw ParserException.createForMalformedManifest(/* message= */ null, /* cause= */ e); } } else { return defaultValue; @@ -305,7 +298,7 @@ protected final long parseRequiredLong(XmlPullParser parser, String key) try { return Long.parseLong(value); } catch (NumberFormatException e) { - throw new ParserException(e); + throw ParserException.createForMalformedManifest(/* message= */ null, /* cause= */ e); } } else { throw new MissingFieldException(key); @@ -320,7 +313,6 @@ protected final boolean parseBoolean(XmlPullParser parser, String key, boolean d return defaultValue; } } - } private static class SmoothStreamingMediaParser extends ElementParser { @@ -380,8 +372,10 @@ public Object build() { StreamElement[] streamElementArray = new StreamElement[streamElements.size()]; streamElements.toArray(streamElementArray); if (protectionElement != null) { - DrmInitData drmInitData = new DrmInitData(new SchemeData(protectionElement.uuid, - MimeTypes.VIDEO_MP4, protectionElement.data)); + DrmInitData drmInitData = + new DrmInitData( + new SchemeData( + protectionElement.uuid, MimeTypes.VIDEO_MP4, protectionElement.data)); for (StreamElement streamElement : streamElementArray) { int type = streamElement.type; if (type == C.TRACK_TYPE_VIDEO || type == C.TRACK_TYPE_AUDIO) { @@ -392,10 +386,17 @@ public Object build() { } } } - return new SsManifest(majorVersion, minorVersion, timescale, duration, dvrWindowLength, - lookAheadCount, isLive, protectionElement, streamElementArray); + return new SsManifest( + majorVersion, + minorVersion, + timescale, + duration, + dvrWindowLength, + lookAheadCount, + isLive, + protectionElement, + streamElementArray); } - } private static class ProtectionParser extends ElementParser { @@ -565,7 +566,8 @@ private void parseStreamFragmentStartTag(XmlPullParser parser) throws ParserExce startTime = startTimes.get(chunkIndex - 1) + lastChunkDuration; } else { // We don't have the start time, and we're unable to infer it. - throw new ParserException("Unable to infer start time"); + throw ParserException.createForMalformedManifest( + "Unable to infer start time", /* cause= */ null); } } chunkIndex++; @@ -574,7 +576,8 @@ private void parseStreamFragmentStartTag(XmlPullParser parser) throws ParserExce // Handle repeated chunks. long repeatCount = parseLong(parser, KEY_FRAGMENT_REPEAT_COUNT, 1L); if (repeatCount > 1 && lastChunkDuration == C.TIME_UNSET) { - throw new ParserException("Repeated chunk with unspecified duration"); + throw ParserException.createForMalformedManifest( + "Repeated chunk with unspecified duration", /* cause= */ null); } for (int i = 1; i < repeatCount; i++) { chunkIndex++; @@ -592,6 +595,7 @@ private void parseStreamElementStartTag(XmlPullParser parser) throws ParserExcep } putNormalizedAttribute(KEY_SUB_TYPE, subType); name = parser.getAttributeValue(null, KEY_NAME); + putNormalizedAttribute(KEY_NAME, name); url = parseRequiredString(parser, KEY_URL); maxWidth = parseInt(parser, KEY_MAX_WIDTH, Format.NO_VALUE); maxHeight = parseInt(parser, KEY_MAX_HEIGHT, Format.NO_VALUE); @@ -616,7 +620,8 @@ private int parseType(XmlPullParser parser) throws ParserException { } else if (KEY_TYPE_TEXT.equalsIgnoreCase(value)) { return C.TRACK_TYPE_TEXT; } else { - throw new ParserException("Invalid key value[" + value + "]"); + throw ParserException.createForMalformedManifest( + "Invalid key value[" + value + "]", /* cause= */ null); } } throw new MissingFieldException(KEY_TYPE); @@ -633,10 +638,22 @@ public void addChild(Object child) { public Object build() { Format[] formatArray = new Format[formats.size()]; formats.toArray(formatArray); - return new StreamElement(baseUri, url, type, subType, timescale, name, maxWidth, maxHeight, - displayWidth, displayHeight, language, formatArray, startTimes, lastChunkDuration); + return new StreamElement( + baseUri, + url, + type, + subType, + timescale, + name, + maxWidth, + maxHeight, + displayWidth, + displayHeight, + language, + formatArray, + startTimes, + lastChunkDuration); } - } private static class QualityLevelParser extends ElementParser { @@ -669,8 +686,8 @@ public void parseStartTag(XmlPullParser parser) throws ParserException { @Nullable String sampleMimeType = fourCCToMimeType(parseRequiredString(parser, KEY_FOUR_CC)); int type = (Integer) getNormalizedAttribute(KEY_TYPE); if (type == C.TRACK_TYPE_VIDEO) { - List codecSpecificData = buildCodecSpecificData( - parser.getAttributeValue(null, KEY_CODEC_PRIVATE_DATA)); + List codecSpecificData = + buildCodecSpecificData(parser.getAttributeValue(null, KEY_CODEC_PRIVATE_DATA)); formatBuilder .setContainerMimeType(MimeTypes.VIDEO_MP4) .setWidth(parseRequiredInt(parser, KEY_MAX_WIDTH)) @@ -683,8 +700,8 @@ public void parseStartTag(XmlPullParser parser) throws ParserException { } int channelCount = parseRequiredInt(parser, KEY_CHANNELS); int sampleRate = parseRequiredInt(parser, KEY_SAMPLING_RATE); - List codecSpecificData = buildCodecSpecificData( - parser.getAttributeValue(null, KEY_CODEC_PRIVATE_DATA)); + List codecSpecificData = + buildCodecSpecificData(parser.getAttributeValue(null, KEY_CODEC_PRIVATE_DATA)); if (codecSpecificData.isEmpty() && MimeTypes.AUDIO_AAC.equals(sampleMimeType)) { codecSpecificData = Collections.singletonList( @@ -746,11 +763,15 @@ private static List buildCodecSpecificData(String codecSpecificDataStrin @Nullable private static String fourCCToMimeType(String fourCC) { - if (fourCC.equalsIgnoreCase("H264") || fourCC.equalsIgnoreCase("X264") - || fourCC.equalsIgnoreCase("AVC1") || fourCC.equalsIgnoreCase("DAVC")) { + if (fourCC.equalsIgnoreCase("H264") + || fourCC.equalsIgnoreCase("X264") + || fourCC.equalsIgnoreCase("AVC1") + || fourCC.equalsIgnoreCase("DAVC")) { return MimeTypes.VIDEO_H264; - } else if (fourCC.equalsIgnoreCase("AAC") || fourCC.equalsIgnoreCase("AACL") - || fourCC.equalsIgnoreCase("AACH") || fourCC.equalsIgnoreCase("AACP")) { + } else if (fourCC.equalsIgnoreCase("AAC") + || fourCC.equalsIgnoreCase("AACL") + || fourCC.equalsIgnoreCase("AACH") + || fourCC.equalsIgnoreCase("AACP")) { return MimeTypes.AUDIO_AAC; } else if (fourCC.equalsIgnoreCase("TTML") || fourCC.equalsIgnoreCase("DFXP")) { return MimeTypes.APPLICATION_TTML; @@ -769,7 +790,5 @@ private static String fourCCToMimeType(String fourCC) { } return null; } - } - } diff --git a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/offline/SsDownloader.java b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/offline/SsDownloader.java index 998820de4ba..416e4b92a68 100644 --- a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/offline/SsDownloader.java +++ b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/offline/SsDownloader.java @@ -17,10 +17,8 @@ import static com.google.android.exoplayer2.util.Assertions.checkNotNull; -import android.net.Uri; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.offline.SegmentDownloader; -import com.google.android.exoplayer2.offline.StreamKey; import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest; import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest.StreamElement; import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifestParser; @@ -61,16 +59,6 @@ */ public final class SsDownloader extends SegmentDownloader { - /** - * @deprecated Use {@link #SsDownloader(MediaItem, CacheDataSource.Factory, Executor)} instead. - */ - @SuppressWarnings("deprecation") - @Deprecated - public SsDownloader( - Uri manifestUri, List streamKeys, CacheDataSource.Factory cacheDataSourceFactory) { - this(manifestUri, streamKeys, cacheDataSourceFactory, Runnable::run); - } - /** * Creates an instance. * @@ -82,21 +70,6 @@ public SsDownloader(MediaItem mediaItem, CacheDataSource.Factory cacheDataSource this(mediaItem, cacheDataSourceFactory, Runnable::run); } - /** - * @deprecated Use {@link #SsDownloader(MediaItem, CacheDataSource.Factory, Executor)} instead. - */ - @Deprecated - public SsDownloader( - Uri manifestUri, - List streamKeys, - CacheDataSource.Factory cacheDataSourceFactory, - Executor executor) { - this( - new MediaItem.Builder().setUri(manifestUri).setStreamKeys(streamKeys).build(), - cacheDataSourceFactory, - executor); - } - /** * Creates an instance. * @@ -156,5 +129,4 @@ protected List getSegments( } return segments; } - } diff --git a/library/smoothstreaming/src/test/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSourceTest.java b/library/smoothstreaming/src/test/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSourceTest.java index 1f28d2263bf..7e6f659ce72 100644 --- a/library/smoothstreaming/src/test/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSourceTest.java +++ b/library/smoothstreaming/src/test/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSourceTest.java @@ -18,7 +18,6 @@ import static com.google.android.exoplayer2.util.Util.castNonNull; import static com.google.common.truth.Truth.assertThat; -import androidx.annotation.Nullable; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.offline.StreamKey; @@ -67,34 +66,6 @@ public void factorySetTag_nonNullMediaItemTag_doesNotOverrideMediaItemTag() { assertThat(ssMediaItem.playbackProperties.tag).isEqualTo(mediaItemTag); } - // Tests backwards compatibility - @SuppressWarnings("deprecation") - @Test - public void factorySetTag_setsDeprecatedMediaSourceTag() { - Object tag = new Object(); - MediaItem mediaItem = MediaItem.fromUri("http://www.google.com"); - SsMediaSource.Factory factory = - new SsMediaSource.Factory(new FileDataSource.Factory()).setTag(tag); - - @Nullable Object mediaSourceTag = factory.createMediaSource(mediaItem).getTag(); - - assertThat(mediaSourceTag).isEqualTo(tag); - } - - // Tests backwards compatibility - @SuppressWarnings("deprecation") - @Test - public void factoryCreateMediaSource_setsDeprecatedMediaSourceTag() { - Object tag = new Object(); - MediaItem mediaItem = - new MediaItem.Builder().setUri("http://www.google.com").setTag(tag).build(); - SsMediaSource.Factory factory = new SsMediaSource.Factory(new FileDataSource.Factory()); - - @Nullable Object mediaSourceTag = factory.createMediaSource(mediaItem).getTag(); - - assertThat(mediaSourceTag).isEqualTo(tag); - } - // Tests backwards compatibility @SuppressWarnings("deprecation") @Test diff --git a/library/smoothstreaming/src/test/java/com/google/android/exoplayer2/source/smoothstreaming/manifest/SsManifestParserTest.java b/library/smoothstreaming/src/test/java/com/google/android/exoplayer2/source/smoothstreaming/manifest/SsManifestParserTest.java index e5a7ee5addd..320db6bad29 100644 --- a/library/smoothstreaming/src/test/java/com/google/android/exoplayer2/source/smoothstreaming/manifest/SsManifestParserTest.java +++ b/library/smoothstreaming/src/test/java/com/google/android/exoplayer2/source/smoothstreaming/manifest/SsManifestParserTest.java @@ -15,11 +15,12 @@ */ package com.google.android.exoplayer2.source.smoothstreaming.manifest; +import static com.google.common.truth.Truth.assertThat; + import android.net.Uri; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.testutil.TestUtil; -import java.io.IOException; import org.junit.Test; import org.junit.runner.RunWith; @@ -32,7 +33,7 @@ public final class SsManifestParserTest { /** Simple test to ensure the sample manifests parse without any exceptions being thrown. */ @Test - public void parseSmoothStreamingManifest() throws IOException { + public void parseSmoothStreamingManifest() throws Exception { SsManifestParser parser = new SsManifestParser(); parser.parse( Uri.parse("https://example.com/test.ismc"), @@ -41,4 +42,15 @@ public void parseSmoothStreamingManifest() throws IOException { Uri.parse("https://example.com/test.ismc"), TestUtil.getInputStream(ApplicationProvider.getApplicationContext(), SAMPLE_ISMC_2)); } + + @Test + public void parse_populatesFormatLabelWithStreamIndexName() throws Exception { + SsManifestParser parser = new SsManifestParser(); + SsManifest ssManifest = + parser.parse( + Uri.parse("https://example.com/test.ismc"), + TestUtil.getInputStream(ApplicationProvider.getApplicationContext(), SAMPLE_ISMC_1)); + + assertThat(ssManifest.streamElements[0].formats[0].label).isEqualTo("video"); + } } diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/MuxerWrapper.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/MuxerWrapper.java index 2e9710dc15c..e400630d5ea 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/MuxerWrapper.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/MuxerWrapper.java @@ -201,5 +201,4 @@ private boolean canWriteSampleOfType(int trackType) { } return trackTimeUs - minTrackTimeUs <= MAX_TRACK_WRITE_AHEAD_US; } - } diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Transformer.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Transformer.java index 1ca5be3570e..aa0437daba8 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Transformer.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Transformer.java @@ -37,8 +37,8 @@ import androidx.annotation.VisibleForTesting; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.DefaultLoadControl; -import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.RenderersFactory; @@ -639,7 +639,7 @@ public void onTracksChanged( } @Override - public void onPlayerError(EventTime eventTime, ExoPlaybackException error) { + public void onPlayerError(EventTime eventTime, PlaybackException error) { handleTransformationEnded(error); } diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerAudioRenderer.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerAudioRenderer.java index c5be7dc0299..6198054aa29 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerAudioRenderer.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerAudioRenderer.java @@ -28,6 +28,7 @@ import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.FormatHolder; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.audio.AudioProcessor; import com.google.android.exoplayer2.audio.AudioProcessor.AudioFormat; import com.google.android.exoplayer2.audio.SonicAudioProcessor; @@ -345,7 +346,8 @@ private boolean ensureEncoderAndAudioProcessingConfigured() throws ExoPlaybackEx outputAudioFormat = sonicAudioProcessor.configure(outputAudioFormat); flushSonicAndSetSpeed(currentSpeed); } catch (AudioProcessor.UnhandledAudioFormatException e) { - throw createRendererException(e); + // TODO(internal b/192864511): Assign an adequate error code. + throw createRendererException(e, PlaybackException.ERROR_CODE_UNSPECIFIED); } } try { @@ -358,7 +360,8 @@ private boolean ensureEncoderAndAudioProcessingConfigured() throws ExoPlaybackEx .setAverageBitrate(DEFAULT_ENCODER_BITRATE) .build()); } catch (IOException e) { - throw createRendererException(e); + // TODO(internal b/192864511): Assign an adequate error code. + throw createRendererException(e, PlaybackException.ERROR_CODE_UNSPECIFIED); } encoderInputAudioFormat = outputAudioFormat; return true; @@ -382,7 +385,8 @@ private boolean ensureDecoderConfigured() throws ExoPlaybackException { try { decoder = MediaCodecAdapterWrapper.createForAudioDecoding(inputFormat); } catch (IOException e) { - throw createRendererException(e); + // TODO (internal b/184262323): Assign an adequate error code. + throw createRendererException(e, PlaybackException.ERROR_CODE_UNSPECIFIED); } speedProvider = new SegmentSpeedProvider(inputFormat); currentSpeed = speedProvider.getSpeed(0); @@ -405,9 +409,15 @@ private void flushSonicAndSetSpeed(float speed) { sonicAudioProcessor.flush(); } - private ExoPlaybackException createRendererException(Throwable cause) { + private ExoPlaybackException createRendererException(Throwable cause, int errorCode) { return ExoPlaybackException.createForRenderer( - cause, TAG, getIndex(), inputFormat, /* rendererFormatSupport= */ C.FORMAT_HANDLED); + cause, + TAG, + getIndex(), + inputFormat, + /* rendererFormatSupport= */ C.FORMAT_HANDLED, + /* isRecoverable= */ false, + errorCode); } private static long getBufferDurationUs(long bytesWritten, int bytesPerFrame, int sampleRate) { diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerBaseRenderer.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerBaseRenderer.java index 33888226b88..40d6690a302 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerBaseRenderer.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerBaseRenderer.java @@ -16,7 +16,6 @@ package com.google.android.exoplayer2.transformer; - import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import com.google.android.exoplayer2.BaseRenderer; diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/SefSlowMotionVideoSampleTransformerTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/SefSlowMotionVideoSampleTransformerTest.java index a63db831fc8..c29289e4c8c 100644 --- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/SefSlowMotionVideoSampleTransformerTest.java +++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/SefSlowMotionVideoSampleTransformerTest.java @@ -236,9 +236,7 @@ private static SlowMotionData.Segment createSegment( /** Creates a {@link Format} for an SEF slow motion video track. */ private static Format createSefSlowMotionFormat( - int captureFrameRate, - int inputMaxLayer, - List segments) { + int captureFrameRate, int inputMaxLayer, List segments) { SmtaMetadataEntry smtaMetadataEntry = new SmtaMetadataEntry(captureFrameRate, /* svcTemporalLayerCount= */ inputMaxLayer + 1); SlowMotionData slowMotionData = new SlowMotionData(segments); @@ -259,9 +257,7 @@ private static Format createSefSlowMotionFormat( * @return The output layers. */ private static List getKeptOutputLayers( - SefSlowMotionVideoSampleTransformer sampleTransformer, - int[] layerSequence, - int frameCount) { + SefSlowMotionVideoSampleTransformer sampleTransformer, int[] layerSequence, int frameCount) { List outputLayers = new ArrayList<>(); for (int i = 0; i < frameCount; i++) { int layer = layerSequence[i % layerSequence.length]; @@ -286,9 +282,7 @@ private static List getKeptOutputLayers( * @return The frame output times, in microseconds. */ private static List getOutputTimesUs( - SefSlowMotionVideoSampleTransformer sampleTransformer, - int[] layerSequence, - int frameCount) { + SefSlowMotionVideoSampleTransformer sampleTransformer, int[] layerSequence, int frameCount) { List outputTimesUs = new ArrayList<>(); for (int i = 0; i < frameCount; i++) { int layer = layerSequence[i % layerSequence.length]; diff --git a/library/ui/proguard-rules.txt b/library/ui/proguard-rules.txt index f18183637b0..2e6ea621dbb 100644 --- a/library/ui/proguard-rules.txt +++ b/library/ui/proguard-rules.txt @@ -1,5 +1,15 @@ # Proguard rules specific to the UI module. +# Constructor method accessed via reflection in StyledPlayerView and PlayerView +-dontnote com.google.android.exoplayer2.video.spherical.SphericalGLSurfaceView +-keepclassmembers class com.google.android.exoplayer2.video.spherical.SphericalGLSurfaceView { + (android.content.Context); +} +-dontnote com.google.android.exoplayer2.video.VideoDecoderGLSurfaceView +-keepclassmembers class com.google.android.exoplayer2.video.VideoDecoderGLSurfaceView { + (android.content.Context); +} + # Constructor method accessed via reflection in TrackSelectionDialogBuilder -dontnote androidx.appcompat.app.AlertDialog.Builder -keepclassmembers class androidx.appcompat.app.AlertDialog$Builder { diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/AspectRatioFrameLayout.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/AspectRatioFrameLayout.java index cc0435be88c..e2428948fa6 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/AspectRatioFrameLayout.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/AspectRatioFrameLayout.java @@ -44,7 +44,6 @@ void onAspectRatioUpdated( float targetAspectRatio, float naturalAspectRatio, boolean aspectRatioMismatch); } - // LINT.IfChange /** * Resize modes for {@link AspectRatioFrameLayout}. One of {@link #RESIZE_MODE_FIT}, {@link * #RESIZE_MODE_FIXED_WIDTH}, {@link #RESIZE_MODE_FIXED_HEIGHT}, {@link #RESIZE_MODE_FILL} or @@ -61,9 +60,7 @@ void onAspectRatioUpdated( }) public @interface ResizeMode {} - /** - * Either the width or height is decreased to obtain the desired aspect ratio. - */ + /** Either the width or height is decreased to obtain the desired aspect ratio. */ public static final int RESIZE_MODE_FIT = 0; /** * The width is fixed and the height is increased or decreased to obtain the desired aspect ratio. @@ -73,15 +70,10 @@ void onAspectRatioUpdated( * The height is fixed and the width is increased or decreased to obtain the desired aspect ratio. */ public static final int RESIZE_MODE_FIXED_HEIGHT = 2; - /** - * The specified aspect ratio is ignored. - */ + /** The specified aspect ratio is ignored. */ public static final int RESIZE_MODE_FILL = 3; - /** - * Either the width or height is increased to obtain the desired aspect ratio. - */ + /** Either the width or height is increased to obtain the desired aspect ratio. */ public static final int RESIZE_MODE_ZOOM = 4; - // LINT.ThenChange(../../../../../../res/values/attrs.xml) /** * The {@link FrameLayout} will not resize itself if the fractional difference between its natural @@ -109,8 +101,10 @@ public AspectRatioFrameLayout(Context context, @Nullable AttributeSet attrs) { super(context, attrs); resizeMode = RESIZE_MODE_FIT; if (attrs != null) { - TypedArray a = context.getTheme().obtainStyledAttributes(attrs, - R.styleable.AspectRatioFrameLayout, 0, 0); + TypedArray a = + context + .getTheme() + .obtainStyledAttributes(attrs, R.styleable.AspectRatioFrameLayout, 0, 0); try { resizeMode = a.getInt(R.styleable.AspectRatioFrameLayout_resize_mode, RESIZE_MODE_FIT); } finally { @@ -204,7 +198,8 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { break; } aspectRatioUpdateDispatcher.scheduleUpdate(videoAspectRatio, viewAspectRatio, true); - super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), + super.onMeasure( + MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); } diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/CaptionStyleCompat.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/CaptionStyleCompat.java index 22c8ca78b11..dc96abb31d9 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/CaptionStyleCompat.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/CaptionStyleCompat.java @@ -45,30 +45,18 @@ public final class CaptionStyleCompat { EDGE_TYPE_DEPRESSED }) public @interface EdgeType {} - /** - * Edge type value specifying no character edges. - */ + /** Edge type value specifying no character edges. */ public static final int EDGE_TYPE_NONE = 0; - /** - * Edge type value specifying uniformly outlined character edges. - */ + /** Edge type value specifying uniformly outlined character edges. */ public static final int EDGE_TYPE_OUTLINE = 1; - /** - * Edge type value specifying drop-shadowed character edges. - */ + /** Edge type value specifying drop-shadowed character edges. */ public static final int EDGE_TYPE_DROP_SHADOW = 2; - /** - * Edge type value specifying raised bevel character edges. - */ + /** Edge type value specifying raised bevel character edges. */ public static final int EDGE_TYPE_RAISED = 3; - /** - * Edge type value specifying depressed bevel character edges. - */ + /** Edge type value specifying depressed bevel character edges. */ public static final int EDGE_TYPE_DEPRESSED = 4; - /** - * Use color setting specified by the track and fallback to default caption style. - */ + /** Use color setting specified by the track and fallback to default caption style. */ public static final int USE_TRACK_COLOR_SETTINGS = 1; /** Default caption style. */ @@ -81,36 +69,29 @@ public final class CaptionStyleCompat { Color.WHITE, /* typeface= */ null); - /** - * The preferred foreground color. - */ + /** The preferred foreground color. */ public final int foregroundColor; - /** - * The preferred background color. - */ + /** The preferred background color. */ public final int backgroundColor; - /** - * The preferred window color. - */ + /** The preferred window color. */ public final int windowColor; /** * The preferred edge type. One of: + * *

      - *
    • {@link #EDGE_TYPE_NONE} - *
    • {@link #EDGE_TYPE_OUTLINE} - *
    • {@link #EDGE_TYPE_DROP_SHADOW} - *
    • {@link #EDGE_TYPE_RAISED} - *
    • {@link #EDGE_TYPE_DEPRESSED} + *
    • {@link #EDGE_TYPE_NONE} + *
    • {@link #EDGE_TYPE_OUTLINE} + *
    • {@link #EDGE_TYPE_DROP_SHADOW} + *
    • {@link #EDGE_TYPE_RAISED} + *
    • {@link #EDGE_TYPE_DEPRESSED} *
    */ @EdgeType public final int edgeType; - /** - * The preferred edge color, if using an edge type other than {@link #EDGE_TYPE_NONE}. - */ + /** The preferred edge color, if using an edge type other than {@link #EDGE_TYPE_NONE}. */ public final int edgeColor; /** The preferred typeface, or {@code null} if unspecified. */ @@ -162,8 +143,12 @@ public CaptionStyleCompat( private static CaptionStyleCompat createFromCaptionStyleV19( CaptioningManager.CaptionStyle captionStyle) { return new CaptionStyleCompat( - captionStyle.foregroundColor, captionStyle.backgroundColor, Color.TRANSPARENT, - captionStyle.edgeType, captionStyle.edgeColor, captionStyle.getTypeface()); + captionStyle.foregroundColor, + captionStyle.backgroundColor, + Color.TRANSPARENT, + captionStyle.edgeType, + captionStyle.edgeColor, + captionStyle.getTypeface()); } @RequiresApi(21) @@ -178,5 +163,4 @@ private static CaptionStyleCompat createFromCaptionStyleV21( captionStyle.hasEdgeColor() ? captionStyle.edgeColor : DEFAULT.edgeColor, captionStyle.getTypeface()); } - } diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultMediaDescriptionAdapter.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultMediaDescriptionAdapter.java new file mode 100644 index 00000000000..629a8c06210 --- /dev/null +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultMediaDescriptionAdapter.java @@ -0,0 +1,84 @@ +/* + * 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 com.google.android.exoplayer2.ui; + +import android.app.PendingIntent; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.text.TextUtils; +import androidx.annotation.Nullable; +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.ui.PlayerNotificationManager.BitmapCallback; +import com.google.android.exoplayer2.ui.PlayerNotificationManager.MediaDescriptionAdapter; + +/** + * Default implementation of {@link MediaDescriptionAdapter}. + * + *

    Uses values from the {@link Player#getMediaMetadata() player mediaMetadata} to populate the + * notification. + */ +public final class DefaultMediaDescriptionAdapter implements MediaDescriptionAdapter { + + @Nullable private final PendingIntent pendingIntent; + + /** + * Creates a default {@link MediaDescriptionAdapter}. + * + * @param pendingIntent The {@link PendingIntent} to be returned from {@link + * #createCurrentContentIntent(Player)}, or null if no intent should be fired. + */ + public DefaultMediaDescriptionAdapter(@Nullable PendingIntent pendingIntent) { + this.pendingIntent = pendingIntent; + } + + @Override + public CharSequence getCurrentContentTitle(Player player) { + @Nullable CharSequence displayTitle = player.getMediaMetadata().displayTitle; + if (!TextUtils.isEmpty(displayTitle)) { + return displayTitle; + } + + @Nullable CharSequence title = player.getMediaMetadata().title; + return title != null ? title : ""; + } + + @Nullable + @Override + public PendingIntent createCurrentContentIntent(Player player) { + return pendingIntent; + } + + @Nullable + @Override + public CharSequence getCurrentContentText(Player player) { + @Nullable CharSequence artist = player.getMediaMetadata().artist; + if (!TextUtils.isEmpty(artist)) { + return artist; + } + + return player.getMediaMetadata().albumArtist; + } + + @Nullable + @Override + public Bitmap getCurrentLargeIcon(Player player, BitmapCallback callback) { + @Nullable byte[] data = player.getMediaMetadata().artworkData; + if (data == null) { + return null; + } + return BitmapFactory.decodeByteArray(data, /* offset= */ 0, data.length); + } +} diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultTimeBar.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultTimeBar.java index ce041cba4eb..2b0dce52d09 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultTimeBar.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultTimeBar.java @@ -51,7 +51,7 @@ * *

    A DefaultTimeBar can be customized by setting attributes, as outlined below. * - *

    Attributes

    + *

    Attributes

    * * The following attributes can be set on a DefaultTimeBar when used in a layout XML file: * @@ -152,12 +152,10 @@ public class DefaultTimeBar extends View implements TimeBar { /** Default color for played ad markers. */ public static final int DEFAULT_PLAYED_AD_MARKER_COLOR = 0x33FFFF00; - // LINT.IfChange /** Vertical gravity for progress bar to be located at the center in the view. */ public static final int BAR_GRAVITY_CENTER = 0; /** Vertical gravity for progress bar to be located at the bottom in the view. */ public static final int BAR_GRAVITY_BOTTOM = 1; - // LINT.ThenChange(../../../../../../../../../ui/src/main/res/values/attrs.xml) /** The threshold in dps above the bar at which touch events trigger fine scrub mode. */ private static final int FINE_SCRUB_Y_THRESHOLD_DP = -50; @@ -245,7 +243,7 @@ public DefaultTimeBar( } // Suppress warnings due to usage of View methods in the constructor. - @SuppressWarnings("nullness:method.invocation.invalid") + @SuppressWarnings("nullness:method.invocation") public DefaultTimeBar( Context context, @Nullable AttributeSet attrs, @@ -291,19 +289,24 @@ public DefaultTimeBar( defaultTouchTargetHeight = Math.max(scrubberDrawable.getMinimumHeight(), defaultTouchTargetHeight); } - barHeight = a.getDimensionPixelSize(R.styleable.DefaultTimeBar_bar_height, - defaultBarHeight); - touchTargetHeight = a.getDimensionPixelSize(R.styleable.DefaultTimeBar_touch_target_height, - defaultTouchTargetHeight); + barHeight = + a.getDimensionPixelSize(R.styleable.DefaultTimeBar_bar_height, defaultBarHeight); + touchTargetHeight = + a.getDimensionPixelSize( + R.styleable.DefaultTimeBar_touch_target_height, defaultTouchTargetHeight); barGravity = a.getInt(R.styleable.DefaultTimeBar_bar_gravity, BAR_GRAVITY_CENTER); - adMarkerWidth = a.getDimensionPixelSize(R.styleable.DefaultTimeBar_ad_marker_width, - defaultAdMarkerWidth); - scrubberEnabledSize = a.getDimensionPixelSize( - R.styleable.DefaultTimeBar_scrubber_enabled_size, defaultScrubberEnabledSize); - scrubberDisabledSize = a.getDimensionPixelSize( - R.styleable.DefaultTimeBar_scrubber_disabled_size, defaultScrubberDisabledSize); - scrubberDraggedSize = a.getDimensionPixelSize( - R.styleable.DefaultTimeBar_scrubber_dragged_size, defaultScrubberDraggedSize); + adMarkerWidth = + a.getDimensionPixelSize( + R.styleable.DefaultTimeBar_ad_marker_width, defaultAdMarkerWidth); + scrubberEnabledSize = + a.getDimensionPixelSize( + R.styleable.DefaultTimeBar_scrubber_enabled_size, defaultScrubberEnabledSize); + scrubberDisabledSize = + a.getDimensionPixelSize( + R.styleable.DefaultTimeBar_scrubber_disabled_size, defaultScrubberDisabledSize); + scrubberDraggedSize = + a.getDimensionPixelSize( + R.styleable.DefaultTimeBar_scrubber_dragged_size, defaultScrubberDraggedSize); int playedColor = a.getInt(R.styleable.DefaultTimeBar_played_color, DEFAULT_PLAYED_COLOR); int scrubberColor = a.getInt(R.styleable.DefaultTimeBar_scrubber_color, DEFAULT_SCRUBBER_COLOR); @@ -311,8 +314,8 @@ public DefaultTimeBar( a.getInt(R.styleable.DefaultTimeBar_buffered_color, DEFAULT_BUFFERED_COLOR); int unplayedColor = a.getInt(R.styleable.DefaultTimeBar_unplayed_color, DEFAULT_UNPLAYED_COLOR); - int adMarkerColor = a.getInt(R.styleable.DefaultTimeBar_ad_marker_color, - DEFAULT_AD_MARKER_COLOR); + int adMarkerColor = + a.getInt(R.styleable.DefaultTimeBar_ad_marker_color, DEFAULT_AD_MARKER_COLOR); int playedAdMarkerColor = a.getInt( R.styleable.DefaultTimeBar_played_ad_marker_color, DEFAULT_PLAYED_AD_MARKER_COLOR); @@ -538,10 +541,10 @@ public long getPreferredUpdateDelay() { } @Override - public void setAdGroupTimesMs(@Nullable long[] adGroupTimesMs, @Nullable boolean[] playedAdGroups, - int adGroupCount) { - Assertions.checkArgument(adGroupCount == 0 - || (adGroupTimesMs != null && playedAdGroups != null)); + public void setAdGroupTimesMs( + @Nullable long[] adGroupTimesMs, @Nullable boolean[] playedAdGroups, int adGroupCount) { + Assertions.checkArgument( + adGroupCount == 0 || (adGroupTimesMs != null && playedAdGroups != null)); this.adGroupCount = adGroupCount; this.adGroupTimesMs = adGroupTimesMs; this.playedAdGroups = playedAdGroups; @@ -668,8 +671,12 @@ public void jumpDrawablesToCurrentState() { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); - int height = heightMode == MeasureSpec.UNSPECIFIED ? touchTargetHeight - : heightMode == MeasureSpec.EXACTLY ? heightSize : Math.min(touchTargetHeight, heightSize); + int height = + heightMode == MeasureSpec.UNSPECIFIED + ? touchTargetHeight + : heightMode == MeasureSpec.EXACTLY + ? heightSize + : Math.min(touchTargetHeight, heightSize); setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), height); updateDrawableState(); } @@ -889,8 +896,9 @@ private void drawTimeBar(Canvas canvas) { long adGroupTimeMs = Util.constrainValue(adGroupTimesMs[i], 0, duration); int markerPositionOffset = (int) (progressBar.width() * adGroupTimeMs / duration) - adMarkerOffset; - int markerLeft = progressBar.left + Math.min(progressBar.width() - adMarkerWidth, - Math.max(0, markerPositionOffset)); + int markerLeft = + progressBar.left + + Math.min(progressBar.width() - adMarkerWidth, Math.max(0, markerPositionOffset)); Paint paint = playedAdGroups[i] ? playedAdMarkerPaint : adMarkerPaint; canvas.drawRect(markerLeft, barTop, markerLeft + adMarkerWidth, barBottom, paint); } @@ -903,8 +911,10 @@ private void drawPlayhead(Canvas canvas) { int playheadX = Util.constrainValue(scrubberBar.right, scrubberBar.left, progressBar.right); int playheadY = scrubberBar.centerY(); if (scrubberDrawable == null) { - int scrubberSize = (scrubbing || isFocused()) ? scrubberDraggedSize - : (isEnabled() ? scrubberEnabledSize : scrubberDisabledSize); + int scrubberSize = + (scrubbing || isFocused()) + ? scrubberDraggedSize + : (isEnabled() ? scrubberEnabledSize : scrubberDisabledSize); int playheadRadius = (int) ((scrubberSize * scrubberScale) / 2); canvas.drawCircle(playheadX, playheadY, playheadRadius, scrubberPaint); } else { @@ -920,7 +930,8 @@ private void drawPlayhead(Canvas canvas) { } private void updateDrawableState() { - if (scrubberDrawable != null && scrubberDrawable.isStateful() + if (scrubberDrawable != null + && scrubberDrawable.isStateful() && scrubberDrawable.setState(getDrawableState())) { invalidate(); } @@ -944,7 +955,8 @@ private String getProgressText() { private long getPositionIncrement() { return keyTimeIncrement == C.TIME_UNSET - ? (duration == C.TIME_UNSET ? 0 : (duration / keyCountIncrement)) : keyTimeIncrement; + ? (duration == C.TIME_UNSET ? 0 : (duration / keyCountIncrement)) + : keyTimeIncrement; } private boolean setDrawableLayoutDirection(Drawable drawable) { diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java index e4a88c083e1..dd8a6d212f8 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java @@ -15,9 +15,11 @@ */ package com.google.android.exoplayer2.ui; -import static com.google.android.exoplayer2.Player.COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM; -import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM; -import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_BACK; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_FORWARD; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_IN_CURRENT_WINDOW; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_NEXT; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_PREVIOUS; import static com.google.android.exoplayer2.Player.EVENT_IS_PLAYING_CHANGED; import static com.google.android.exoplayer2.Player.EVENT_PLAYBACK_STATE_CHANGED; import static com.google.android.exoplayer2.Player.EVENT_PLAY_WHEN_READY_CHANGED; @@ -45,12 +47,12 @@ import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ControlDispatcher; -import com.google.android.exoplayer2.DefaultControlDispatcher; import com.google.android.exoplayer2.ExoPlayerLibraryInfo; -import com.google.android.exoplayer2.PlaybackPreparer; +import com.google.android.exoplayer2.ForwardingPlayer; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player.Events; import com.google.android.exoplayer2.Player.State; +import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.RepeatModeUtil; @@ -67,7 +69,7 @@ * methods), overriding drawables, overriding the view's layout file, or by specifying a custom view * layout file. * - *

    Attributes

    + *

    Attributes

    * * The following attributes can be set on a PlayerControlView when used in a layout XML file: * @@ -99,17 +101,6 @@ *
  • Corresponding method: {@link #setShowNextButton(boolean)} *
  • Default: true * - *
  • {@code rewind_increment} - The duration of the rewind applied when the user taps the - * rewind button, in milliseconds. Use zero to disable the rewind button. - *
      - *
    • Corresponding method: {@link #setControlDispatcher(ControlDispatcher)} - *
    • Default: {@link DefaultControlDispatcher#DEFAULT_REWIND_MS} - *
    - *
  • {@code fastforward_increment} - Like {@code rewind_increment}, but for fast forward. - *
      - *
    • Corresponding method: {@link #setControlDispatcher(ControlDispatcher)} - *
    • Default: {@link DefaultControlDispatcher#DEFAULT_FAST_FORWARD_MS} - *
    *
  • {@code repeat_toggle_modes} - A flagged enumeration value specifying which repeat * mode toggle options are enabled. Valid values are: {@code none}, {@code one}, {@code all}, * or {@code one|all}. @@ -139,7 +130,7 @@ * layout is overridden to specify a custom {@code exo_progress} (see below). * * - *

    Overriding drawables

    + *

    Overriding drawables

    * * The drawables used by PlayerControlView (with its default layout file) can be overridden by * drawables with the same names defined in your application. The drawables that can be overridden @@ -163,7 +154,7 @@ *
  • {@code exo_controls_vr} - The VR icon. * * - *

    Overriding the layout file

    + *

    Overriding the layout file

    * * To customize the layout of PlayerControlView throughout your app, or just for certain * configurations, you can define {@code exo_player_control_view.xml} layout files in your @@ -242,7 +233,7 @@ *

    All child views are optional and so can be omitted if not required, however where defined they * must be of the expected type. * - *

    Specifying a custom layout file

    + *

    Specifying a custom layout file

    * * Defining your own {@code exo_player_control_view.xml} is useful to customize the layout of * PlayerControlView throughout your application. It's also possible to customize the layout for a @@ -329,7 +320,6 @@ public interface ProgressUpdateListener { @Nullable private Player player; private com.google.android.exoplayer2.ControlDispatcher controlDispatcher; @Nullable private ProgressUpdateListener progressUpdateListener; - @Nullable private PlaybackPreparer playbackPreparer; private boolean isAttachedToWindow; private boolean showMultiWindowTimeBar; @@ -363,9 +353,9 @@ public PlayerControlView(Context context, @Nullable AttributeSet attrs, int defS } @SuppressWarnings({ - "nullness:argument.type.incompatible", - "nullness:method.invocation.invalid", - "nullness:methodref.receiver.bound.invalid" + "nullness:argument", + "nullness:method.invocation", + "nullness:methodref.receiver.bound" }) public PlayerControlView( Context context, @@ -383,17 +373,12 @@ public PlayerControlView( showPreviousButton = true; showNextButton = true; showShuffleButton = false; - int rewindMs = DefaultControlDispatcher.DEFAULT_REWIND_MS; - int fastForwardMs = DefaultControlDispatcher.DEFAULT_FAST_FORWARD_MS; if (playbackAttrs != null) { TypedArray a = context .getTheme() .obtainStyledAttributes(playbackAttrs, R.styleable.PlayerControlView, 0, 0); try { - rewindMs = a.getInt(R.styleable.PlayerControlView_rewind_increment, rewindMs); - fastForwardMs = - a.getInt(R.styleable.PlayerControlView_fastforward_increment, fastForwardMs); showTimeoutMs = a.getInt(R.styleable.PlayerControlView_show_timeout, showTimeoutMs); controllerLayoutId = a.getResourceId(R.styleable.PlayerControlView_controller_layout_id, controllerLayoutId); @@ -427,8 +412,7 @@ public PlayerControlView( extraAdGroupTimesMs = new long[0]; extraPlayedAdGroups = new boolean[0]; componentListener = new ComponentListener(); - controlDispatcher = - new com.google.android.exoplayer2.DefaultControlDispatcher(fastForwardMs, rewindMs); + controlDispatcher = new com.google.android.exoplayer2.DefaultControlDispatcher(); updateProgressAction = this::updateProgress; hideAction = this::hide; @@ -617,24 +601,11 @@ public void setProgressUpdateListener(@Nullable ProgressUpdateListener listener) } /** - * @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} instead. The view calls {@link - * ControlDispatcher#dispatchPrepare(Player)} instead of {@link - * PlaybackPreparer#preparePlayback()}. The {@link DefaultControlDispatcher} that the view - * uses by default, calls {@link Player#prepare()}. If you wish to customize this behaviour, - * you can provide a custom implementation of {@link - * ControlDispatcher#dispatchPrepare(Player)}. + * @deprecated Use a {@link ForwardingPlayer} and pass it to {@link #setPlayer(Player)} instead. + * You can also customize some operations when configuring the player (for example by using + * {@link SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)}). */ - @SuppressWarnings("deprecation") @Deprecated - public void setPlaybackPreparer(@Nullable PlaybackPreparer playbackPreparer) { - this.playbackPreparer = playbackPreparer; - } - - /** - * Sets the {@link com.google.android.exoplayer2.ControlDispatcher}. - * - * @param controlDispatcher The {@link com.google.android.exoplayer2.ControlDispatcher}. - */ public void setControlDispatcher(ControlDispatcher controlDispatcher) { if (this.controlDispatcher != controlDispatcher) { this.controlDispatcher = controlDispatcher; @@ -682,32 +653,6 @@ public void setShowNextButton(boolean showNextButton) { updateNavigation(); } - /** - * @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} with {@link - * DefaultControlDispatcher#DefaultControlDispatcher(long, long)}. - */ - @SuppressWarnings("deprecation") - @Deprecated - public void setRewindIncrementMs(int rewindMs) { - if (controlDispatcher instanceof DefaultControlDispatcher) { - ((DefaultControlDispatcher) controlDispatcher).setRewindIncrementMs(rewindMs); - updateNavigation(); - } - } - - /** - * @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} with {@link - * DefaultControlDispatcher#DefaultControlDispatcher(long, long)}. - */ - @SuppressWarnings("deprecation") - @Deprecated - public void setFastForwardIncrementMs(int fastForwardMs) { - if (controlDispatcher instanceof DefaultControlDispatcher) { - ((DefaultControlDispatcher) controlDispatcher).setFastForwardIncrementMs(fastForwardMs); - updateNavigation(); - } - } - /** * Returns the playback controls timeout. The playback controls are automatically hidden after * this duration of time has elapsed without user input. @@ -911,21 +856,14 @@ private void updateNavigation() { boolean enableFastForward = false; boolean enableNext = false; if (player != null) { - Timeline timeline = player.getCurrentTimeline(); - if (!timeline.isEmpty() && !player.isPlayingAd()) { - boolean isSeekable = player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM); - timeline.getWindow(player.getCurrentWindowIndex(), window); - enableSeeking = isSeekable; - enablePrevious = - isSeekable - || !window.isLive() - || player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); - enableRewind = isSeekable && controlDispatcher.isRewindEnabled(); - enableFastForward = isSeekable && controlDispatcher.isFastForwardEnabled(); - enableNext = - (window.isLive() && window.isDynamic) - || player.isCommandAvailable(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); - } + enableSeeking = player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_WINDOW); + enablePrevious = player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS); + enableRewind = + player.isCommandAvailable(COMMAND_SEEK_BACK) && controlDispatcher.isRewindEnabled(); + enableFastForward = + player.isCommandAvailable(COMMAND_SEEK_FORWARD) + && controlDispatcher.isFastForwardEnabled(); + enableNext = player.isCommandAvailable(COMMAND_SEEK_TO_NEXT); } updateButton(showPreviousButton, enablePrevious, previousButton); @@ -1024,8 +962,9 @@ private void updateTimeline() { } for (int j = window.firstPeriodIndex; j <= window.lastPeriodIndex; j++) { timeline.getPeriod(j, period); - int periodAdGroupCount = period.getAdGroupCount(); - for (int adGroupIndex = 0; adGroupIndex < periodAdGroupCount; adGroupIndex++) { + int removedGroups = period.getRemovedAdGroupCount(); + int totalGroups = period.getAdGroupCount(); + for (int adGroupIndex = removedGroups; adGroupIndex < totalGroups; adGroupIndex++) { long adGroupTimeInPeriodUs = period.getAdGroupTimeUs(adGroupIndex); if (adGroupTimeInPeriodUs == C.TIME_END_OF_SOURCE) { if (period.durationUs == C.TIME_UNSET) { @@ -1269,11 +1208,7 @@ private void dispatchPlayPause(Player player) { private void dispatchPlay(Player player) { @State int state = player.getPlaybackState(); if (state == Player.STATE_IDLE) { - if (playbackPreparer != null) { - playbackPreparer.preparePlayback(); - } else { - controlDispatcher.dispatchPrepare(player); - } + controlDispatcher.dispatchPrepare(player); } else if (state == Player.STATE_ENDED) { seekTo(player, player.getCurrentWindowIndex(), C.TIME_UNSET); } @@ -1323,30 +1258,7 @@ private static boolean canShowMultiWindowTimeBar(Timeline timeline, Timeline.Win } private final class ComponentListener - implements Player.EventListener, TimeBar.OnScrubListener, OnClickListener { - - @Override - public void onScrubStart(TimeBar timeBar, long position) { - scrubbing = true; - if (positionView != null) { - positionView.setText(Util.getStringForTime(formatBuilder, formatter, position)); - } - } - - @Override - public void onScrubMove(TimeBar timeBar, long position) { - if (positionView != null) { - positionView.setText(Util.getStringForTime(formatBuilder, formatter, position)); - } - } - - @Override - public void onScrubStop(TimeBar timeBar, long position, boolean canceled) { - scrubbing = false; - if (!canceled && player != null) { - seekToTimeBarPosition(player, position); - } - } + implements Player.Listener, TimeBar.OnScrubListener, OnClickListener { @Override public void onEvents(Player player, Events events) { @@ -1375,6 +1287,29 @@ public void onEvents(Player player, Events events) { } } + @Override + public void onScrubStart(TimeBar timeBar, long position) { + scrubbing = true; + if (positionView != null) { + positionView.setText(Util.getStringForTime(formatBuilder, formatter, position)); + } + } + + @Override + public void onScrubMove(TimeBar timeBar, long position) { + if (positionView != null) { + positionView.setText(Util.getStringForTime(formatBuilder, formatter, position)); + } + } + + @Override + public void onScrubStop(TimeBar timeBar, long position, boolean canceled) { + scrubbing = false; + if (!canceled && player != null) { + seekToTimeBarPosition(player, position); + } + } + @Override public void onClick(View view) { Player player = PlayerControlView.this.player; diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerNotificationManager.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerNotificationManager.java index f59a2115043..53d989d9d6d 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerNotificationManager.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerNotificationManager.java @@ -15,10 +15,12 @@ */ package com.google.android.exoplayer2.ui; -import static com.google.android.exoplayer2.Player.COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM; -import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM; -import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_BACK; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_FORWARD; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_NEXT; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_PREVIOUS; import static com.google.android.exoplayer2.Player.EVENT_IS_PLAYING_CHANGED; +import static com.google.android.exoplayer2.Player.EVENT_MEDIA_METADATA_CHANGED; import static com.google.android.exoplayer2.Player.EVENT_PLAYBACK_PARAMETERS_CHANGED; import static com.google.android.exoplayer2.Player.EVENT_PLAYBACK_STATE_CHANGED; import static com.google.android.exoplayer2.Player.EVENT_PLAY_WHEN_READY_CHANGED; @@ -45,16 +47,15 @@ import androidx.annotation.DrawableRes; import androidx.annotation.IntDef; import androidx.annotation.Nullable; -import androidx.annotation.StringRes; import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; import androidx.media.app.NotificationCompat.MediaStyle; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ControlDispatcher; import com.google.android.exoplayer2.DefaultControlDispatcher; -import com.google.android.exoplayer2.PlaybackPreparer; +import com.google.android.exoplayer2.ForwardingPlayer; import com.google.android.exoplayer2.Player; -import com.google.android.exoplayer2.Timeline; +import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.util.NotificationUtil; import com.google.android.exoplayer2.util.Util; import java.lang.annotation.Documented; @@ -77,7 +78,7 @@ *

    If the player is released it must be removed from the manager by calling {@code * setPlayer(null)}. * - *

    Action customization

    + *

    Action customization

    * * Playback actions can be included or omitted as follows: * @@ -87,17 +88,29 @@ *
  • Corresponding setter: {@link #setUsePlayPauseActions(boolean)} *
  • Default: {@code true} * - *
  • {@code rewindIncrementMs} - Sets the rewind increment. If set to zero the rewind - * action is not used. + *
  • {@code useRewindAction} - Sets whether the rewind action is used. *
      - *
    • Corresponding setter: {@link #setControlDispatcher(ControlDispatcher)} - *
    • Default: {@link DefaultControlDispatcher#DEFAULT_REWIND_MS} (5000) + *
    • Corresponding setter: {@link #setUseRewindAction(boolean)} + *
    • Default: {@code true} + *
    + *
  • {@code useRewindActionInCompactView} - If {@code useRewindAction} is {@code true}, + * sets whether the rewind action is also used in compact view (including the lock screen + * notification). Else does nothing. + *
      + *
    • Corresponding setter: {@link #setUseRewindActionInCompactView(boolean)} + *
    • Default: {@code false} *
    - *
  • {@code fastForwardIncrementMs} - Sets the fast forward increment. If set to zero the - * fast forward action is not used. + *
  • {@code useFastForwardAction} - Sets whether the fast forward action is used. *
      - *
    • Corresponding setter: {@link #setControlDispatcher(ControlDispatcher)} - *
    • Default: {@link DefaultControlDispatcher#DEFAULT_FAST_FORWARD_MS} (15000) + *
    • Corresponding setter: {@link #setUseFastForwardAction(boolean)} + *
    • Default: {@code true} + *
    + *
  • {@code useFastForwardActionInCompactView} - If {@code useFastForwardAction} is + * {@code true}, sets whether the fast forward action is also used in compact view (including + * the lock screen notification). Else does nothing. + *
      + *
    • Corresponding setter: {@link #setUseFastForwardActionInCompactView(boolean)} + *
    • Default: {@code false} *
    *
  • {@code usePreviousAction} - Whether the previous action is used. *
      @@ -130,7 +143,7 @@ *
    * * - *

    Overriding drawables

    + *

    Overriding drawables

    * * The drawables used by PlayerNotificationManager can be overridden by drawables with the same * names defined in your application. The drawables that can be overridden are: @@ -166,6 +179,7 @@ public interface MediaDescriptionAdapter { *

    See {@link NotificationCompat.Builder#setContentTitle(CharSequence)}. * * @param player The {@link Player} for which a notification is being built. + * @return The content title for the current media item. */ CharSequence getCurrentContentTitle(Player player); @@ -175,6 +189,7 @@ public interface MediaDescriptionAdapter { *

    See {@link NotificationCompat.Builder#setContentIntent(PendingIntent)}. * * @param player The {@link Player} for which a notification is being built. + * @return The content intent for the current media item, or null if no intent should be fired. */ @Nullable PendingIntent createCurrentContentIntent(Player player); @@ -185,6 +200,8 @@ public interface MediaDescriptionAdapter { *

    See {@link NotificationCompat.Builder#setContentText(CharSequence)}. * * @param player The {@link Player} for which a notification is being built. + * @return The content text for the current media item, or null if no context text should be + * displayed. */ @Nullable CharSequence getCurrentContentText(Player player); @@ -195,6 +212,8 @@ public interface MediaDescriptionAdapter { *

    See {@link NotificationCompat.Builder#setSubText(CharSequence)}. * * @param player The {@link Player} for which a notification is being built. + * @return The content subtext for the current media item, or null if no subtext should be + * displayed. */ @Nullable default CharSequence getCurrentSubText(Player player) { @@ -213,6 +232,8 @@ default CharSequence getCurrentSubText(Player player) { * * @param player The {@link Player} for which a notification is being built. * @param callback A {@link BitmapCallback} to provide a {@link Bitmap} asynchronously. + * @return The large icon for the current media item, or null if the icon will be returned + * through the {@link BitmapCallback} or if no icon should be displayed. */ @Nullable Bitmap getCurrentLargeIcon(Player player, BitmapCallback callback); @@ -289,10 +310,10 @@ public static class Builder { private final Context context; private final int notificationId; private final String channelId; - private final MediaDescriptionAdapter mediaDescriptionAdapter; @Nullable private NotificationListener notificationListener; @Nullable private CustomActionReceiver customActionReceiver; + private MediaDescriptionAdapter mediaDescriptionAdapter; private int channelNameResourceId; private int channelDescriptionResourceId; private int channelImportance; @@ -307,24 +328,33 @@ public static class Builder { @Nullable private String groupKey; /** - * Creates an instance. - * - * @param context The {@link Context}. - * @param notificationId The id of the notification to be posted. Must be greater than 0. - * @param channelId The id of the notification channel. - * @param mediaDescriptionAdapter The {@link MediaDescriptionAdapter} to be used. + * @deprecated Use {@link #Builder(Context, int, String)} instead, then call {@link + * #setMediaDescriptionAdapter(MediaDescriptionAdapter)}. */ + @Deprecated public Builder( Context context, int notificationId, String channelId, MediaDescriptionAdapter mediaDescriptionAdapter) { + this(context, notificationId, channelId); + this.mediaDescriptionAdapter = mediaDescriptionAdapter; + } + + /** + * Creates an instance. + * + * @param context The {@link Context}. + * @param notificationId The id of the notification to be posted. Must be greater than 0. + * @param channelId The id of the notification channel. + */ + public Builder(Context context, int notificationId, String channelId) { checkArgument(notificationId > 0); this.context = context; this.notificationId = notificationId; this.channelId = channelId; - this.mediaDescriptionAdapter = mediaDescriptionAdapter; channelImportance = NotificationUtil.IMPORTANCE_LOW; + mediaDescriptionAdapter = new DefaultMediaDescriptionAdapter(/* pendingIntent= */ null); smallIconResourceId = R.drawable.exo_notification_small_icon; playActionIconResourceId = R.drawable.exo_notification_play; pauseActionIconResourceId = R.drawable.exo_notification_pause; @@ -511,6 +541,18 @@ public Builder setGroup(String groupKey) { return this; } + /** + * The {@link MediaDescriptionAdapter} to be queried for the notification contents. + * + *

    The default is {@link DefaultMediaDescriptionAdapter} with no {@link PendingIntent} + * + * @return This builder. + */ + public Builder setMediaDescriptionAdapter(MediaDescriptionAdapter mediaDescriptionAdapter) { + this.mediaDescriptionAdapter = mediaDescriptionAdapter; + return this; + } + /** Builds the {@link PlayerNotificationManager}. */ public PlayerNotificationManager build() { if (channelNameResourceId != 0) { @@ -521,6 +563,7 @@ public PlayerNotificationManager build() { channelDescriptionResourceId, channelImportance); } + return new PlayerNotificationManager( context, channelId, @@ -630,18 +673,16 @@ public void onBitmap(final Bitmap bitmap) { private final Handler mainHandler; private final NotificationManagerCompat notificationManager; private final IntentFilter intentFilter; - private final Player.EventListener playerListener; + private final Player.Listener playerListener; private final NotificationBroadcastReceiver notificationBroadcastReceiver; private final Map playbackActions; private final Map customActions; private final PendingIntent dismissPendingIntent; private final int instanceId; - private final Timeline.Window window; @Nullable private NotificationCompat.Builder builder; @Nullable private List builderActions; @Nullable private Player player; - @Nullable private PlaybackPreparer playbackPreparer; private ControlDispatcher controlDispatcher; private boolean isNotificationStarted; private int currentNotificationTag; @@ -650,6 +691,10 @@ public void onBitmap(final Bitmap bitmap) { private boolean useNextAction; private boolean usePreviousActionInCompactView; private boolean useNextActionInCompactView; + private boolean useRewindAction; + private boolean useFastForwardAction; + private boolean useRewindActionInCompactView; + private boolean useFastForwardActionInCompactView; private boolean usePlayPauseActions; private boolean useStopAction; private int badgeIconType; @@ -662,152 +707,6 @@ public void onBitmap(final Bitmap bitmap) { private boolean useChronometer; @Nullable private String groupKey; - /** @deprecated Use the {@link Builder} instead. */ - @SuppressWarnings("deprecation") - @Deprecated - public static PlayerNotificationManager createWithNotificationChannel( - Context context, - String channelId, - @StringRes int channelName, - int notificationId, - MediaDescriptionAdapter mediaDescriptionAdapter) { - return createWithNotificationChannel( - context, - channelId, - channelName, - /* channelDescription= */ 0, - notificationId, - mediaDescriptionAdapter); - } - - /** @deprecated Use the {@link Builder} instead. */ - @Deprecated - public static PlayerNotificationManager createWithNotificationChannel( - Context context, - String channelId, - @StringRes int channelName, - @StringRes int channelDescription, - int notificationId, - MediaDescriptionAdapter mediaDescriptionAdapter) { - NotificationUtil.createNotificationChannel( - context, channelId, channelName, channelDescription, NotificationUtil.IMPORTANCE_LOW); - return new PlayerNotificationManager( - context, channelId, notificationId, mediaDescriptionAdapter); - } - - /** @deprecated Use the {@link Builder} instead. */ - @Deprecated - public static PlayerNotificationManager createWithNotificationChannel( - Context context, - String channelId, - @StringRes int channelName, - int notificationId, - MediaDescriptionAdapter mediaDescriptionAdapter, - @Nullable NotificationListener notificationListener) { - return createWithNotificationChannel( - context, - channelId, - channelName, - /* channelDescription= */ 0, - notificationId, - mediaDescriptionAdapter, - notificationListener); - } - - /** @deprecated Use the {@link Builder} instead. */ - @Deprecated - public static PlayerNotificationManager createWithNotificationChannel( - Context context, - String channelId, - @StringRes int channelName, - @StringRes int channelDescription, - int notificationId, - MediaDescriptionAdapter mediaDescriptionAdapter, - @Nullable NotificationListener notificationListener) { - NotificationUtil.createNotificationChannel( - context, channelId, channelName, channelDescription, NotificationUtil.IMPORTANCE_LOW); - return new PlayerNotificationManager( - context, channelId, notificationId, mediaDescriptionAdapter, notificationListener); - } - - /** @deprecated Use the {@link Builder} instead. */ - @Deprecated - public PlayerNotificationManager( - Context context, - String channelId, - int notificationId, - MediaDescriptionAdapter mediaDescriptionAdapter) { - this( - context, - channelId, - notificationId, - mediaDescriptionAdapter, - /* notificationListener= */ null, - /* customActionReceiver */ null); - } - - /** @deprecated Use the {@link Builder} instead. */ - @Deprecated - public PlayerNotificationManager( - Context context, - String channelId, - int notificationId, - MediaDescriptionAdapter mediaDescriptionAdapter, - @Nullable NotificationListener notificationListener) { - this( - context, - channelId, - notificationId, - mediaDescriptionAdapter, - notificationListener, - /* customActionReceiver= */ null); - } - - /** @deprecated Use the {@link Builder} instead. */ - @SuppressWarnings("deprecation") - @Deprecated - public PlayerNotificationManager( - Context context, - String channelId, - int notificationId, - MediaDescriptionAdapter mediaDescriptionAdapter, - @Nullable CustomActionReceiver customActionReceiver) { - this( - context, - channelId, - notificationId, - mediaDescriptionAdapter, - /* notificationListener= */ null, - customActionReceiver); - } - - /** @deprecated Use the {@link Builder} instead. */ - @Deprecated - public PlayerNotificationManager( - Context context, - String channelId, - int notificationId, - MediaDescriptionAdapter mediaDescriptionAdapter, - @Nullable NotificationListener notificationListener, - @Nullable CustomActionReceiver customActionReceiver) { - this( - context, - channelId, - notificationId, - mediaDescriptionAdapter, - notificationListener, - customActionReceiver, - R.drawable.exo_notification_small_icon, - R.drawable.exo_notification_play, - R.drawable.exo_notification_pause, - R.drawable.exo_notification_stop, - R.drawable.exo_notification_rewind, - R.drawable.exo_notification_fastforward, - R.drawable.exo_notification_previous, - R.drawable.exo_notification_next, - null); - } - private PlayerNotificationManager( Context context, String channelId, @@ -834,12 +733,11 @@ private PlayerNotificationManager( this.smallIconResourceId = smallIconResourceId; this.groupKey = groupKey; controlDispatcher = new DefaultControlDispatcher(); - window = new Timeline.Window(); instanceId = instanceIdCounter++; // This fails the nullness checker because handleMessage() is 'called' while `this` is still // @UnderInitialization. No tasks are scheduled on mainHandler before the constructor completes, // so this is safe and we can suppress the warning. - @SuppressWarnings("nullness:methodref.receiver.bound.invalid") + @SuppressWarnings("nullness:methodref.receiver.bound") Handler mainHandler = Util.createHandler(Looper.getMainLooper(), this::handleMessage); this.mainHandler = mainHandler; notificationManager = NotificationManagerCompat.from(context); @@ -849,6 +747,8 @@ private PlayerNotificationManager( usePreviousAction = true; useNextAction = true; usePlayPauseActions = true; + useRewindAction = true; + useFastForwardAction = true; colorized = true; useChronometer = true; color = Color.TRANSPARENT; @@ -917,25 +817,13 @@ public final void setPlayer(@Nullable Player player) { } /** - * @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} instead. The manager calls - * {@link ControlDispatcher#dispatchPrepare(Player)} instead of {@link - * PlaybackPreparer#preparePlayback()}. The {@link DefaultControlDispatcher} that this manager - * uses by default, calls {@link Player#prepare()}. If you wish to intercept or customize this - * behaviour, you can provide a custom implementation of {@link - * ControlDispatcher#dispatchPrepare(Player)} and pass it to {@link - * #setControlDispatcher(ControlDispatcher)}. + * @deprecated Use a {@link ForwardingPlayer} and pass it to {@link #setPlayer(Player)} instead. + * You can also customize some operations when configuring the player (for example by using + * {@link SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)}), or configure whether the + * rewind and fast forward actions should be used with {{@link #setUseRewindAction(boolean)}} + * and {@link #setUseFastForwardAction(boolean)}. */ - @SuppressWarnings("deprecation") @Deprecated - public void setPlaybackPreparer(@Nullable PlaybackPreparer playbackPreparer) { - this.playbackPreparer = playbackPreparer; - } - - /** - * Sets the {@link ControlDispatcher}. - * - * @param controlDispatcher The {@link ControlDispatcher}. - */ public final void setControlDispatcher(ControlDispatcher controlDispatcher) { if (this.controlDispatcher != controlDispatcher) { this.controlDispatcher = controlDispatcher; @@ -943,32 +831,6 @@ public final void setControlDispatcher(ControlDispatcher controlDispatcher) { } } - /** - * @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} with {@link - * DefaultControlDispatcher#DefaultControlDispatcher(long, long)}. - */ - @SuppressWarnings("deprecation") - @Deprecated - public final void setFastForwardIncrementMs(long fastForwardMs) { - if (controlDispatcher instanceof DefaultControlDispatcher) { - ((DefaultControlDispatcher) controlDispatcher).setFastForwardIncrementMs(fastForwardMs); - invalidate(); - } - } - - /** - * @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} with {@link - * DefaultControlDispatcher#DefaultControlDispatcher(long, long)}. - */ - @SuppressWarnings("deprecation") - @Deprecated - public final void setRewindIncrementMs(long rewindMs) { - if (controlDispatcher instanceof DefaultControlDispatcher) { - ((DefaultControlDispatcher) controlDispatcher).setRewindIncrementMs(rewindMs); - invalidate(); - } - } - /** * Sets whether the next action should be used. * @@ -993,28 +855,22 @@ public void setUsePreviousAction(boolean usePreviousAction) { } } - /** - * Sets whether the navigation actions should be used. - * - * @param useNavigationActions Whether to use navigation actions. - * @deprecated Use {@link #setUseNextAction(boolean)} and {@link #setUsePreviousAction(boolean)}. - */ - @Deprecated - public final void setUseNavigationActions(boolean useNavigationActions) { - setUseNextAction(useNavigationActions); - setUsePreviousAction(useNavigationActions); - } - /** * If {@link #setUseNextAction useNextAction} is {@code true}, sets whether the next action should * also be used in compact view. Has no effect if {@link #setUseNextAction useNextAction} is * {@code false}. * + *

    If set to {@code true}, {@link #setUseFastForwardActionInCompactView(boolean) + * setUseFastForwardActionInCompactView} is set to false. + * * @param useNextActionInCompactView Whether to use the next action in compact view. */ public void setUseNextActionInCompactView(boolean useNextActionInCompactView) { if (this.useNextActionInCompactView != useNextActionInCompactView) { this.useNextActionInCompactView = useNextActionInCompactView; + if (useNextActionInCompactView) { + useFastForwardActionInCompactView = false; + } invalidate(); } } @@ -1024,29 +880,82 @@ public void setUseNextActionInCompactView(boolean useNextActionInCompactView) { * action should also be used in compact view. Has no effect if {@link #setUsePreviousAction * usePreviousAction} is {@code false}. * + *

    If set to {@code true}, {@link #setUseRewindActionInCompactView(boolean) + * setUseRewindActionInCompactView} is set to false. + * * @param usePreviousActionInCompactView Whether to use the previous action in compact view. */ public void setUsePreviousActionInCompactView(boolean usePreviousActionInCompactView) { if (this.usePreviousActionInCompactView != usePreviousActionInCompactView) { this.usePreviousActionInCompactView = usePreviousActionInCompactView; + if (usePreviousActionInCompactView) { + useRewindActionInCompactView = false; + } invalidate(); } } /** - * If {@link #setUseNavigationActions useNavigationActions} is {@code true}, sets whether - * navigation actions should also be used in compact view. Has no effect if {@link - * #setUseNavigationActions useNavigationActions} is {@code false}. + * Sets whether the fast forward action should be used. * - * @param useNavigationActionsInCompactView Whether to use navigation actions in compact view. - * @deprecated Use {@link #setUseNextActionInCompactView(boolean)} and {@link - * #setUsePreviousActionInCompactView(boolean)} instead. + * @param useFastForwardAction Whether to use the fast forward action. */ - @Deprecated - public final void setUseNavigationActionsInCompactView( - boolean useNavigationActionsInCompactView) { - setUseNextActionInCompactView(useNavigationActionsInCompactView); - setUsePreviousActionInCompactView(useNavigationActionsInCompactView); + public void setUseFastForwardAction(boolean useFastForwardAction) { + if (this.useFastForwardAction != useFastForwardAction) { + this.useFastForwardAction = useFastForwardAction; + invalidate(); + } + } + + /** + * Sets whether the rewind action should be used. + * + * @param useRewindAction Whether to use the rewind action. + */ + public void setUseRewindAction(boolean useRewindAction) { + if (this.useRewindAction != useRewindAction) { + this.useRewindAction = useRewindAction; + invalidate(); + } + } + + /** + * Sets whether the fast forward action should also be used in compact view. Has no effect if + * {@link #ACTION_FAST_FORWARD} is not enabled, for instance if the media is not seekable. + * + *

    If set to {@code true}, {@link #setUseNextActionInCompactView(boolean) + * setUseNextActionInCompactView} is set to false. + * + * @param useFastForwardActionInCompactView Whether to use the fast forward action in compact + * view. + */ + public void setUseFastForwardActionInCompactView(boolean useFastForwardActionInCompactView) { + if (this.useFastForwardActionInCompactView != useFastForwardActionInCompactView) { + this.useFastForwardActionInCompactView = useFastForwardActionInCompactView; + if (useFastForwardActionInCompactView) { + useNextActionInCompactView = false; + } + invalidate(); + } + } + + /** + * Sets whether the rewind action should also be used in compact view. Has no effect if {@link + * #ACTION_REWIND} is not enabled, for instance if the media is not seekable. + * + *

    If set to {@code true}, {@link #setUsePreviousActionInCompactView(boolean) + * setUsePreviousActionInCompactView} is set to false. + * + * @param useRewindActionInCompactView Whether to use the rewind action in compact view. + */ + public void setUseRewindActionInCompactView(boolean useRewindActionInCompactView) { + if (this.useRewindActionInCompactView != useRewindActionInCompactView) { + this.useRewindActionInCompactView = useRewindActionInCompactView; + if (useRewindActionInCompactView) { + usePreviousActionInCompactView = false; + } + invalidate(); + } } /** @@ -1158,8 +1067,8 @@ public final void setColor(int color) { *

    See {@link NotificationCompat.Builder#setPriority(int)}. * *

    To set the priority for API levels above 25, you can create your own {@link - * NotificationChannel} with a given importance level and pass the id of the channel to the {@link - * #PlayerNotificationManager(Context, String, int, MediaDescriptionAdapter) constructor}. + * NotificationChannel} with a given importance level and pass the id of the channel to {@link + * Builder#Builder(Context, int, String, MediaDescriptionAdapter)}. * * @param priority The priority which can be one of {@link NotificationCompat#PRIORITY_DEFAULT}, * {@link NotificationCompat#PRIORITY_MAX}, {@link NotificationCompat#PRIORITY_HIGH}, {@link @@ -1413,30 +1322,18 @@ protected NotificationCompat.Builder createNotification( * action name is ignored. */ protected List getActions(Player player) { - boolean enablePrevious = false; - boolean enableRewind = false; - boolean enableFastForward = false; - boolean enableNext = false; - Timeline timeline = player.getCurrentTimeline(); - if (!timeline.isEmpty() && !player.isPlayingAd()) { - boolean isSeekable = player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM); - timeline.getWindow(player.getCurrentWindowIndex(), window); - enablePrevious = - isSeekable - || !window.isLive() - || player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); - enableRewind = isSeekable && controlDispatcher.isRewindEnabled(); - enableFastForward = isSeekable && controlDispatcher.isFastForwardEnabled(); - enableNext = - (window.isLive() && window.isDynamic) - || player.isCommandAvailable(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); - } + boolean enablePrevious = player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS); + boolean enableRewind = + player.isCommandAvailable(COMMAND_SEEK_BACK) && controlDispatcher.isRewindEnabled(); + boolean enableFastForward = + player.isCommandAvailable(COMMAND_SEEK_FORWARD) && controlDispatcher.isFastForwardEnabled(); + boolean enableNext = player.isCommandAvailable(COMMAND_SEEK_TO_NEXT); List stringActions = new ArrayList<>(); if (usePreviousAction && enablePrevious) { stringActions.add(ACTION_PREVIOUS); } - if (enableRewind) { + if (useRewindAction && enableRewind) { stringActions.add(ACTION_REWIND); } if (usePlayPauseActions) { @@ -1446,7 +1343,7 @@ protected List getActions(Player player) { stringActions.add(ACTION_PLAY); } } - if (enableFastForward) { + if (useFastForwardAction && enableFastForward) { stringActions.add(ACTION_FAST_FORWARD); } if (useNextAction && enableNext) { @@ -1474,14 +1371,19 @@ protected List getActions(Player player) { protected int[] getActionIndicesForCompactView(List actionNames, Player player) { int pauseActionIndex = actionNames.indexOf(ACTION_PAUSE); int playActionIndex = actionNames.indexOf(ACTION_PLAY); - int previousActionIndex = - usePreviousActionInCompactView ? actionNames.indexOf(ACTION_PREVIOUS) : -1; - int nextActionIndex = useNextActionInCompactView ? actionNames.indexOf(ACTION_NEXT) : -1; + int leftSideActionIndex = + usePreviousActionInCompactView + ? actionNames.indexOf(ACTION_PREVIOUS) + : (useRewindActionInCompactView ? actionNames.indexOf(ACTION_REWIND) : -1); + int rightSideActionIndex = + useNextActionInCompactView + ? actionNames.indexOf(ACTION_NEXT) + : (useFastForwardActionInCompactView ? actionNames.indexOf(ACTION_FAST_FORWARD) : -1); int[] actionIndices = new int[3]; int actionCounter = 0; - if (previousActionIndex != -1) { - actionIndices[actionCounter++] = previousActionIndex; + if (leftSideActionIndex != -1) { + actionIndices[actionCounter++] = leftSideActionIndex; } boolean shouldShowPauseButton = shouldShowPauseButton(player); if (pauseActionIndex != -1 && shouldShowPauseButton) { @@ -1489,8 +1391,8 @@ protected int[] getActionIndicesForCompactView(List actionNames, Player } else if (playActionIndex != -1 && !shouldShowPauseButton) { actionIndices[actionCounter++] = playActionIndex; } - if (nextActionIndex != -1) { - actionIndices[actionCounter++] = nextActionIndex; + if (rightSideActionIndex != -1) { + actionIndices[actionCounter++] = rightSideActionIndex; } return Arrays.copyOf(actionIndices, actionCounter); } @@ -1610,12 +1512,12 @@ private static PendingIntent createBroadcastIntent( return PendingIntent.getBroadcast(context, instanceId, intent, pendingFlags); } - @SuppressWarnings("nullness:argument.type.incompatible") + @SuppressWarnings("nullness:argument") private static void setLargeIcon(NotificationCompat.Builder builder, @Nullable Bitmap largeIcon) { builder.setLargeIcon(largeIcon); } - private class PlayerListener implements Player.EventListener { + private class PlayerListener implements Player.Listener { @Override public void onEvents(Player player, Player.Events events) { @@ -1627,7 +1529,8 @@ public void onEvents(Player player, Player.Events events) { EVENT_PLAYBACK_PARAMETERS_CHANGED, EVENT_POSITION_DISCONTINUITY, EVENT_REPEAT_MODE_CHANGED, - EVENT_SHUFFLE_MODE_ENABLED_CHANGED)) { + EVENT_SHUFFLE_MODE_ENABLED_CHANGED, + EVENT_MEDIA_METADATA_CHANGED)) { postStartOrUpdateNotification(); } } @@ -1647,11 +1550,7 @@ public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (ACTION_PLAY.equals(action)) { if (player.getPlaybackState() == Player.STATE_IDLE) { - if (playbackPreparer != null) { - playbackPreparer.preparePlayback(); - } else { - controlDispatcher.dispatchPrepare(player); - } + controlDispatcher.dispatchPrepare(player); } else if (player.getPlaybackState() == Player.STATE_ENDED) { controlDispatcher.dispatchSeekTo(player, player.getCurrentWindowIndex(), C.TIME_UNSET); } diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java index c6354188078..530b81e138c 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java @@ -47,27 +47,26 @@ import androidx.core.content.ContextCompat; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ControlDispatcher; -import com.google.android.exoplayer2.DefaultControlDispatcher; -import com.google.android.exoplayer2.ExoPlaybackException; -import com.google.android.exoplayer2.PlaybackPreparer; +import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.ForwardingPlayer; +import com.google.android.exoplayer2.MediaMetadata; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player.DiscontinuityReason; +import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline.Period; -import com.google.android.exoplayer2.metadata.Metadata; -import com.google.android.exoplayer2.metadata.flac.PictureFrame; -import com.google.android.exoplayer2.metadata.id3.ApicFrame; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.text.Cue; +import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelectionArray; -import com.google.android.exoplayer2.trackselection.TrackSelectionUtil; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout.ResizeMode; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.ErrorMessageProvider; +import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.RepeatModeUtil; import com.google.android.exoplayer2.util.Util; -import com.google.android.exoplayer2.video.VideoDecoderGLSurfaceView; -import com.google.android.exoplayer2.video.spherical.SphericalGLSurfaceView; +import com.google.android.exoplayer2.video.VideoSize; import com.google.common.collect.ImmutableList; import java.lang.annotation.Documented; import java.lang.annotation.Retention; @@ -85,7 +84,7 @@ * overriding drawables, overriding the view's layout file, or by specifying a custom view layout * file. * - *

    Attributes

    + *

    Attributes

    * * The following attributes can be set on a PlayerView when used in a layout XML file: * @@ -177,13 +176,13 @@ * exo_controller} (see below). * * - *

    Overriding drawables

    + *

    Overriding drawables

    * * The drawables used by {@link PlayerControlView} (with its default layout file) can be overridden * by drawables with the same names defined in your application. See the {@link PlayerControlView} * documentation for a list of drawables that can be overridden. * - *

    Overriding the layout file

    + *

    Overriding the layout file

    * * To customize the layout of PlayerView throughout your app, or just for certain configurations, * you can define {@code exo_player_view.xml} layout files in your application {@code res/layout*} @@ -250,7 +249,7 @@ *

    All child views are optional and so can be omitted if not required, however where defined they * must be of the expected type. * - *

    Specifying a custom layout file

    + *

    Specifying a custom layout file

    * * Defining your own {@code exo_player_view.xml} is useful to customize the layout of PlayerView * throughout your application. It's also possible to customize the layout for a single instance in @@ -260,7 +259,6 @@ */ public class PlayerView extends FrameLayout implements AdViewProvider { - // LINT.IfChange /** * Determines when the buffering view is shown. One of {@link #SHOW_BUFFERING_NEVER}, {@link * #SHOW_BUFFERING_WHEN_PLAYING} or {@link #SHOW_BUFFERING_ALWAYS}. @@ -281,15 +279,12 @@ public class PlayerView extends FrameLayout implements AdViewProvider { * buffering} state. */ public static final int SHOW_BUFFERING_ALWAYS = 2; - // LINT.ThenChange(../../../../../../res/values/attrs.xml) - // LINT.IfChange private static final int SURFACE_TYPE_NONE = 0; private static final int SURFACE_TYPE_SURFACE_VIEW = 1; private static final int SURFACE_TYPE_TEXTURE_VIEW = 2; private static final int SURFACE_TYPE_SPHERICAL_GL_SURFACE_VIEW = 3; private static final int SURFACE_TYPE_VIDEO_DECODER_GL_SURFACE_VIEW = 4; - // LINT.ThenChange(../../../../../../res/values/attrs.xml) private final ComponentListener componentListener; @Nullable private final AspectRatioFrameLayout contentFrame; @@ -311,7 +306,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider { @Nullable private Drawable defaultArtwork; private @ShowBuffering int showBuffering; private boolean keepContentOnPlayerReset; - @Nullable private ErrorMessageProvider errorMessageProvider; + @Nullable private ErrorMessageProvider errorMessageProvider; @Nullable private CharSequence customErrorMessage; private int controllerShowTimeoutMs; private boolean controllerAutoShow; @@ -330,7 +325,7 @@ public PlayerView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, /* defStyleAttr= */ 0); } - @SuppressWarnings({"nullness:argument.type.incompatible", "nullness:method.invocation.invalid"}) + @SuppressWarnings({"nullness:argument", "nullness:method.invocation"}) public PlayerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); @@ -425,11 +420,26 @@ public PlayerView(Context context, @Nullable AttributeSet attrs, int defStyleAtt surfaceView = new TextureView(context); break; case SURFACE_TYPE_SPHERICAL_GL_SURFACE_VIEW: - surfaceView = new SphericalGLSurfaceView(context); + try { + Class clazz = + Class.forName( + "com.google.android.exoplayer2.video.spherical.SphericalGLSurfaceView"); + surfaceView = (View) clazz.getConstructor(Context.class).newInstance(context); + } catch (Exception e) { + throw new IllegalStateException( + "spherical_gl_surface_view requires an ExoPlayer dependency", e); + } surfaceViewIgnoresVideoAspectRatio = true; break; case SURFACE_TYPE_VIDEO_DECODER_GL_SURFACE_VIEW: - surfaceView = new VideoDecoderGLSurfaceView(context); + try { + Class clazz = + Class.forName("com.google.android.exoplayer2.video.VideoDecoderGLSurfaceView"); + surfaceView = (View) clazz.getConstructor(Context.class).newInstance(context); + } catch (Exception e) { + throw new IllegalStateException( + "video_decoder_gl_surface_view requires an ExoPlayer dependency", e); + } break; default: surfaceView = new SurfaceView(context); @@ -588,6 +598,7 @@ public void setPlayer(@Nullable Player player) { } else if (surfaceView instanceof SurfaceView) { player.setVideoSurfaceView((SurfaceView) surfaceView); } + updateAspectRatio(); } if (subtitleView != null && player.isCommandAvailable(COMMAND_GET_TEXT)) { subtitleView.setCues(player.getCurrentCues()); @@ -745,7 +756,7 @@ public void setShowBuffering(@ShowBuffering int showBuffering) { * @param errorMessageProvider The error message provider. */ public void setErrorMessageProvider( - @Nullable ErrorMessageProvider errorMessageProvider) { + @Nullable ErrorMessageProvider errorMessageProvider) { if (this.errorMessageProvider != errorMessageProvider) { this.errorMessageProvider = errorMessageProvider; updateErrorMessage(); @@ -918,25 +929,11 @@ public void setControllerVisibilityListener( } /** - * @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} instead. The view calls {@link - * ControlDispatcher#dispatchPrepare(Player)} instead of {@link - * PlaybackPreparer#preparePlayback()}. The {@link DefaultControlDispatcher} that the view - * uses by default, calls {@link Player#prepare()}. If you wish to customize this behaviour, - * you can provide a custom implementation of {@link - * ControlDispatcher#dispatchPrepare(Player)}. + * @deprecated Use a {@link ForwardingPlayer} and pass it to {@link #setPlayer(Player)} instead. + * You can also customize some operations when configuring the player (for example by using + * {@link SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)}). */ - @SuppressWarnings("deprecation") @Deprecated - public void setPlaybackPreparer(@Nullable PlaybackPreparer playbackPreparer) { - Assertions.checkStateNotNull(controller); - controller.setPlaybackPreparer(playbackPreparer); - } - - /** - * Sets the {@link ControlDispatcher}. - * - * @param controlDispatcher The {@link ControlDispatcher}. - */ public void setControlDispatcher(ControlDispatcher controlDispatcher) { Assertions.checkStateNotNull(controller); controller.setControlDispatcher(controlDispatcher); @@ -982,28 +979,6 @@ public void setShowNextButton(boolean showNextButton) { controller.setShowNextButton(showNextButton); } - /** - * @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} with {@link - * DefaultControlDispatcher#DefaultControlDispatcher(long, long)}. - */ - @SuppressWarnings("deprecation") - @Deprecated - public void setRewindIncrementMs(int rewindMs) { - Assertions.checkStateNotNull(controller); - controller.setRewindIncrementMs(rewindMs); - } - - /** - * @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} with {@link - * DefaultControlDispatcher#DefaultControlDispatcher(long, long)}. - */ - @SuppressWarnings("deprecation") - @Deprecated - public void setFastForwardIncrementMs(int fastForwardMs) { - Assertions.checkStateNotNull(controller); - controller.setFastForwardIncrementMs(fastForwardMs); - } - /** * Sets which repeat toggle modes are enabled. * @@ -1069,14 +1044,14 @@ public void setAspectRatioListener( *
  • {@link SurfaceView} by default, or if the {@code surface_type} attribute is set to {@code * surface_view}. *
  • {@link TextureView} if {@code surface_type} is {@code texture_view}. - *
  • {@link SphericalGLSurfaceView} if {@code surface_type} is {@code + *
  • {@code SphericalGLSurfaceView} if {@code surface_type} is {@code * spherical_gl_surface_view}. - *
  • {@link VideoDecoderGLSurfaceView} if {@code surface_type} is {@code + *
  • {@code VideoDecoderGLSurfaceView} if {@code surface_type} is {@code * video_decoder_gl_surface_view}. *
  • {@code null} if {@code surface_type} is {@code none}. * * - * @return The {@link SurfaceView}, {@link TextureView}, {@link SphericalGLSurfaceView}, {@link + * @return The {@link SurfaceView}, {@link TextureView}, {@code SphericalGLSurfaceView}, {@code * VideoDecoderGLSurfaceView} or {@code null}. */ @Nullable @@ -1291,21 +1266,28 @@ private void updateForCurrentTrackSelections(boolean isNewPlayer) { closeShutter(); } - if (TrackSelectionUtil.hasTrackOfType(player.getCurrentTrackSelections(), C.TRACK_TYPE_VIDEO)) { - // Video enabled so artwork must be hidden. If the shutter is closed, it will be opened in - // onRenderedFirstFrame(). - hideArtwork(); - return; + TrackSelectionArray trackSelections = player.getCurrentTrackSelections(); + for (int i = 0; i < trackSelections.length; i++) { + @Nullable TrackSelection trackSelection = trackSelections.get(i); + if (trackSelection != null) { + for (int j = 0; j < trackSelection.length(); j++) { + Format format = trackSelection.getFormat(j); + if (MimeTypes.getTrackType(format.sampleMimeType) == C.TRACK_TYPE_VIDEO) { + // Video enabled, so artwork must be hidden. If the shutter is closed, it will be opened + // in onRenderedFirstFrame(). + hideArtwork(); + return; + } + } + } } // Video disabled so the shutter must be closed. closeShutter(); // Display artwork if enabled and available, else hide it. if (useArtwork()) { - for (Metadata metadata : player.getCurrentStaticMetadata()) { - if (setArtworkFromMetadata(metadata)) { - return; - } + if (setArtworkFromMediaMetadata(player.getMediaMetadata())) { + return; } if (setDrawableArtwork(defaultArtwork)) { return; @@ -1315,34 +1297,47 @@ private void updateForCurrentTrackSelections(boolean isNewPlayer) { hideArtwork(); } - @RequiresNonNull("artworkView") - private boolean setArtworkFromMetadata(Metadata metadata) { - boolean isArtworkSet = false; - int currentPictureType = PICTURE_TYPE_NOT_SET; - for (int i = 0; i < metadata.length(); i++) { - Metadata.Entry metadataEntry = metadata.get(i); - int pictureType; - byte[] bitmapData; - if (metadataEntry instanceof ApicFrame) { - bitmapData = ((ApicFrame) metadataEntry).pictureData; - pictureType = ((ApicFrame) metadataEntry).pictureType; - } else if (metadataEntry instanceof PictureFrame) { - bitmapData = ((PictureFrame) metadataEntry).pictureData; - pictureType = ((PictureFrame) metadataEntry).pictureType; - } else { - continue; + private void updateAspectRatio() { + VideoSize videoSize = player != null ? player.getVideoSize() : VideoSize.UNKNOWN; + int width = videoSize.width; + int height = videoSize.height; + int unappliedRotationDegrees = videoSize.unappliedRotationDegrees; + float videoAspectRatio = + (height == 0 || width == 0) ? 0 : (width * videoSize.pixelWidthHeightRatio) / height; + + if (surfaceView instanceof TextureView) { + // Try to apply rotation transformation when our surface is a TextureView. + if (videoAspectRatio > 0 + && (unappliedRotationDegrees == 90 || unappliedRotationDegrees == 270)) { + // We will apply a rotation 90/270 degree to the output texture of the TextureView. + // In this case, the output video's width and height will be swapped. + videoAspectRatio = 1 / videoAspectRatio; } - // Prefer the first front cover picture. If there aren't any, prefer the first picture. - if (currentPictureType == PICTURE_TYPE_NOT_SET || pictureType == PICTURE_TYPE_FRONT_COVER) { - Bitmap bitmap = BitmapFactory.decodeByteArray(bitmapData, 0, bitmapData.length); - isArtworkSet = setDrawableArtwork(new BitmapDrawable(getResources(), bitmap)); - currentPictureType = pictureType; - if (currentPictureType == PICTURE_TYPE_FRONT_COVER) { - break; - } + if (textureViewRotation != 0) { + surfaceView.removeOnLayoutChangeListener(componentListener); + } + textureViewRotation = unappliedRotationDegrees; + if (textureViewRotation != 0) { + // The texture view's dimensions might be changed after layout step. + // So add an OnLayoutChangeListener to apply rotation after layout step. + surfaceView.addOnLayoutChangeListener(componentListener); } + applyTextureViewRotation((TextureView) surfaceView, textureViewRotation); + } + + onContentAspectRatioChanged( + contentFrame, surfaceViewIgnoresVideoAspectRatio ? 0 : videoAspectRatio); + } + + @RequiresNonNull("artworkView") + private boolean setArtworkFromMediaMetadata(MediaMetadata mediaMetadata) { + if (mediaMetadata.artworkData == null) { + return false; } - return isArtworkSet; + Bitmap bitmap = + BitmapFactory.decodeByteArray( + mediaMetadata.artworkData, /* offset= */ 0, mediaMetadata.artworkData.length); + return setDrawableArtwork(new BitmapDrawable(getResources(), bitmap)); } @RequiresNonNull("artworkView") @@ -1392,7 +1387,7 @@ private void updateErrorMessage() { errorMessageView.setVisibility(View.VISIBLE); return; } - @Nullable ExoPlaybackException error = player != null ? player.getPlayerError() : null; + @Nullable PlaybackException error = player != null ? player.getPlayerError() : null; if (error != null && errorMessageProvider != null) { CharSequence errorMessage = errorMessageProvider.getErrorMessage(error).second; errorMessageView.setText(errorMessage); @@ -1490,7 +1485,7 @@ public ComponentListener() { period = new Period(); } - // TextOutput implementation + // Player.Listener implementation @Override public void onCues(List cues) { @@ -1499,35 +1494,9 @@ public void onCues(List cues) { } } - // VideoListener implementation - @Override - public void onVideoSizeChanged( - int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) { - float videoAspectRatio = - (height == 0 || width == 0) ? 1 : (width * pixelWidthHeightRatio) / height; - - if (surfaceView instanceof TextureView) { - // Try to apply rotation transformation when our surface is a TextureView. - if (unappliedRotationDegrees == 90 || unappliedRotationDegrees == 270) { - // We will apply a rotation 90/270 degree to the output texture of the TextureView. - // In this case, the output video's width and height will be swapped. - videoAspectRatio = 1 / videoAspectRatio; - } - if (textureViewRotation != 0) { - surfaceView.removeOnLayoutChangeListener(this); - } - textureViewRotation = unappliedRotationDegrees; - if (textureViewRotation != 0) { - // The texture view's dimensions might be changed after layout step. - // So add an OnLayoutChangeListener to apply rotation after layout step. - surfaceView.addOnLayoutChangeListener(this); - } - applyTextureViewRotation((TextureView) surfaceView, textureViewRotation); - } - - onContentAspectRatioChanged( - contentFrame, surfaceViewIgnoresVideoAspectRatio ? 0 : videoAspectRatio); + public void onVideoSizeChanged(VideoSize videoSize) { + updateAspectRatio(); } @Override @@ -1538,7 +1507,7 @@ public void onRenderedFirstFrame() { } @Override - public void onTracksChanged(TrackGroupArray tracks, TrackSelectionArray selections) { + public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray selections) { // Suppress the update if transitioning to an unprepared period within the same window. This // is necessary to avoid closing the shutter when such a transition occurs. See: // https://github.com/google/ExoPlayer/issues/5507. @@ -1565,8 +1534,6 @@ public void onTracksChanged(TrackGroupArray tracks, TrackSelectionArray selectio updateForCurrentTrackSelections(/* isNewPlayer= */ false); } - // Player.EventListener implementation - @Override public void onPlaybackStateChanged(@Player.State int playbackState) { updateBuffering(); diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlView.java index 86086dd90b0..8a4b6ae9a9d 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlView.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlView.java @@ -15,15 +15,19 @@ */ package com.google.android.exoplayer2.ui; -import static com.google.android.exoplayer2.Player.COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM; -import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM; -import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_BACK; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_FORWARD; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_IN_CURRENT_WINDOW; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_NEXT; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_PREVIOUS; import static com.google.android.exoplayer2.Player.EVENT_IS_PLAYING_CHANGED; import static com.google.android.exoplayer2.Player.EVENT_PLAYBACK_PARAMETERS_CHANGED; import static com.google.android.exoplayer2.Player.EVENT_PLAYBACK_STATE_CHANGED; import static com.google.android.exoplayer2.Player.EVENT_PLAY_WHEN_READY_CHANGED; import static com.google.android.exoplayer2.Player.EVENT_POSITION_DISCONTINUITY; import static com.google.android.exoplayer2.Player.EVENT_REPEAT_MODE_CHANGED; +import static com.google.android.exoplayer2.Player.EVENT_SEEK_BACK_INCREMENT_CHANGED; +import static com.google.android.exoplayer2.Player.EVENT_SEEK_FORWARD_INCREMENT_CHANGED; import static com.google.android.exoplayer2.Player.EVENT_SHUFFLE_MODE_ENABLED_CHANGED; import static com.google.android.exoplayer2.Player.EVENT_TIMELINE_CHANGED; import static com.google.android.exoplayer2.Player.EVENT_TRACKS_CHANGED; @@ -57,10 +61,11 @@ import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ExoPlayerLibraryInfo; import com.google.android.exoplayer2.Format; -import com.google.android.exoplayer2.PlaybackPreparer; +import com.google.android.exoplayer2.ForwardingPlayer; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player.Events; import com.google.android.exoplayer2.Player.State; +import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroupArray; @@ -89,7 +94,7 @@ * methods), overriding drawables, overriding the view's layout file, or by specifying a custom view * layout file. * - *

    Attributes

    + *

    Attributes

    * * The following attributes can be set on a StyledPlayerControlView when used in a layout XML file: * @@ -121,17 +126,6 @@ *
  • Corresponding method: {@link #setShowNextButton(boolean)} *
  • Default: true * - *
  • {@code rewind_increment} - The duration of the rewind applied when the user taps the - * rewind button, in milliseconds. Use zero to disable the rewind button. - *
      - *
    • Corresponding method: {@link #setControlDispatcher(ControlDispatcher)} - *
    • Default: {@link DefaultControlDispatcher#DEFAULT_REWIND_MS} - *
    - *
  • {@code fastforward_increment} - Like {@code rewind_increment}, but for fast forward. - *
      - *
    • Corresponding method: {@link #setControlDispatcher(ControlDispatcher)} - *
    • Default: {@link DefaultControlDispatcher#DEFAULT_FAST_FORWARD_MS} - *
    *
  • {@code repeat_toggle_modes} - A flagged enumeration value specifying which repeat * mode toggle options are enabled. Valid values are: {@code none}, {@code one}, {@code all}, * or {@code one|all}. @@ -172,7 +166,7 @@ * unless the layout is overridden to specify a custom {@code exo_progress} (see below). * * - *

    Overriding drawables

    + *

    Overriding drawables

    * * The drawables used by StyledPlayerControlView (with its default layout file) can be overridden by * drawables with the same names defined in your application. The drawables that can be overridden @@ -197,7 +191,7 @@ *
  • {@code exo_styled_controls_vr} - The VR icon. * * - *

    Overriding the layout file

    + *

    Overriding the layout file

    * * To customize the layout of StyledPlayerControlView throughout your app, or just for certain * configurations, you can define {@code exo_styled_player_control_view.xml} layout files in your @@ -302,7 +296,7 @@ *

    All child views are optional and so can be omitted if not required, however where defined they * must be of the expected type. * - *

    Specifying a custom layout file

    + *

    Specifying a custom layout file

    * * Defining your own {@code exo_styled_player_control_view.xml} is useful to customize the layout of * StyledPlayerControlView throughout your application. It's also possible to customize the layout @@ -417,7 +411,6 @@ public interface OnFullScreenModeChangedListener { @Nullable private Player player; private ControlDispatcher controlDispatcher; @Nullable private ProgressUpdateListener progressUpdateListener; - @Nullable private PlaybackPreparer playbackPreparer; @Nullable private OnFullScreenModeChangedListener onFullScreenModeChangedListener; private boolean isFullScreen; @@ -433,8 +426,6 @@ public interface OnFullScreenModeChangedListener { private long[] extraAdGroupTimesMs; private boolean[] extraPlayedAdGroups; private long currentWindowOffset; - private long rewindMs; - private long fastForwardMs; private StyledPlayerControlViewLayoutManager controlViewLayoutManager; private Resources resources; @@ -472,10 +463,10 @@ public StyledPlayerControlView(Context context, @Nullable AttributeSet attrs, in } @SuppressWarnings({ - "nullness:argument.type.incompatible", - "nullness:assignment.type.incompatible", - "nullness:method.invocation.invalid", - "nullness:methodref.receiver.bound.invalid" + "nullness:argument", + "nullness:assignment", + "nullness:method.invocation", + "nullness:methodref.receiver.bound" }) public StyledPlayerControlView( Context context, @@ -484,8 +475,6 @@ public StyledPlayerControlView( @Nullable AttributeSet playbackAttrs) { super(context, attrs, defStyleAttr); int controllerLayoutId = R.layout.exo_styled_player_control_view; - rewindMs = DefaultControlDispatcher.DEFAULT_REWIND_MS; - fastForwardMs = DefaultControlDispatcher.DEFAULT_FAST_FORWARD_MS; showTimeoutMs = DEFAULT_SHOW_TIMEOUT_MS; repeatToggleModes = DEFAULT_REPEAT_TOGGLE_MODES; timeBarMinUpdateIntervalMs = DEFAULT_TIME_BAR_MIN_UPDATE_INTERVAL_MS; @@ -504,10 +493,6 @@ public StyledPlayerControlView( .getTheme() .obtainStyledAttributes(playbackAttrs, R.styleable.StyledPlayerControlView, 0, 0); try { - rewindMs = a.getInt(R.styleable.StyledPlayerControlView_rewind_increment, (int) rewindMs); - fastForwardMs = - a.getInt( - R.styleable.StyledPlayerControlView_fastforward_increment, (int) fastForwardMs); controllerLayoutId = a.getResourceId( R.styleable.StyledPlayerControlView_controller_layout_id, controllerLayoutId); @@ -555,7 +540,7 @@ public StyledPlayerControlView( playedAdGroups = new boolean[0]; extraAdGroupTimesMs = new long[0]; extraPlayedAdGroups = new boolean[0]; - controlDispatcher = new DefaultControlDispatcher(fastForwardMs, rewindMs); + controlDispatcher = new DefaultControlDispatcher(); updateProgressAction = this::updateProgress; durationView = findViewById(R.id.exo_duration); @@ -849,24 +834,11 @@ public void setProgressUpdateListener(@Nullable ProgressUpdateListener listener) } /** - * @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} instead. The view calls {@link - * ControlDispatcher#dispatchPrepare(Player)} instead of {@link - * PlaybackPreparer#preparePlayback()}. The {@link DefaultControlDispatcher} that the view - * uses by default, calls {@link Player#prepare()}. If you wish to customize this behaviour, - * you can provide a custom implementation of {@link - * ControlDispatcher#dispatchPrepare(Player)}. + * @deprecated Use a {@link ForwardingPlayer} and pass it to {@link #setPlayer(Player)} instead. + * You can also customize some operations when configuring the player (for example by using + * {@link SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)}). */ - @SuppressWarnings("deprecation") @Deprecated - public void setPlaybackPreparer(@Nullable PlaybackPreparer playbackPreparer) { - this.playbackPreparer = playbackPreparer; - } - - /** - * Sets the {@link ControlDispatcher}. - * - * @param controlDispatcher The {@link ControlDispatcher}. - */ public void setControlDispatcher(ControlDispatcher controlDispatcher) { if (this.controlDispatcher != controlDispatcher) { this.controlDispatcher = controlDispatcher; @@ -1147,21 +1119,14 @@ private void updateNavigation() { boolean enableFastForward = false; boolean enableNext = false; if (player != null) { - Timeline timeline = player.getCurrentTimeline(); - if (!timeline.isEmpty() && !player.isPlayingAd()) { - boolean isSeekable = player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM); - timeline.getWindow(player.getCurrentWindowIndex(), window); - enableSeeking = isSeekable; - enablePrevious = - isSeekable - || !window.isLive() - || player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); - enableRewind = isSeekable && controlDispatcher.isRewindEnabled(); - enableFastForward = isSeekable && controlDispatcher.isFastForwardEnabled(); - enableNext = - (window.isLive() && window.isDynamic) - || player.isCommandAvailable(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); - } + enableSeeking = player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_WINDOW); + enablePrevious = player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS); + enableRewind = + player.isCommandAvailable(COMMAND_SEEK_BACK) && controlDispatcher.isRewindEnabled(); + enableFastForward = + player.isCommandAvailable(COMMAND_SEEK_FORWARD) + && controlDispatcher.isFastForwardEnabled(); + enableNext = player.isCommandAvailable(COMMAND_SEEK_TO_NEXT); } if (enableRewind) { @@ -1181,9 +1146,10 @@ private void updateNavigation() { } private void updateRewindButton() { - if (controlDispatcher instanceof DefaultControlDispatcher) { - rewindMs = ((DefaultControlDispatcher) controlDispatcher).getRewindIncrementMs(); - } + long rewindMs = + controlDispatcher instanceof DefaultControlDispatcher && player != null + ? ((DefaultControlDispatcher) controlDispatcher).getRewindIncrementMs(player) + : C.DEFAULT_SEEK_BACK_INCREMENT_MS; int rewindSec = (int) (rewindMs / 1_000); if (rewindButtonTextView != null) { rewindButtonTextView.setText(String.valueOf(rewindSec)); @@ -1196,9 +1162,10 @@ private void updateRewindButton() { } private void updateFastForwardButton() { - if (controlDispatcher instanceof DefaultControlDispatcher) { - fastForwardMs = ((DefaultControlDispatcher) controlDispatcher).getFastForwardIncrementMs(); - } + long fastForwardMs = + controlDispatcher instanceof DefaultControlDispatcher && player != null + ? ((DefaultControlDispatcher) controlDispatcher).getFastForwardIncrementMs(player) + : C.DEFAULT_SEEK_FORWARD_INCREMENT_MS; int fastForwardSec = (int) (fastForwardMs / 1_000); if (fastForwardButtonTextView != null) { fastForwardButtonTextView.setText(String.valueOf(fastForwardSec)); @@ -1362,8 +1329,9 @@ private void updateTimeline() { } for (int j = window.firstPeriodIndex; j <= window.lastPeriodIndex; j++) { timeline.getPeriod(j, period); - int periodAdGroupCount = period.getAdGroupCount(); - for (int adGroupIndex = 0; adGroupIndex < periodAdGroupCount; adGroupIndex++) { + int removedGroups = period.getRemovedAdGroupCount(); + int totalGroups = period.getAdGroupCount(); + for (int adGroupIndex = removedGroups; adGroupIndex < totalGroups; adGroupIndex++) { long adGroupTimeInPeriodUs = period.getAdGroupTimeUs(adGroupIndex); if (adGroupTimeInPeriodUs == C.TIME_END_OF_SOURCE) { if (period.durationUs == C.TIME_UNSET) { @@ -1699,11 +1667,7 @@ private void dispatchPlayPause(Player player) { private void dispatchPlay(Player player) { @State int state = player.getPlaybackState(); if (state == Player.STATE_IDLE) { - if (playbackPreparer != null) { - playbackPreparer.preparePlayback(); - } else { - controlDispatcher.dispatchPrepare(player); - } + controlDispatcher.dispatchPrepare(player); } else if (state == Player.STATE_ENDED) { seekTo(player, player.getCurrentWindowIndex(), C.TIME_UNSET); } @@ -1773,36 +1737,11 @@ private static void updateFullScreenButtonVisibility( } private final class ComponentListener - implements Player.EventListener, + implements Player.Listener, TimeBar.OnScrubListener, OnClickListener, PopupWindow.OnDismissListener { - @Override - public void onScrubStart(TimeBar timeBar, long position) { - scrubbing = true; - if (positionView != null) { - positionView.setText(Util.getStringForTime(formatBuilder, formatter, position)); - } - controlViewLayoutManager.removeHideCallbacks(); - } - - @Override - public void onScrubMove(TimeBar timeBar, long position) { - if (positionView != null) { - positionView.setText(Util.getStringForTime(formatBuilder, formatter, position)); - } - } - - @Override - public void onScrubStop(TimeBar timeBar, long position, boolean canceled) { - scrubbing = false; - if (!canceled && player != null) { - seekToTimeBarPosition(player, position); - } - controlViewLayoutManager.resetHideCallbacks(); - } - @Override public void onEvents(Player player, Events events) { if (events.containsAny(EVENT_PLAYBACK_STATE_CHANGED, EVENT_PLAY_WHEN_READY_CHANGED)) { @@ -1822,7 +1761,9 @@ public void onEvents(Player player, Events events) { EVENT_REPEAT_MODE_CHANGED, EVENT_SHUFFLE_MODE_ENABLED_CHANGED, EVENT_POSITION_DISCONTINUITY, - EVENT_TIMELINE_CHANGED)) { + EVENT_TIMELINE_CHANGED, + EVENT_SEEK_BACK_INCREMENT_CHANGED, + EVENT_SEEK_FORWARD_INCREMENT_CHANGED)) { updateNavigation(); } if (events.containsAny(EVENT_POSITION_DISCONTINUITY, EVENT_TIMELINE_CHANGED)) { @@ -1836,6 +1777,31 @@ public void onEvents(Player player, Events events) { } } + @Override + public void onScrubStart(TimeBar timeBar, long position) { + scrubbing = true; + if (positionView != null) { + positionView.setText(Util.getStringForTime(formatBuilder, formatter, position)); + } + controlViewLayoutManager.removeHideCallbacks(); + } + + @Override + public void onScrubMove(TimeBar timeBar, long position) { + if (positionView != null) { + positionView.setText(Util.getStringForTime(formatBuilder, formatter, position)); + } + } + + @Override + public void onScrubStop(TimeBar timeBar, long position, boolean canceled) { + scrubbing = false; + if (!canceled && player != null) { + seekToTimeBarPosition(player, position); + } + controlViewLayoutManager.resetHideCallbacks(); + } + @Override public void onDismiss() { if (needToHideBars) { diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlViewLayoutManager.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlViewLayoutManager.java index 6fbf7593051..8c03272b3b8 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlViewLayoutManager.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlViewLayoutManager.java @@ -83,10 +83,7 @@ private boolean needToShowBars; private boolean animationEnabled; - @SuppressWarnings({ - "nullness:method.invocation.invalid", - "nullness:methodref.receiver.bound.invalid" - }) + @SuppressWarnings({"nullness:method.invocation", "nullness:methodref.receiver.bound"}) public StyledPlayerControlViewLayoutManager(StyledPlayerControlView styledPlayerControlView) { this.styledPlayerControlView = styledPlayerControlView; showAllBarsRunnable = this::showAllBars; diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerView.java index e626a1c54f5..b5a2822c8db 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerView.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerView.java @@ -48,27 +48,26 @@ import androidx.core.content.ContextCompat; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ControlDispatcher; -import com.google.android.exoplayer2.DefaultControlDispatcher; -import com.google.android.exoplayer2.ExoPlaybackException; -import com.google.android.exoplayer2.PlaybackPreparer; +import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.ForwardingPlayer; +import com.google.android.exoplayer2.MediaMetadata; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player.DiscontinuityReason; +import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline.Period; -import com.google.android.exoplayer2.metadata.Metadata; -import com.google.android.exoplayer2.metadata.flac.PictureFrame; -import com.google.android.exoplayer2.metadata.id3.ApicFrame; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.text.Cue; +import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelectionArray; -import com.google.android.exoplayer2.trackselection.TrackSelectionUtil; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout.ResizeMode; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.ErrorMessageProvider; +import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.RepeatModeUtil; import com.google.android.exoplayer2.util.Util; -import com.google.android.exoplayer2.video.VideoDecoderGLSurfaceView; -import com.google.android.exoplayer2.video.spherical.SphericalGLSurfaceView; +import com.google.android.exoplayer2.video.VideoSize; import com.google.common.collect.ImmutableList; import java.lang.annotation.Documented; import java.lang.annotation.Retention; @@ -86,7 +85,7 @@ * overriding drawables, overriding the view's layout file, or by specifying a custom view layout * file. * - *

    Attributes

    + *

    Attributes

    * * The following attributes can be set on a StyledPlayerView when used in a layout XML file: * @@ -178,13 +177,13 @@ * custom {@code exo_controller} (see below). * * - *

    Overriding drawables

    + *

    Overriding drawables

    * * The drawables used by {@link StyledPlayerControlView} (with its default layout file) can be * overridden by drawables with the same names defined in your application. See the {@link * StyledPlayerControlView} documentation for a list of drawables that can be overridden. * - *

    Overriding the layout file

    + *

    Overriding the layout file

    * * To customize the layout of StyledPlayerView throughout your app, or just for certain * configurations, you can define {@code exo_styled_player_view.xml} layout files in your @@ -251,7 +250,7 @@ *

    All child views are optional and so can be omitted if not required, however where defined they * must be of the expected type. * - *

    Specifying a custom layout file

    + *

    Specifying a custom layout file

    * * Defining your own {@code exo_styled_player_view.xml} is useful to customize the layout of * StyledPlayerView throughout your application. It's also possible to customize the layout for a @@ -261,7 +260,6 @@ */ public class StyledPlayerView extends FrameLayout implements AdViewProvider { - // LINT.IfChange /** * Determines when the buffering view is shown. One of {@link #SHOW_BUFFERING_NEVER}, {@link * #SHOW_BUFFERING_WHEN_PLAYING} or {@link #SHOW_BUFFERING_ALWAYS}. @@ -282,15 +280,12 @@ public class StyledPlayerView extends FrameLayout implements AdViewProvider { * buffering} state. */ public static final int SHOW_BUFFERING_ALWAYS = 2; - // LINT.ThenChange(../../../../../../res/values/attrs.xml) - // LINT.IfChange private static final int SURFACE_TYPE_NONE = 0; private static final int SURFACE_TYPE_SURFACE_VIEW = 1; private static final int SURFACE_TYPE_TEXTURE_VIEW = 2; private static final int SURFACE_TYPE_SPHERICAL_GL_SURFACE_VIEW = 3; private static final int SURFACE_TYPE_VIDEO_DECODER_GL_SURFACE_VIEW = 4; - // LINT.ThenChange(../../../../../../res/values/attrs.xml) private final ComponentListener componentListener; @Nullable private final AspectRatioFrameLayout contentFrame; @@ -312,7 +307,7 @@ public class StyledPlayerView extends FrameLayout implements AdViewProvider { @Nullable private Drawable defaultArtwork; private @ShowBuffering int showBuffering; private boolean keepContentOnPlayerReset; - @Nullable private ErrorMessageProvider errorMessageProvider; + @Nullable private ErrorMessageProvider errorMessageProvider; @Nullable private CharSequence customErrorMessage; private int controllerShowTimeoutMs; private boolean controllerAutoShow; @@ -331,7 +326,7 @@ public StyledPlayerView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, /* defStyleAttr= */ 0); } - @SuppressWarnings({"nullness:argument.type.incompatible", "nullness:method.invocation.invalid"}) + @SuppressWarnings({"nullness:argument", "nullness:method.invocation"}) public StyledPlayerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); @@ -431,11 +426,26 @@ public StyledPlayerView(Context context, @Nullable AttributeSet attrs, int defSt surfaceView = new TextureView(context); break; case SURFACE_TYPE_SPHERICAL_GL_SURFACE_VIEW: - surfaceView = new SphericalGLSurfaceView(context); + try { + Class clazz = + Class.forName( + "com.google.android.exoplayer2.video.spherical.SphericalGLSurfaceView"); + surfaceView = (View) clazz.getConstructor(Context.class).newInstance(context); + } catch (Exception e) { + throw new IllegalStateException( + "spherical_gl_surface_view requires an ExoPlayer dependency", e); + } surfaceViewIgnoresVideoAspectRatio = true; break; case SURFACE_TYPE_VIDEO_DECODER_GL_SURFACE_VIEW: - surfaceView = new VideoDecoderGLSurfaceView(context); + try { + Class clazz = + Class.forName("com.google.android.exoplayer2.video.VideoDecoderGLSurfaceView"); + surfaceView = (View) clazz.getConstructor(Context.class).newInstance(context); + } catch (Exception e) { + throw new IllegalStateException( + "video_decoder_gl_surface_view requires an ExoPlayer dependency", e); + } break; default: surfaceView = new SurfaceView(context); @@ -594,6 +604,7 @@ public void setPlayer(@Nullable Player player) { } else if (surfaceView instanceof SurfaceView) { player.setVideoSurfaceView((SurfaceView) surfaceView); } + updateAspectRatio(); } if (subtitleView != null && player.isCommandAvailable(COMMAND_GET_TEXT)) { subtitleView.setCues(player.getCurrentCues()); @@ -751,7 +762,7 @@ public void setShowBuffering(@ShowBuffering int showBuffering) { * @param errorMessageProvider The error message provider. */ public void setErrorMessageProvider( - @Nullable ErrorMessageProvider errorMessageProvider) { + @Nullable ErrorMessageProvider errorMessageProvider) { if (this.errorMessageProvider != errorMessageProvider) { this.errorMessageProvider = errorMessageProvider; updateErrorMessage(); @@ -936,25 +947,11 @@ public void setControllerOnFullScreenModeChangedListener( } /** - * @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} instead. The view calls {@link - * ControlDispatcher#dispatchPrepare(Player)} instead of {@link - * PlaybackPreparer#preparePlayback()}. The {@link DefaultControlDispatcher} that the view - * uses by default, calls {@link Player#prepare()}. If you wish to customize this behaviour, - * you can provide a custom implementation of {@link - * ControlDispatcher#dispatchPrepare(Player)}. + * @deprecated Use a {@link ForwardingPlayer} and pass it to {@link #setPlayer(Player)} instead. + * You can also customize some operations when configuring the player (for example by using + * {@link SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)}). */ - @SuppressWarnings("deprecation") @Deprecated - public void setPlaybackPreparer(@Nullable PlaybackPreparer playbackPreparer) { - Assertions.checkStateNotNull(controller); - controller.setPlaybackPreparer(playbackPreparer); - } - - /** - * Sets the {@link ControlDispatcher}. - * - * @param controlDispatcher The {@link ControlDispatcher}. - */ public void setControlDispatcher(ControlDispatcher controlDispatcher) { Assertions.checkStateNotNull(controller); controller.setControlDispatcher(controlDispatcher); @@ -1085,14 +1082,14 @@ public void setAspectRatioListener( *
  • {@link SurfaceView} by default, or if the {@code surface_type} attribute is set to {@code * surface_view}. *
  • {@link TextureView} if {@code surface_type} is {@code texture_view}. - *
  • {@link SphericalGLSurfaceView} if {@code surface_type} is {@code + *
  • {@code SphericalGLSurfaceView} if {@code surface_type} is {@code * spherical_gl_surface_view}. - *
  • {@link VideoDecoderGLSurfaceView} if {@code surface_type} is {@code + *
  • {@code VideoDecoderGLSurfaceView} if {@code surface_type} is {@code * video_decoder_gl_surface_view}. *
  • {@code null} if {@code surface_type} is {@code none}. * * - * @return The {@link SurfaceView}, {@link TextureView}, {@link SphericalGLSurfaceView}, {@link + * @return The {@link SurfaceView}, {@link TextureView}, {@code SphericalGLSurfaceView}, {@code * VideoDecoderGLSurfaceView} or {@code null}. */ @Nullable @@ -1310,21 +1307,28 @@ private void updateForCurrentTrackSelections(boolean isNewPlayer) { closeShutter(); } - if (TrackSelectionUtil.hasTrackOfType(player.getCurrentTrackSelections(), C.TRACK_TYPE_VIDEO)) { - // Video enabled so artwork must be hidden. If the shutter is closed, it will be opened in - // onRenderedFirstFrame(). - hideArtwork(); - return; + TrackSelectionArray trackSelections = player.getCurrentTrackSelections(); + for (int i = 0; i < trackSelections.length; i++) { + @Nullable TrackSelection trackSelection = trackSelections.get(i); + if (trackSelection != null) { + for (int j = 0; j < trackSelection.length(); j++) { + Format format = trackSelection.getFormat(j); + if (MimeTypes.getTrackType(format.sampleMimeType) == C.TRACK_TYPE_VIDEO) { + // Video enabled, so artwork must be hidden. If the shutter is closed, it will be opened + // in onRenderedFirstFrame(). + hideArtwork(); + return; + } + } + } } // Video disabled so the shutter must be closed. closeShutter(); // Display artwork if enabled and available, else hide it. if (useArtwork()) { - for (Metadata metadata : player.getCurrentStaticMetadata()) { - if (setArtworkFromMetadata(metadata)) { - return; - } + if (setArtworkFromMediaMetadata(player.getMediaMetadata())) { + return; } if (setDrawableArtwork(defaultArtwork)) { return; @@ -1335,33 +1339,14 @@ private void updateForCurrentTrackSelections(boolean isNewPlayer) { } @RequiresNonNull("artworkView") - private boolean setArtworkFromMetadata(Metadata metadata) { - boolean isArtworkSet = false; - int currentPictureType = PICTURE_TYPE_NOT_SET; - for (int i = 0; i < metadata.length(); i++) { - Metadata.Entry metadataEntry = metadata.get(i); - int pictureType; - byte[] bitmapData; - if (metadataEntry instanceof ApicFrame) { - bitmapData = ((ApicFrame) metadataEntry).pictureData; - pictureType = ((ApicFrame) metadataEntry).pictureType; - } else if (metadataEntry instanceof PictureFrame) { - bitmapData = ((PictureFrame) metadataEntry).pictureData; - pictureType = ((PictureFrame) metadataEntry).pictureType; - } else { - continue; - } - // Prefer the first front cover picture. If there aren't any, prefer the first picture. - if (currentPictureType == PICTURE_TYPE_NOT_SET || pictureType == PICTURE_TYPE_FRONT_COVER) { - Bitmap bitmap = BitmapFactory.decodeByteArray(bitmapData, 0, bitmapData.length); - isArtworkSet = setDrawableArtwork(new BitmapDrawable(getResources(), bitmap)); - currentPictureType = pictureType; - if (currentPictureType == PICTURE_TYPE_FRONT_COVER) { - break; - } - } + private boolean setArtworkFromMediaMetadata(MediaMetadata mediaMetadata) { + if (mediaMetadata.artworkData == null) { + return false; } - return isArtworkSet; + Bitmap bitmap = + BitmapFactory.decodeByteArray( + mediaMetadata.artworkData, /* offset= */ 0, mediaMetadata.artworkData.length); + return setDrawableArtwork(new BitmapDrawable(getResources(), bitmap)); } @RequiresNonNull("artworkView") @@ -1411,7 +1396,7 @@ private void updateErrorMessage() { errorMessageView.setVisibility(View.VISIBLE); return; } - @Nullable ExoPlaybackException error = player != null ? player.getPlayerError() : null; + @Nullable PlaybackException error = player != null ? player.getPlayerError() : null; if (error != null && errorMessageProvider != null) { CharSequence errorMessage = errorMessageProvider.getErrorMessage(error).second; errorMessageView.setText(errorMessage); @@ -1444,6 +1429,38 @@ private void updateControllerVisibility() { } } + private void updateAspectRatio() { + VideoSize videoSize = player != null ? player.getVideoSize() : VideoSize.UNKNOWN; + int width = videoSize.width; + int height = videoSize.height; + int unappliedRotationDegrees = videoSize.unappliedRotationDegrees; + float videoAspectRatio = + (height == 0 || width == 0) ? 0 : (width * videoSize.pixelWidthHeightRatio) / height; + + if (surfaceView instanceof TextureView) { + // Try to apply rotation transformation when our surface is a TextureView. + if (videoAspectRatio > 0 + && (unappliedRotationDegrees == 90 || unappliedRotationDegrees == 270)) { + // We will apply a rotation 90/270 degree to the output texture of the TextureView. + // In this case, the output video's width and height will be swapped. + videoAspectRatio = 1 / videoAspectRatio; + } + if (textureViewRotation != 0) { + surfaceView.removeOnLayoutChangeListener(componentListener); + } + textureViewRotation = unappliedRotationDegrees; + if (textureViewRotation != 0) { + // The texture view's dimensions might be changed after layout step. + // So add an OnLayoutChangeListener to apply rotation after layout step. + surfaceView.addOnLayoutChangeListener(componentListener); + } + applyTextureViewRotation((TextureView) surfaceView, textureViewRotation); + } + + onContentAspectRatioChanged( + contentFrame, surfaceViewIgnoresVideoAspectRatio ? 0 : videoAspectRatio); + } + @RequiresApi(23) private static void configureEditModeLogoV23(Resources resources, ImageView logo) { logo.setImageDrawable(resources.getDrawable(R.drawable.exo_edit_mode_logo, null)); @@ -1509,7 +1526,7 @@ public ComponentListener() { period = new Period(); } - // TextOutput implementation + // Player.Listener implementation @Override public void onCues(List cues) { @@ -1518,35 +1535,9 @@ public void onCues(List cues) { } } - // VideoListener implementation - @Override - public void onVideoSizeChanged( - int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) { - float videoAspectRatio = - (height == 0 || width == 0) ? 1 : (width * pixelWidthHeightRatio) / height; - - if (surfaceView instanceof TextureView) { - // Try to apply rotation transformation when our surface is a TextureView. - if (unappliedRotationDegrees == 90 || unappliedRotationDegrees == 270) { - // We will apply a rotation 90/270 degree to the output texture of the TextureView. - // In this case, the output video's width and height will be swapped. - videoAspectRatio = 1 / videoAspectRatio; - } - if (textureViewRotation != 0) { - surfaceView.removeOnLayoutChangeListener(this); - } - textureViewRotation = unappliedRotationDegrees; - if (textureViewRotation != 0) { - // The texture view's dimensions might be changed after layout step. - // So add an OnLayoutChangeListener to apply rotation after layout step. - surfaceView.addOnLayoutChangeListener(this); - } - applyTextureViewRotation((TextureView) surfaceView, textureViewRotation); - } - - onContentAspectRatioChanged( - contentFrame, surfaceViewIgnoresVideoAspectRatio ? 0 : videoAspectRatio); + public void onVideoSizeChanged(VideoSize videoSize) { + updateAspectRatio(); } @Override @@ -1557,7 +1548,7 @@ public void onRenderedFirstFrame() { } @Override - public void onTracksChanged(TrackGroupArray tracks, TrackSelectionArray selections) { + public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray selections) { // Suppress the update if transitioning to an unprepared period within the same window. This // is necessary to avoid closing the shutter when such a transition occurs. See: // https://github.com/google/ExoPlayer/issues/5507. @@ -1584,8 +1575,6 @@ public void onTracksChanged(TrackGroupArray tracks, TrackSelectionArray selectio updateForCurrentTrackSelections(/* isNewPlayer= */ false); } - // Player.EventListener implementation - @Override public void onPlaybackStateChanged(@Player.State int playbackState) { updateBuffering(); diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/SubtitlePainter.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/SubtitlePainter.java index 5037eb4a4ec..e21e0aa2dd5 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/SubtitlePainter.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/SubtitlePainter.java @@ -43,16 +43,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.RequiresNonNull; -/** - * Paints subtitle {@link Cue}s. - */ +/** Paints subtitle {@link Cue}s. */ /* package */ final class SubtitlePainter { private static final String TAG = "SubtitlePainter"; - /** - * Ratio of inner padding to font size. - */ + /** Ratio of inner padding to font size. */ private static final float INNER_PADDING_RATIO = 0.125f; // Styled dimensions. @@ -71,21 +67,17 @@ @Nullable private Alignment cueTextAlignment; @Nullable private Bitmap cueBitmap; private float cueLine; - @Cue.LineType - private int cueLineType; - @Cue.AnchorType - private int cueLineAnchor; + @Cue.LineType private int cueLineType; + @Cue.AnchorType private int cueLineAnchor; private float cuePosition; - @Cue.AnchorType - private int cuePositionAnchor; + @Cue.AnchorType private int cuePositionAnchor; private float cueSize; private float cueBitmapHeight; private int foregroundColor; private int backgroundColor; private int windowColor; private int edgeColor; - @CaptionStyleCompat.EdgeType - private int edgeType; + @CaptionStyleCompat.EdgeType private int edgeType; private float defaultTextSizePx; private float cueTextSizePx; private float bottomPaddingFraction; @@ -137,8 +129,8 @@ public SubtitlePainter(Context context) { * call, and so an instance of this class is able to optimize repeated calls to this method in * which the same parameters are passed. * - * @param cue The cue to draw. - * sizes embedded within the cue should be applied. Otherwise, it is ignored. + * @param cue The cue to draw. sizes embedded within the cue should be applied. Otherwise, it is + * ignored. * @param style The style to use when drawing the cue text. * @param defaultTextSizePx The default text size to use when drawing the text, in pixels. * @param cueTextSizePx The embedded text size of this cue, in pixels. @@ -291,8 +283,9 @@ private void setupTextLayout() { } Alignment textAlignment = cueTextAlignment == null ? Alignment.ALIGN_CENTER : cueTextAlignment; - textLayout = new StaticLayout(cueText, textPaint, availableWidth, textAlignment, spacingMult, - spacingAdd, true); + textLayout = + new StaticLayout( + cueText, textPaint, availableWidth, textAlignment, spacingMult, spacingAdd, true); int textHeight = textLayout.getHeight(); int textWidth = 0; int lineCount = textLayout.getLineCount(); @@ -364,8 +357,9 @@ private void setupTextLayout() { } // Update the derived drawing variables. - this.textLayout = new StaticLayout(cueText, textPaint, textWidth, textAlignment, spacingMult, - spacingAdd, true); + this.textLayout = + new StaticLayout( + cueText, textPaint, textWidth, textAlignment, spacingMult, spacingAdd, true); this.edgeLayout = new StaticLayout( cueTextEdge, textPaint, textWidth, textAlignment, spacingMult, spacingAdd, true); @@ -382,8 +376,10 @@ private void setupBitmapLayout() { float anchorX = parentLeft + (parentWidth * cuePosition); float anchorY = parentTop + (parentHeight * cueLine); int width = Math.round(parentWidth * cueSize); - int height = cueBitmapHeight != Cue.DIMEN_UNSET ? Math.round(parentHeight * cueBitmapHeight) - : Math.round(width * ((float) cueBitmap.getHeight() / cueBitmap.getWidth())); + int height = + cueBitmapHeight != Cue.DIMEN_UNSET + ? Math.round(parentHeight * cueBitmapHeight) + : Math.round(width * ((float) cueBitmap.getHeight() / cueBitmap.getWidth())); int x = Math.round( cuePositionAnchor == Cue.ANCHOR_TYPE_END @@ -474,5 +470,4 @@ private static boolean areCharSequencesEqual( // equals methods, so we perform one explicitly here. return first == second || (first != null && first.equals(second)); } - } diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/SubtitleView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/SubtitleView.java index 5926b2dbded..9731506ecd7 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/SubtitleView.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/SubtitleView.java @@ -231,8 +231,8 @@ public void setUserDefaultTextSize() { /** * Sets the text size to be a fraction of the view's remaining height after its top and bottom * padding have been subtracted. - *

    - * Equivalent to {@code #setFractionalTextSize(fractionOfHeight, false)}. + * + *

    Equivalent to {@code #setFractionalTextSize(fractionOfHeight, false)}. * * @param fractionOfHeight A fraction between 0 and 1. */ @@ -245,9 +245,9 @@ public void setFractionalTextSize(float fractionOfHeight) { * * @param fractionOfHeight A fraction between 0 and 1. * @param ignorePadding Set to true if {@code fractionOfHeight} should be interpreted as a - * fraction of this view's height ignoring any top and bottom padding. Set to false if - * {@code fractionOfHeight} should be interpreted as a fraction of this view's remaining - * height after the top and bottom padding has been subtracted. + * fraction of this view's height ignoring any top and bottom padding. Set to false if {@code + * fractionOfHeight} should be interpreted as a fraction of this view's remaining height after + * the top and bottom padding has been subtracted. */ public void setFractionalTextSize(float fractionOfHeight, boolean ignorePadding) { setTextSize( @@ -264,8 +264,8 @@ private void setTextSize(@Cue.TextSizeType int textSizeType, float textSize) { } /** - * Sets whether styling embedded within the cues should be applied. Enabled by default. - * Overrides any setting made with {@link SubtitleView#setApplyEmbeddedFontSizes}. + * Sets whether styling embedded within the cues should be applied. Enabled by default. Overrides + * any setting made with {@link SubtitleView#setApplyEmbeddedFontSizes}. * * @param applyEmbeddedStyles Whether styling embedded within the cues should be applied. */ @@ -275,8 +275,8 @@ public void setApplyEmbeddedStyles(boolean applyEmbeddedStyles) { } /** - * Sets whether font sizes embedded within the cues should be applied. Enabled by default. - * Only takes effect if {@link SubtitleView#setApplyEmbeddedStyles} is set to true. + * Sets whether font sizes embedded within the cues should be applied. Enabled by default. Only + * takes effect if {@link SubtitleView#setApplyEmbeddedStyles} is set to true. * * @param applyEmbeddedFontSizes Whether font sizes embedded within the cues should be applied. */ @@ -306,11 +306,11 @@ public void setStyle(CaptionStyleCompat style) { } /** - * Sets the bottom padding fraction to apply when {@link Cue#line} is {@link Cue#DIMEN_UNSET}, - * as a fraction of the view's remaining height after its top and bottom padding have been + * Sets the bottom padding fraction to apply when {@link Cue#line} is {@link Cue#DIMEN_UNSET}, as + * a fraction of the view's remaining height after its top and bottom padding have been * subtracted. - *

    - * Note that this padding is applied in addition to any standard view padding. + * + *

    Note that this padding is applied in addition to any standard view padding. * * @param bottomPaddingFraction The bottom padding fraction. */ @@ -384,5 +384,4 @@ private Cue removeEmbeddedStyling(Cue cue) { } return strippedCue.build(); } - } diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/TimeBar.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/TimeBar.java index 9e3f2e42ff4..467394f653e 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/TimeBar.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/TimeBar.java @@ -38,15 +38,13 @@ public interface TimeBar { */ void removeListener(OnScrubListener listener); - /** - * @see View#isEnabled() - */ + /** @see View#isEnabled() */ void setEnabled(boolean enabled); /** * Sets the position increment for key presses and accessibility actions, in milliseconds. - *

    - * Clears any increment specified in a preceding call to {@link #setKeyCountIncrement(int)}. + * + *

    Clears any increment specified in a preceding call to {@link #setKeyCountIncrement(int)}. * * @param time The time increment, in milliseconds. */ @@ -56,8 +54,8 @@ public interface TimeBar { * Sets the position increment for key presses and accessibility actions, as a number of * increments that divide the duration of the media. For example, passing 20 will cause key * presses to increment/decrement the position by 1/20th of the duration (if known). - *

    - * Clears any increment specified in a preceding call to {@link #setKeyTimeIncrement(long)}. + * + *

    Clears any increment specified in a preceding call to {@link #setKeyTimeIncrement(long)}. * * @param count The number of increments that divide the duration of the media. */ @@ -102,12 +100,10 @@ public interface TimeBar { * groups. * @param adGroupCount The number of ad groups. */ - void setAdGroupTimesMs(@Nullable long[] adGroupTimesMs, @Nullable boolean[] playedAdGroups, - int adGroupCount); + void setAdGroupTimesMs( + @Nullable long[] adGroupTimesMs, @Nullable boolean[] playedAdGroups, int adGroupCount); - /** - * Listener for scrubbing events. - */ + /** Listener for scrubbing events. */ interface OnScrubListener { /** @@ -135,5 +131,4 @@ interface OnScrubListener { */ void onScrubStop(TimeBar timeBar, long position, boolean canceled); } - } diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/TrackSelectionDialogBuilder.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/TrackSelectionDialogBuilder.java index be3fb9bc90f..86bb2428644 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/TrackSelectionDialogBuilder.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/TrackSelectionDialogBuilder.java @@ -256,13 +256,12 @@ private Dialog buildForPlatform() { } // Reflection calls can't verify null safety of return values or parameters. - @SuppressWarnings("nullness:argument.type.incompatible") + @SuppressWarnings("nullness:argument") @Nullable private Dialog buildForAndroidX() { try { // This method uses reflection to avoid a dependency on AndroidX appcompat that adds 800KB to // the APK size even with shrinking. See https://issuetracker.google.com/161514204. - // LINT.IfChange Class builderClazz = Class.forName("androidx.appcompat.app.AlertDialog$Builder"); Constructor builderConstructor = builderClazz.getConstructor(Context.class, int.class); Object builder = builderConstructor.newInstance(context, themeResId); @@ -283,7 +282,6 @@ private Dialog buildForAndroidX() { .getMethod("setNegativeButton", int.class, DialogInterface.OnClickListener.class) .invoke(builder, android.R.string.cancel, null); return (Dialog) builderClazz.getMethod("create").invoke(builder); - // LINT.ThenChange(../../../../../../../../proguard-rules.txt) } catch (ClassNotFoundException e) { // Expected if the AndroidX compat library is not available. return null; diff --git a/library/ui/src/main/res/values/attrs.xml b/library/ui/src/main/res/values/attrs.xml index bb4806db06a..6121aa1402f 100644 --- a/library/ui/src/main/res/values/attrs.xml +++ b/library/ui/src/main/res/values/attrs.xml @@ -58,8 +58,6 @@ - - @@ -109,8 +107,6 @@ - - @@ -147,8 +143,6 @@ - - @@ -179,8 +173,6 @@ - - @@ -208,8 +200,6 @@ - - diff --git a/library/ui/src/test/AndroidManifest.xml b/library/ui/src/test/AndroidManifest.xml index b8f75629695..0874d510e2c 100644 --- a/library/ui/src/test/AndroidManifest.xml +++ b/library/ui/src/test/AndroidManifest.xml @@ -15,6 +15,6 @@ ~ limitations under the License. --> - + diff --git a/library/ui/src/test/java/com/google/android/exoplayer2/ui/DefaultMediaDescriptionAdapterTest.java b/library/ui/src/test/java/com/google/android/exoplayer2/ui/DefaultMediaDescriptionAdapterTest.java new file mode 100644 index 00000000000..4ebe0f42e57 --- /dev/null +++ b/library/ui/src/test/java/com/google/android/exoplayer2/ui/DefaultMediaDescriptionAdapterTest.java @@ -0,0 +1,54 @@ +/* + * 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 com.google.android.exoplayer2.ui; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.MediaMetadata; +import com.google.android.exoplayer2.Player; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** Tests for the {@link DefaultMediaDescriptionAdapter}. */ +@RunWith(AndroidJUnit4.class) +public class DefaultMediaDescriptionAdapterTest { + + @Test + public void getters_returnMediaMetadataValues() { + Context context = ApplicationProvider.getApplicationContext(); + Player player = mock(Player.class); + MediaMetadata mediaMetadata = + new MediaMetadata.Builder().setDisplayTitle("display title").setArtist("artist").build(); + PendingIntent pendingIntent = + PendingIntent.getActivity(context, 0, new Intent(), PendingIntent.FLAG_IMMUTABLE); + DefaultMediaDescriptionAdapter adapter = new DefaultMediaDescriptionAdapter(pendingIntent); + + when(player.getMediaMetadata()).thenReturn(mediaMetadata); + + assertThat(adapter.createCurrentContentIntent(player)).isEqualTo(pendingIntent); + assertThat(adapter.getCurrentContentTitle(player).toString()) + .isEqualTo(mediaMetadata.displayTitle.toString()); + assertThat(adapter.getCurrentContentText(player).toString()) + .isEqualTo(mediaMetadata.artist.toString()); + } +} diff --git a/library/ui/src/test/java/com/google/android/exoplayer2/ui/HtmlUtilsTest.java b/library/ui/src/test/java/com/google/android/exoplayer2/ui/HtmlUtilsTest.java index 82ddfb42023..68469e88862 100644 --- a/library/ui/src/test/java/com/google/android/exoplayer2/ui/HtmlUtilsTest.java +++ b/library/ui/src/test/java/com/google/android/exoplayer2/ui/HtmlUtilsTest.java @@ -21,9 +21,11 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Tests for {@link HtmlUtils}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public class HtmlUtilsTest { @Test diff --git a/library/ui/src/test/java/com/google/android/exoplayer2/ui/SpannedToHtmlConverterTest.java b/library/ui/src/test/java/com/google/android/exoplayer2/ui/SpannedToHtmlConverterTest.java index 09efaad7095..187dcf6204a 100644 --- a/library/ui/src/test/java/com/google/android/exoplayer2/ui/SpannedToHtmlConverterTest.java +++ b/library/ui/src/test/java/com/google/android/exoplayer2/ui/SpannedToHtmlConverterTest.java @@ -39,9 +39,11 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.annotation.Config; +import org.robolectric.annotation.internal.DoNotInstrument; /** Tests for {@link SpannedToHtmlConverter}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public class SpannedToHtmlConverterTest { private final float displayDensity; diff --git a/library/ui/src/test/java/com/google/android/exoplayer2/ui/SubtitleViewUtilsTest.java b/library/ui/src/test/java/com/google/android/exoplayer2/ui/SubtitleViewUtilsTest.java index 1ad530cc113..1b211626c33 100644 --- a/library/ui/src/test/java/com/google/android/exoplayer2/ui/SubtitleViewUtilsTest.java +++ b/library/ui/src/test/java/com/google/android/exoplayer2/ui/SubtitleViewUtilsTest.java @@ -34,9 +34,11 @@ import com.google.android.exoplayer2.text.span.TextEmphasisSpan; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.internal.DoNotInstrument; /** Tests for {@link SubtitleView}. */ @RunWith(AndroidJUnit4.class) +@DoNotInstrument public class SubtitleViewUtilsTest { private static final Cue CUE = buildCue(); diff --git a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/CommonEncryptionDrmTest.java b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/CommonEncryptionDrmTest.java index 0f2c856dd7c..8f2d9c6f210 100644 --- a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/CommonEncryptionDrmTest.java +++ b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/CommonEncryptionDrmTest.java @@ -40,10 +40,18 @@ public final class CommonEncryptionDrmTest { private static final String[] IDS_VIDEO = new String[] {"1", "2"}; // Seeks help reproduce playback issues in certain devices. - private static final ActionSchedule ACTION_SCHEDULE_WITH_SEEKS = new ActionSchedule.Builder(TAG) - .waitForPlaybackState(Player.STATE_READY).delay(30000).seekAndWait(300000).delay(10000) - .seekAndWait(270000).delay(10000).seekAndWait(200000).delay(10000).seekAndWait(732000) - .build(); + private static final ActionSchedule ACTION_SCHEDULE_WITH_SEEKS = + new ActionSchedule.Builder(TAG) + .waitForPlaybackState(Player.STATE_READY) + .delay(30000) + .seekAndWait(300000) + .delay(10000) + .seekAndWait(270000) + .delay(10000) + .seekAndWait(200000) + .delay(10000) + .seekAndWait(732000) + .build(); @Rule public ActivityTestRule testRule = new ActivityTestRule<>(HostActivity.class); diff --git a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashDownloadTest.java b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashDownloadTest.java index c14295b027e..418cb691762 100644 --- a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashDownloadTest.java +++ b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashDownloadTest.java @@ -128,5 +128,4 @@ private DashDownloader downloadContent() throws Exception { new MediaItem.Builder().setUri(MANIFEST_URI).setStreamKeys(keys).build(), cacheDataSourceFactory); } - } diff --git a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashStreamingTest.java b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashStreamingTest.java index c3e82ec33da..495372ab48e 100644 --- a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashStreamingTest.java +++ b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashStreamingTest.java @@ -42,49 +42,75 @@ public final class DashStreamingTest { private static final String TAG = "DashStreamingTest"; - private static final ActionSchedule SEEKING_SCHEDULE = new ActionSchedule.Builder(TAG) - .waitForPlaybackState(Player.STATE_READY) - .delay(10000).seekAndWait(15000) - .delay(10000).seek(30000).seek(31000).seek(32000).seek(33000).seekAndWait(34000) - .delay(1000).pause().delay(1000).play() - .delay(1000).pause().seekAndWait(120000).delay(1000).play() - .build(); - private static final ActionSchedule RENDERER_DISABLING_SCHEDULE = new ActionSchedule.Builder(TAG) - .waitForPlaybackState(Player.STATE_READY) - // Wait 10 seconds, disable the video renderer, wait another 10 seconds and enable it again. - .delay(10000).disableRenderer(DashTestRunner.VIDEO_RENDERER_INDEX) - .delay(10000).enableRenderer(DashTestRunner.VIDEO_RENDERER_INDEX) - // Ditto for the audio renderer. - .delay(10000).disableRenderer(DashTestRunner.AUDIO_RENDERER_INDEX) - .delay(10000).enableRenderer(DashTestRunner.AUDIO_RENDERER_INDEX) - // Wait 10 seconds, then disable and enable the video renderer 5 times in quick succession. - .delay(10000).disableRenderer(DashTestRunner.VIDEO_RENDERER_INDEX) - .enableRenderer(DashTestRunner.VIDEO_RENDERER_INDEX) - .disableRenderer(DashTestRunner.VIDEO_RENDERER_INDEX) - .enableRenderer(DashTestRunner.VIDEO_RENDERER_INDEX) - .disableRenderer(DashTestRunner.VIDEO_RENDERER_INDEX) - .enableRenderer(DashTestRunner.VIDEO_RENDERER_INDEX) - .disableRenderer(DashTestRunner.VIDEO_RENDERER_INDEX) - .enableRenderer(DashTestRunner.VIDEO_RENDERER_INDEX) - .disableRenderer(DashTestRunner.VIDEO_RENDERER_INDEX) - .enableRenderer(DashTestRunner.VIDEO_RENDERER_INDEX) - // Ditto for the audio renderer. - .delay(10000).disableRenderer(DashTestRunner.AUDIO_RENDERER_INDEX) - .enableRenderer(DashTestRunner.AUDIO_RENDERER_INDEX) - .disableRenderer(DashTestRunner.AUDIO_RENDERER_INDEX) - .enableRenderer(DashTestRunner.AUDIO_RENDERER_INDEX) - .disableRenderer(DashTestRunner.AUDIO_RENDERER_INDEX) - .enableRenderer(DashTestRunner.AUDIO_RENDERER_INDEX) - .disableRenderer(DashTestRunner.AUDIO_RENDERER_INDEX) - .enableRenderer(DashTestRunner.AUDIO_RENDERER_INDEX) - .disableRenderer(DashTestRunner.AUDIO_RENDERER_INDEX) - .enableRenderer(DashTestRunner.AUDIO_RENDERER_INDEX) - // Wait 10 seconds, detach the surface, wait another 10 seconds and attach it again. - .delay(10000).clearVideoSurface() - .delay(10000).setVideoSurface() - // Wait 10 seconds, then seek to near end. - .delay(10000).seek(120000) - .build(); + private static final ActionSchedule SEEKING_SCHEDULE = + new ActionSchedule.Builder(TAG) + .waitForPlaybackState(Player.STATE_READY) + .delay(10000) + .seekAndWait(15000) + .delay(10000) + .seek(30000) + .seek(31000) + .seek(32000) + .seek(33000) + .seekAndWait(34000) + .delay(1000) + .pause() + .delay(1000) + .play() + .delay(1000) + .pause() + .seekAndWait(120000) + .delay(1000) + .play() + .build(); + private static final ActionSchedule RENDERER_DISABLING_SCHEDULE = + new ActionSchedule.Builder(TAG) + .waitForPlaybackState(Player.STATE_READY) + // Wait 10 seconds, disable the video renderer, wait another 10 seconds and enable it + // again. + .delay(10000) + .disableRenderer(DashTestRunner.VIDEO_RENDERER_INDEX) + .delay(10000) + .enableRenderer(DashTestRunner.VIDEO_RENDERER_INDEX) + // Ditto for the audio renderer. + .delay(10000) + .disableRenderer(DashTestRunner.AUDIO_RENDERER_INDEX) + .delay(10000) + .enableRenderer(DashTestRunner.AUDIO_RENDERER_INDEX) + // Wait 10 seconds, then disable and enable the video renderer 5 times in quick + // succession. + .delay(10000) + .disableRenderer(DashTestRunner.VIDEO_RENDERER_INDEX) + .enableRenderer(DashTestRunner.VIDEO_RENDERER_INDEX) + .disableRenderer(DashTestRunner.VIDEO_RENDERER_INDEX) + .enableRenderer(DashTestRunner.VIDEO_RENDERER_INDEX) + .disableRenderer(DashTestRunner.VIDEO_RENDERER_INDEX) + .enableRenderer(DashTestRunner.VIDEO_RENDERER_INDEX) + .disableRenderer(DashTestRunner.VIDEO_RENDERER_INDEX) + .enableRenderer(DashTestRunner.VIDEO_RENDERER_INDEX) + .disableRenderer(DashTestRunner.VIDEO_RENDERER_INDEX) + .enableRenderer(DashTestRunner.VIDEO_RENDERER_INDEX) + // Ditto for the audio renderer. + .delay(10000) + .disableRenderer(DashTestRunner.AUDIO_RENDERER_INDEX) + .enableRenderer(DashTestRunner.AUDIO_RENDERER_INDEX) + .disableRenderer(DashTestRunner.AUDIO_RENDERER_INDEX) + .enableRenderer(DashTestRunner.AUDIO_RENDERER_INDEX) + .disableRenderer(DashTestRunner.AUDIO_RENDERER_INDEX) + .enableRenderer(DashTestRunner.AUDIO_RENDERER_INDEX) + .disableRenderer(DashTestRunner.AUDIO_RENDERER_INDEX) + .enableRenderer(DashTestRunner.AUDIO_RENDERER_INDEX) + .disableRenderer(DashTestRunner.AUDIO_RENDERER_INDEX) + .enableRenderer(DashTestRunner.AUDIO_RENDERER_INDEX) + // Wait 10 seconds, detach the surface, wait another 10 seconds and attach it again. + .delay(10000) + .clearVideoSurface() + .delay(10000) + .setVideoSurface() + // Wait 10 seconds, then seek to near end. + .delay(10000) + .seek(120000) + .build(); @Rule public ActivityTestRule testRule = new ActivityTestRule<>(HostActivity.class); @@ -124,8 +150,8 @@ public void h264Adaptive() throws Exception { .setManifestUrl(DashTestData.H264_MANIFEST) .setFullPlaybackNoSeeking(true) .setCanIncludeAdditionalVideoFormats(true) - .setAudioVideoFormats(DashTestData.AAC_AUDIO_REPRESENTATION_ID, - DashTestData.H264_CDD_ADAPTIVE) + .setAudioVideoFormats( + DashTestData.AAC_AUDIO_REPRESENTATION_ID, DashTestData.H264_CDD_ADAPTIVE) .run(); } @@ -142,8 +168,8 @@ public void h264AdaptiveWithSeeking() throws Exception { .setFullPlaybackNoSeeking(false) .setCanIncludeAdditionalVideoFormats(true) .setActionSchedule(SEEKING_SCHEDULE) - .setAudioVideoFormats(DashTestData.AAC_AUDIO_REPRESENTATION_ID, - DashTestData.H264_CDD_ADAPTIVE) + .setAudioVideoFormats( + DashTestData.AAC_AUDIO_REPRESENTATION_ID, DashTestData.H264_CDD_ADAPTIVE) .run(); } @@ -160,8 +186,8 @@ public void h264AdaptiveWithRendererDisabling() throws Exception { .setFullPlaybackNoSeeking(false) .setCanIncludeAdditionalVideoFormats(true) .setActionSchedule(RENDERER_DISABLING_SCHEDULE) - .setAudioVideoFormats(DashTestData.AAC_AUDIO_REPRESENTATION_ID, - DashTestData.H264_CDD_ADAPTIVE) + .setAudioVideoFormats( + DashTestData.AAC_AUDIO_REPRESENTATION_ID, DashTestData.H264_CDD_ADAPTIVE) .run(); } @@ -193,8 +219,8 @@ public void h265AdaptiveV24() throws Exception { .setManifestUrl(DashTestData.H265_MANIFEST) .setFullPlaybackNoSeeking(true) .setCanIncludeAdditionalVideoFormats(true) - .setAudioVideoFormats(DashTestData.AAC_AUDIO_REPRESENTATION_ID, - DashTestData.H265_CDD_ADAPTIVE) + .setAudioVideoFormats( + DashTestData.AAC_AUDIO_REPRESENTATION_ID, DashTestData.H265_CDD_ADAPTIVE) .run(); } @@ -210,8 +236,8 @@ public void h265AdaptiveWithSeekingV24() throws Exception { .setFullPlaybackNoSeeking(false) .setCanIncludeAdditionalVideoFormats(true) .setActionSchedule(SEEKING_SCHEDULE) - .setAudioVideoFormats(DashTestData.AAC_AUDIO_REPRESENTATION_ID, - DashTestData.H265_CDD_ADAPTIVE) + .setAudioVideoFormats( + DashTestData.AAC_AUDIO_REPRESENTATION_ID, DashTestData.H265_CDD_ADAPTIVE) .run(); } @@ -227,8 +253,8 @@ public void h265AdaptiveWithRendererDisablingV24() throws Exception { .setFullPlaybackNoSeeking(false) .setCanIncludeAdditionalVideoFormats(true) .setActionSchedule(RENDERER_DISABLING_SCHEDULE) - .setAudioVideoFormats(DashTestData.AAC_AUDIO_REPRESENTATION_ID, - DashTestData.H265_CDD_ADAPTIVE) + .setAudioVideoFormats( + DashTestData.AAC_AUDIO_REPRESENTATION_ID, DashTestData.H265_CDD_ADAPTIVE) .run(); } @@ -245,8 +271,8 @@ public void vp9Fixed360pV23() throws Exception { .setManifestUrl(DashTestData.VP9_MANIFEST) .setFullPlaybackNoSeeking(true) .setCanIncludeAdditionalVideoFormats(false) - .setAudioVideoFormats(DashTestData.VP9_VORBIS_AUDIO_REPRESENTATION_ID, - DashTestData.VP9_CDD_FIXED) + .setAudioVideoFormats( + DashTestData.VP9_VORBIS_AUDIO_REPRESENTATION_ID, DashTestData.VP9_CDD_FIXED) .run(); } @@ -261,8 +287,8 @@ public void vp9AdaptiveV24() throws Exception { .setManifestUrl(DashTestData.VP9_MANIFEST) .setFullPlaybackNoSeeking(true) .setCanIncludeAdditionalVideoFormats(true) - .setAudioVideoFormats(DashTestData.VP9_VORBIS_AUDIO_REPRESENTATION_ID, - DashTestData.VP9_CDD_ADAPTIVE) + .setAudioVideoFormats( + DashTestData.VP9_VORBIS_AUDIO_REPRESENTATION_ID, DashTestData.VP9_CDD_ADAPTIVE) .run(); } @@ -278,8 +304,8 @@ public void vp9AdaptiveWithSeekingV24() throws Exception { .setFullPlaybackNoSeeking(false) .setCanIncludeAdditionalVideoFormats(true) .setActionSchedule(SEEKING_SCHEDULE) - .setAudioVideoFormats(DashTestData.VP9_VORBIS_AUDIO_REPRESENTATION_ID, - DashTestData.VP9_CDD_ADAPTIVE) + .setAudioVideoFormats( + DashTestData.VP9_VORBIS_AUDIO_REPRESENTATION_ID, DashTestData.VP9_CDD_ADAPTIVE) .run(); } @@ -295,8 +321,8 @@ public void vp9AdaptiveWithRendererDisablingV24() throws Exception { .setFullPlaybackNoSeeking(false) .setCanIncludeAdditionalVideoFormats(true) .setActionSchedule(RENDERER_DISABLING_SCHEDULE) - .setAudioVideoFormats(DashTestData.VP9_VORBIS_AUDIO_REPRESENTATION_ID, - DashTestData.VP9_CDD_ADAPTIVE) + .setAudioVideoFormats( + DashTestData.VP9_VORBIS_AUDIO_REPRESENTATION_ID, DashTestData.VP9_CDD_ADAPTIVE) .run(); } @@ -314,7 +340,8 @@ public void test23FpsH264FixedV23() throws Exception { .setManifestUrl(DashTestData.H264_23_MANIFEST) .setFullPlaybackNoSeeking(true) .setCanIncludeAdditionalVideoFormats(false) - .setAudioVideoFormats(DashTestData.AAC_AUDIO_REPRESENTATION_ID, + .setAudioVideoFormats( + DashTestData.AAC_AUDIO_REPRESENTATION_ID, DashTestData.H264_BASELINE_480P_23FPS_VIDEO_REPRESENTATION_ID) .run(); } @@ -331,7 +358,8 @@ public void test24FpsH264FixedV23() throws Exception { .setManifestUrl(DashTestData.H264_24_MANIFEST) .setFullPlaybackNoSeeking(true) .setCanIncludeAdditionalVideoFormats(false) - .setAudioVideoFormats(DashTestData.AAC_AUDIO_REPRESENTATION_ID, + .setAudioVideoFormats( + DashTestData.AAC_AUDIO_REPRESENTATION_ID, DashTestData.H264_BASELINE_480P_24FPS_VIDEO_REPRESENTATION_ID) .run(); } @@ -348,7 +376,8 @@ public void test29FpsH264FixedV23() throws Exception { .setManifestUrl(DashTestData.H264_29_MANIFEST) .setFullPlaybackNoSeeking(true) .setCanIncludeAdditionalVideoFormats(false) - .setAudioVideoFormats(DashTestData.AAC_AUDIO_REPRESENTATION_ID, + .setAudioVideoFormats( + DashTestData.AAC_AUDIO_REPRESENTATION_ID, DashTestData.H264_BASELINE_480P_29FPS_VIDEO_REPRESENTATION_ID) .run(); } @@ -368,8 +397,8 @@ public void widevineH264FixedV18() throws Exception { .setWidevineInfo(MimeTypes.VIDEO_H264, true) .setFullPlaybackNoSeeking(true) .setCanIncludeAdditionalVideoFormats(false) - .setAudioVideoFormats(DashTestData.WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, - DashTestData.WIDEVINE_H264_CDD_FIXED) + .setAudioVideoFormats( + DashTestData.WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, DashTestData.WIDEVINE_H264_CDD_FIXED) .run(); } @@ -387,7 +416,8 @@ public void widevineH264AdaptiveV18() throws Exception { .setWidevineInfo(MimeTypes.VIDEO_H264, true) .setFullPlaybackNoSeeking(true) .setCanIncludeAdditionalVideoFormats(true) - .setAudioVideoFormats(DashTestData.WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, + .setAudioVideoFormats( + DashTestData.WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, DashTestData.WIDEVINE_H264_CDD_ADAPTIVE) .run(); } @@ -407,7 +437,8 @@ public void widevineH264AdaptiveWithSeekingV18() throws Exception { .setFullPlaybackNoSeeking(false) .setCanIncludeAdditionalVideoFormats(true) .setActionSchedule(SEEKING_SCHEDULE) - .setAudioVideoFormats(DashTestData.WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, + .setAudioVideoFormats( + DashTestData.WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, DashTestData.WIDEVINE_H264_CDD_ADAPTIVE) .run(); } @@ -427,7 +458,8 @@ public void widevineH264AdaptiveWithRendererDisablingV18() throws Exception { .setFullPlaybackNoSeeking(false) .setCanIncludeAdditionalVideoFormats(true) .setActionSchedule(RENDERER_DISABLING_SCHEDULE) - .setAudioVideoFormats(DashTestData.WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, + .setAudioVideoFormats( + DashTestData.WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, DashTestData.WIDEVINE_H264_CDD_ADAPTIVE) .run(); } @@ -446,8 +478,8 @@ public void widevineH265FixedV23() throws Exception { .setWidevineInfo(MimeTypes.VIDEO_H265, true) .setFullPlaybackNoSeeking(true) .setCanIncludeAdditionalVideoFormats(false) - .setAudioVideoFormats(DashTestData.WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, - DashTestData.WIDEVINE_H265_CDD_FIXED) + .setAudioVideoFormats( + DashTestData.WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, DashTestData.WIDEVINE_H265_CDD_FIXED) .run(); } @@ -463,7 +495,8 @@ public void widevineH265AdaptiveV24() throws Exception { .setWidevineInfo(MimeTypes.VIDEO_H265, true) .setFullPlaybackNoSeeking(true) .setCanIncludeAdditionalVideoFormats(true) - .setAudioVideoFormats(DashTestData.WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, + .setAudioVideoFormats( + DashTestData.WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, DashTestData.WIDEVINE_H265_CDD_ADAPTIVE) .run(); } @@ -481,7 +514,8 @@ public void widevineH265AdaptiveWithSeekingV24() throws Exception { .setFullPlaybackNoSeeking(false) .setCanIncludeAdditionalVideoFormats(true) .setActionSchedule(SEEKING_SCHEDULE) - .setAudioVideoFormats(DashTestData.WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, + .setAudioVideoFormats( + DashTestData.WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, DashTestData.WIDEVINE_H265_CDD_ADAPTIVE) .run(); } @@ -499,7 +533,8 @@ public void widevineH265AdaptiveWithRendererDisablingV24() throws Exception { .setFullPlaybackNoSeeking(false) .setCanIncludeAdditionalVideoFormats(true) .setActionSchedule(RENDERER_DISABLING_SCHEDULE) - .setAudioVideoFormats(DashTestData.WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, + .setAudioVideoFormats( + DashTestData.WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, DashTestData.WIDEVINE_H265_CDD_ADAPTIVE) .run(); } @@ -518,7 +553,8 @@ public void widevineVp9Fixed360pV23() throws Exception { .setWidevineInfo(MimeTypes.VIDEO_VP9, true) .setFullPlaybackNoSeeking(true) .setCanIncludeAdditionalVideoFormats(false) - .setAudioVideoFormats(DashTestData.WIDEVINE_VP9_AAC_AUDIO_REPRESENTATION_ID, + .setAudioVideoFormats( + DashTestData.WIDEVINE_VP9_AAC_AUDIO_REPRESENTATION_ID, DashTestData.WIDEVINE_VP9_CDD_FIXED) .run(); } @@ -535,7 +571,8 @@ public void widevineVp9AdaptiveV24() throws Exception { .setWidevineInfo(MimeTypes.VIDEO_VP9, true) .setFullPlaybackNoSeeking(true) .setCanIncludeAdditionalVideoFormats(true) - .setAudioVideoFormats(DashTestData.WIDEVINE_VP9_AAC_AUDIO_REPRESENTATION_ID, + .setAudioVideoFormats( + DashTestData.WIDEVINE_VP9_AAC_AUDIO_REPRESENTATION_ID, DashTestData.WIDEVINE_VP9_CDD_ADAPTIVE) .run(); } @@ -553,7 +590,8 @@ public void widevineVp9AdaptiveWithSeekingV24() throws Exception { .setFullPlaybackNoSeeking(false) .setCanIncludeAdditionalVideoFormats(true) .setActionSchedule(SEEKING_SCHEDULE) - .setAudioVideoFormats(DashTestData.WIDEVINE_VP9_AAC_AUDIO_REPRESENTATION_ID, + .setAudioVideoFormats( + DashTestData.WIDEVINE_VP9_AAC_AUDIO_REPRESENTATION_ID, DashTestData.WIDEVINE_VP9_CDD_ADAPTIVE) .run(); } @@ -571,7 +609,8 @@ public void widevineVp9AdaptiveWithRendererDisablingV24() throws Exception { .setFullPlaybackNoSeeking(false) .setCanIncludeAdditionalVideoFormats(true) .setActionSchedule(RENDERER_DISABLING_SCHEDULE) - .setAudioVideoFormats(DashTestData.WIDEVINE_VP9_AAC_AUDIO_REPRESENTATION_ID, + .setAudioVideoFormats( + DashTestData.WIDEVINE_VP9_AAC_AUDIO_REPRESENTATION_ID, DashTestData.WIDEVINE_VP9_CDD_ADAPTIVE) .run(); } @@ -591,7 +630,8 @@ public void widevine23FpsH264FixedV23() throws Exception { .setWidevineInfo(MimeTypes.VIDEO_H264, true) .setFullPlaybackNoSeeking(true) .setCanIncludeAdditionalVideoFormats(false) - .setAudioVideoFormats(DashTestData.WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, + .setAudioVideoFormats( + DashTestData.WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, DashTestData.WIDEVINE_H264_BASELINE_480P_23FPS_VIDEO_REPRESENTATION_ID) .run(); } @@ -609,7 +649,8 @@ public void widevine24FpsH264FixedV23() throws Exception { .setWidevineInfo(MimeTypes.VIDEO_H264, true) .setFullPlaybackNoSeeking(true) .setCanIncludeAdditionalVideoFormats(false) - .setAudioVideoFormats(DashTestData.WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, + .setAudioVideoFormats( + DashTestData.WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, DashTestData.WIDEVINE_H264_BASELINE_480P_24FPS_VIDEO_REPRESENTATION_ID) .run(); } @@ -627,7 +668,8 @@ public void widevine29FpsH264FixedV23() throws Exception { .setWidevineInfo(MimeTypes.VIDEO_H264, true) .setFullPlaybackNoSeeking(true) .setCanIncludeAdditionalVideoFormats(false) - .setAudioVideoFormats(DashTestData.WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, + .setAudioVideoFormats( + DashTestData.WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, DashTestData.WIDEVINE_H264_BASELINE_480P_29FPS_VIDEO_REPRESENTATION_ID) .run(); } @@ -681,5 +723,4 @@ private static boolean shouldSkipAdaptiveTest(String mimeType) throws DecoderQue MediaCodecUtil.getDecoderInfo(mimeType, /* secure= */ false, /* tunneling= */ false); return decoderInfo == null || !decoderInfo.adaptive; } - } diff --git a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashTestData.java b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashTestData.java index 4d888867f29..40037baba0b 100644 --- a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashTestData.java +++ b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashTestData.java @@ -53,20 +53,24 @@ public static final String H264_MAIN_240P_VIDEO_REPRESENTATION_ID = "avc-main-240"; public static final String H264_MAIN_480P_VIDEO_REPRESENTATION_ID = "avc-main-480"; // The highest quality H264 format mandated by the Android CDD. - public static final String H264_CDD_FIXED = Util.SDK_INT < 23 - ? H264_BASELINE_480P_VIDEO_REPRESENTATION_ID : H264_MAIN_480P_VIDEO_REPRESENTATION_ID; + public static final String H264_CDD_FIXED = + Util.SDK_INT < 23 + ? H264_BASELINE_480P_VIDEO_REPRESENTATION_ID + : H264_MAIN_480P_VIDEO_REPRESENTATION_ID; // Multiple H264 formats mandated by the Android CDD. Note: The CDD actually mandated main profile // support from API level 23, but we opt to test only from 24 due to known issues on API level 23 // when switching between baseline and main profiles on certain devices. - public static final String[] H264_CDD_ADAPTIVE = Util.SDK_INT < 24 - ? new String[] { - H264_BASELINE_240P_VIDEO_REPRESENTATION_ID, - H264_BASELINE_480P_VIDEO_REPRESENTATION_ID} - : new String[] { - H264_BASELINE_240P_VIDEO_REPRESENTATION_ID, - H264_BASELINE_480P_VIDEO_REPRESENTATION_ID, - H264_MAIN_240P_VIDEO_REPRESENTATION_ID, - H264_MAIN_480P_VIDEO_REPRESENTATION_ID}; + public static final String[] H264_CDD_ADAPTIVE = + Util.SDK_INT < 24 + ? new String[] { + H264_BASELINE_240P_VIDEO_REPRESENTATION_ID, H264_BASELINE_480P_VIDEO_REPRESENTATION_ID + } + : new String[] { + H264_BASELINE_240P_VIDEO_REPRESENTATION_ID, + H264_BASELINE_480P_VIDEO_REPRESENTATION_ID, + H264_MAIN_240P_VIDEO_REPRESENTATION_ID, + H264_MAIN_480P_VIDEO_REPRESENTATION_ID + }; public static final String H264_BASELINE_480P_23FPS_VIDEO_REPRESENTATION_ID = "avc-baseline-480-23"; @@ -82,8 +86,8 @@ // Multiple H265 formats mandated by the Android CDD. public static final String[] H265_CDD_ADAPTIVE = new String[] { - H265_BASELINE_288P_VIDEO_REPRESENTATION_ID, - H265_BASELINE_360P_VIDEO_REPRESENTATION_ID}; + H265_BASELINE_288P_VIDEO_REPRESENTATION_ID, H265_BASELINE_360P_VIDEO_REPRESENTATION_ID + }; public static final String VP9_VORBIS_AUDIO_REPRESENTATION_ID = "4"; public static final String VP9_180P_VIDEO_REPRESENTATION_ID = "0"; @@ -92,9 +96,7 @@ public static final String VP9_CDD_FIXED = VP9_360P_VIDEO_REPRESENTATION_ID; // Multiple VP9 formats mandated by the Android CDD. public static final String[] VP9_CDD_ADAPTIVE = - new String[] { - VP9_180P_VIDEO_REPRESENTATION_ID, - VP9_360P_VIDEO_REPRESENTATION_ID}; + new String[] {VP9_180P_VIDEO_REPRESENTATION_ID, VP9_360P_VIDEO_REPRESENTATION_ID}; // Widevine encrypted content representation ids. public static final String WIDEVINE_AAC_AUDIO_REPRESENTATION_ID = "0"; @@ -103,21 +105,25 @@ public static final String WIDEVINE_H264_MAIN_240P_VIDEO_REPRESENTATION_ID = "4"; public static final String WIDEVINE_H264_MAIN_480P_VIDEO_REPRESENTATION_ID = "5"; // The highest quality H264 format mandated by the Android CDD. - public static final String WIDEVINE_H264_CDD_FIXED = Util.SDK_INT < 23 - ? WIDEVINE_H264_BASELINE_480P_VIDEO_REPRESENTATION_ID - : WIDEVINE_H264_MAIN_480P_VIDEO_REPRESENTATION_ID; + public static final String WIDEVINE_H264_CDD_FIXED = + Util.SDK_INT < 23 + ? WIDEVINE_H264_BASELINE_480P_VIDEO_REPRESENTATION_ID + : WIDEVINE_H264_MAIN_480P_VIDEO_REPRESENTATION_ID; // Multiple H264 formats mandated by the Android CDD. Note: The CDD actually mandated main profile // support from API level 23, but we opt to test only from 24 due to known issues on API level 23 // when switching between baseline and main profiles on certain devices. - public static final String[] WIDEVINE_H264_CDD_ADAPTIVE = Util.SDK_INT < 24 - ? new String[] { - WIDEVINE_H264_BASELINE_240P_VIDEO_REPRESENTATION_ID, - WIDEVINE_H264_BASELINE_480P_VIDEO_REPRESENTATION_ID} - : new String[] { - WIDEVINE_H264_BASELINE_240P_VIDEO_REPRESENTATION_ID, - WIDEVINE_H264_BASELINE_480P_VIDEO_REPRESENTATION_ID, - WIDEVINE_H264_MAIN_240P_VIDEO_REPRESENTATION_ID, - WIDEVINE_H264_MAIN_480P_VIDEO_REPRESENTATION_ID}; + public static final String[] WIDEVINE_H264_CDD_ADAPTIVE = + Util.SDK_INT < 24 + ? new String[] { + WIDEVINE_H264_BASELINE_240P_VIDEO_REPRESENTATION_ID, + WIDEVINE_H264_BASELINE_480P_VIDEO_REPRESENTATION_ID + } + : new String[] { + WIDEVINE_H264_BASELINE_240P_VIDEO_REPRESENTATION_ID, + WIDEVINE_H264_BASELINE_480P_VIDEO_REPRESENTATION_ID, + WIDEVINE_H264_MAIN_240P_VIDEO_REPRESENTATION_ID, + WIDEVINE_H264_MAIN_480P_VIDEO_REPRESENTATION_ID + }; public static final String WIDEVINE_H264_BASELINE_480P_23FPS_VIDEO_REPRESENTATION_ID = "3"; public static final String WIDEVINE_H264_BASELINE_480P_24FPS_VIDEO_REPRESENTATION_ID = "3"; @@ -131,8 +137,9 @@ // Multiple H265 formats mandated by the Android CDD. public static final String[] WIDEVINE_H265_CDD_ADAPTIVE = new String[] { - WIDEVINE_H265_BASELINE_288P_VIDEO_REPRESENTATION_ID, - WIDEVINE_H265_BASELINE_360P_VIDEO_REPRESENTATION_ID}; + WIDEVINE_H265_BASELINE_288P_VIDEO_REPRESENTATION_ID, + WIDEVINE_H265_BASELINE_360P_VIDEO_REPRESENTATION_ID + }; public static final String WIDEVINE_VP9_AAC_AUDIO_REPRESENTATION_ID = "0"; public static final String WIDEVINE_VP9_180P_VIDEO_REPRESENTATION_ID = "2"; @@ -142,16 +149,16 @@ // Multiple VP9 formats mandated by the Android CDD. public static final String[] WIDEVINE_VP9_CDD_ADAPTIVE = new String[] { - WIDEVINE_VP9_180P_VIDEO_REPRESENTATION_ID, - WIDEVINE_VP9_360P_VIDEO_REPRESENTATION_ID}; + WIDEVINE_VP9_180P_VIDEO_REPRESENTATION_ID, WIDEVINE_VP9_360P_VIDEO_REPRESENTATION_ID + }; private static final String WIDEVINE_LICENSE_URL = "https://proxy.uat.widevine.com/proxy?provider=widevine_test"; private static final String WIDEVINE_SW_CRYPTO_CONTENT_ID = "&video_id=exoplayer_test_1"; private static final String WIDEVINE_HW_SECURE_DECODE_CONTENT_ID = "&video_id=exoplayer_test_2"; - public static String getWidevineLicenseUrl(boolean videoIdRequiredInLicenseUrl, - boolean useL1Widevine) { + public static String getWidevineLicenseUrl( + boolean videoIdRequiredInLicenseUrl, boolean useL1Widevine) { if (!videoIdRequiredInLicenseUrl) { return WIDEVINE_LICENSE_URL; } else { @@ -164,7 +171,5 @@ private static String getBaseUrl() { return "https://storage.googleapis.com/exoplayer-test-media-1/gen-4/"; } - private DashTestData() { - } - + private DashTestData() {} } diff --git a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashTestRunner.java b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashTestRunner.java index e43b2edb03e..f023a73e9ce 100644 --- a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashTestRunner.java +++ b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashTestRunner.java @@ -137,8 +137,8 @@ public DashTestRunner setFullPlaybackNoSeeking(boolean fullPlaybackNoSeeking) { public DashTestRunner setCanIncludeAdditionalVideoFormats( boolean canIncludeAdditionalVideoFormats) { - this.canIncludeAdditionalVideoFormats = canIncludeAdditionalVideoFormats - && ALLOW_ADDITIONAL_VIDEO_FORMATS; + this.canIncludeAdditionalVideoFormats = + canIncludeAdditionalVideoFormats && ALLOW_ADDITIONAL_VIDEO_FORMATS; return this; } @@ -165,8 +165,8 @@ public DashTestRunner setManifestUrl(String manifestUrl) { public DashTestRunner setWidevineInfo(String mimeType, boolean videoIdRequiredInLicenseUrl) { this.useL1Widevine = isL1WidevineAvailable(mimeType); - this.widevineLicenseUrl = DashTestData.getWidevineLicenseUrl(videoIdRequiredInLicenseUrl, - useL1Widevine); + this.widevineLicenseUrl = + DashTestData.getWidevineLicenseUrl(videoIdRequiredInLicenseUrl, useL1Widevine); return this; } @@ -190,15 +190,24 @@ private DashHostedTest createDashHostedTest( MetricsLogger metricsLogger = MetricsLogger.DEFAULT_FACTORY.create( InstrumentationRegistry.getInstrumentation(), tag, streamName); - return new DashHostedTest(tag, streamName, manifestUrl, metricsLogger, fullPlaybackNoSeeking, - audioFormat, canIncludeAdditionalVideoFormats, isCddLimitedRetry, actionSchedule, - offlineLicenseKeySetId, widevineLicenseUrl, useL1Widevine, dataSourceFactory, + return new DashHostedTest( + tag, + streamName, + manifestUrl, + metricsLogger, + fullPlaybackNoSeeking, + audioFormat, + canIncludeAdditionalVideoFormats, + isCddLimitedRetry, + actionSchedule, + offlineLicenseKeySetId, + widevineLicenseUrl, + useL1Widevine, + dataSourceFactory, videoFormats); } - /** - * A {@link HostedTest} for DASH playback tests. - */ + /** A {@link HostedTest} for DASH playback tests. */ private static final class DashHostedTest extends ExoHostedTest { private final String streamName; @@ -232,11 +241,21 @@ private static final class DashHostedTest extends ExoHostedTest { * @param dataSourceFactory If not null, used to load manifest and media. * @param videoFormats The video formats. */ - private DashHostedTest(String tag, String streamName, String manifestUrl, - MetricsLogger metricsLogger, boolean fullPlaybackNoSeeking, String audioFormat, - boolean canIncludeAdditionalVideoFormats, boolean isCddLimitedRetry, - ActionSchedule actionSchedule, byte[] offlineLicenseKeySetId, String widevineLicenseUrl, - boolean useL1Widevine, DataSource.Factory dataSourceFactory, String... videoFormats) { + private DashHostedTest( + String tag, + String streamName, + String manifestUrl, + MetricsLogger metricsLogger, + boolean fullPlaybackNoSeeking, + String audioFormat, + boolean canIncludeAdditionalVideoFormats, + boolean isCddLimitedRetry, + ActionSchedule actionSchedule, + byte[] offlineLicenseKeySetId, + String widevineLicenseUrl, + boolean useL1Widevine, + DataSource.Factory dataSourceFactory, + String... videoFormats) { super(tag, fullPlaybackNoSeeking); Assertions.checkArgument(!(isCddLimitedRetry && canIncludeAdditionalVideoFormats)); this.streamName = streamName; @@ -248,8 +267,9 @@ private DashHostedTest(String tag, String streamName, String manifestUrl, this.widevineLicenseUrl = widevineLicenseUrl; this.useL1Widevine = useL1Widevine; this.dataSourceFactory = dataSourceFactory; - trackSelector = new DashTestTrackSelector(tag, audioFormat, videoFormats, - canIncludeAdditionalVideoFormats); + trackSelector = + new DashTestTrackSelector( + tag, audioFormat, videoFormats, canIncludeAdditionalVideoFormats); if (actionSchedule != null) { setSchedule(actionSchedule); } @@ -303,9 +323,7 @@ protected SimpleExoPlayer buildExoPlayer( @Override protected MediaSource buildSource( - HostActivity host, - DrmSessionManager drmSessionManager, - FrameLayout overlayFrameLayout) { + HostActivity host, DrmSessionManager drmSessionManager, FrameLayout overlayFrameLayout) { DataSource.Factory dataSourceFactory = this.dataSourceFactory != null ? this.dataSourceFactory @@ -320,14 +338,15 @@ protected MediaSource buildSource( protected void logMetrics(DecoderCounters audioCounters, DecoderCounters videoCounters) { metricsLogger.logMetric(MetricsLogger.KEY_TEST_NAME, streamName); metricsLogger.logMetric(MetricsLogger.KEY_IS_CDD_LIMITED_RETRY, isCddLimitedRetry); - metricsLogger.logMetric(MetricsLogger.KEY_FRAMES_DROPPED_COUNT, - videoCounters.droppedBufferCount); - metricsLogger.logMetric(MetricsLogger.KEY_MAX_CONSECUTIVE_FRAMES_DROPPED_COUNT, + metricsLogger.logMetric( + MetricsLogger.KEY_FRAMES_DROPPED_COUNT, videoCounters.droppedBufferCount); + metricsLogger.logMetric( + MetricsLogger.KEY_MAX_CONSECUTIVE_FRAMES_DROPPED_COUNT, videoCounters.maxConsecutiveDroppedBufferCount); - metricsLogger.logMetric(MetricsLogger.KEY_FRAMES_SKIPPED_COUNT, - videoCounters.skippedOutputBufferCount); - metricsLogger.logMetric(MetricsLogger.KEY_FRAMES_RENDERED_COUNT, - videoCounters.renderedOutputBufferCount); + metricsLogger.logMetric( + MetricsLogger.KEY_FRAMES_SKIPPED_COUNT, videoCounters.skippedOutputBufferCount); + metricsLogger.logMetric( + MetricsLogger.KEY_FRAMES_RENDERED_COUNT, videoCounters.renderedOutputBufferCount); metricsLogger.close(); } @@ -335,16 +354,22 @@ protected void logMetrics(DecoderCounters audioCounters, DecoderCounters videoCo protected void assertPassed(DecoderCounters audioCounters, DecoderCounters videoCounters) { if (fullPlaybackNoSeeking) { // We shouldn't have skipped any output buffers. - DecoderCountersUtil - .assertSkippedOutputBufferCount(tag + AUDIO_TAG_SUFFIX, audioCounters, 0); - DecoderCountersUtil - .assertSkippedOutputBufferCount(tag + VIDEO_TAG_SUFFIX, videoCounters, 0); + DecoderCountersUtil.assertSkippedOutputBufferCount( + tag + AUDIO_TAG_SUFFIX, audioCounters, 0); + DecoderCountersUtil.assertSkippedOutputBufferCount( + tag + VIDEO_TAG_SUFFIX, videoCounters, 0); // We allow one fewer output buffer due to the way that MediaCodecRenderer and the // underlying decoders handle the end of stream. This should be tightened up in the future. - DecoderCountersUtil.assertTotalBufferCount(tag + AUDIO_TAG_SUFFIX, audioCounters, - audioCounters.inputBufferCount - 1, audioCounters.inputBufferCount); - DecoderCountersUtil.assertTotalBufferCount(tag + VIDEO_TAG_SUFFIX, videoCounters, - videoCounters.inputBufferCount - 1, videoCounters.inputBufferCount); + DecoderCountersUtil.assertTotalBufferCount( + tag + AUDIO_TAG_SUFFIX, + audioCounters, + audioCounters.inputBufferCount - 1, + audioCounters.inputBufferCount); + DecoderCountersUtil.assertTotalBufferCount( + tag + VIDEO_TAG_SUFFIX, + videoCounters, + videoCounters.inputBufferCount - 1, + videoCounters.inputBufferCount); } try { if (!shouldSkipDroppedOutputBufferPerformanceAssertions()) { @@ -387,7 +412,10 @@ private static final class DashTestTrackSelector extends DefaultTrackSelector { public boolean includedAdditionalVideoFormats; - private DashTestTrackSelector(String tag, String audioFormatId, String[] videoFormatIds, + private DashTestTrackSelector( + String tag, + String audioFormatId, + String[] videoFormatIds, boolean canIncludeAdditionalVideoFormats) { super( ApplicationProvider.getApplicationContext(), @@ -440,8 +468,9 @@ private int[] getVideoTrackIndices( // Always select explicitly listed representations. for (String formatId : formatIds) { int trackIndex = getTrackIndex(trackGroup, formatId); - Log.d(tag, "Adding base video format: " - + Format.toLogString(trackGroup.getFormat(trackIndex))); + Log.d( + tag, + "Adding base video format: " + Format.toLogString(trackGroup.getFormat(trackIndex))); trackIndices.add(trackIndex); } @@ -449,8 +478,7 @@ private int[] getVideoTrackIndices( if (canIncludeAdditionalFormats) { for (int i = 0; i < trackGroup.length; i++) { if (!trackIndices.contains(i) && isFormatHandled(formatSupports[i])) { - Log.d(tag, "Adding extra video format: " - + Format.toLogString(trackGroup.getFormat(i))); + Log.d(tag, "Adding extra video format: " + Format.toLogString(trackGroup.getFormat(i))); trackIndices.add(i); } } @@ -473,7 +501,6 @@ private static int getTrackIndex(TrackGroup trackGroup, String formatId) { private static boolean isFormatHandled(int formatSupport) { return RendererCapabilities.getFormatSupport(formatSupport) == C.FORMAT_HANDLED; } - } /** @@ -483,14 +510,12 @@ private static boolean isFormatHandled(int formatSupport) { @RequiresApi(18) private static final class MediaDrmBuilder { - public static MediaDrm build () { + public static MediaDrm build() { try { return new MediaDrm(WIDEVINE_UUID); } catch (UnsupportedSchemeException e) { throw new IllegalStateException(e); } } - } - } diff --git a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashWidevineOfflineTest.java b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashWidevineOfflineTest.java index ce5ebfe3030..9d962c281d0 100644 --- a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashWidevineOfflineTest.java +++ b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashWidevineOfflineTest.java @@ -221,9 +221,14 @@ public void widevineOfflineLicenseExpiresOnPauseV22() throws Exception { "License duration should be less than 30 sec. Server settings might have changed.") .that(licenseDuration) .isLessThan(30); - ActionSchedule schedule = new ActionSchedule.Builder(TAG) - .waitForPlaybackState(Player.STATE_READY) - .delay(3000).pause().delay(licenseDuration * 1000 + 2000).play().build(); + ActionSchedule schedule = + new ActionSchedule.Builder(TAG) + .waitForPlaybackState(Player.STATE_READY) + .delay(3000) + .pause() + .delay(licenseDuration * 1000 + 2000) + .play() + .build(); // DefaultDrmSessionManager should renew the license and stream play fine testRunner.setActionSchedule(schedule).run(); @@ -231,8 +236,8 @@ public void widevineOfflineLicenseExpiresOnPauseV22() throws Exception { private void downloadLicense() throws IOException { DataSource dataSource = httpDataSourceFactory.createDataSource(); - DashManifest dashManifest = DashUtil.loadManifest(dataSource, - Uri.parse(DashTestData.WIDEVINE_H264_MANIFEST)); + DashManifest dashManifest = + DashUtil.loadManifest(dataSource, Uri.parse(DashTestData.WIDEVINE_H264_MANIFEST)); Format format = DashUtil.loadFormatWithDrmInitData(dataSource, dashManifest.getPeriod(0)); offlineLicenseKeySetId = offlineLicenseHelper.downloadLicense(format); assertThat(offlineLicenseKeySetId).isNotNull(); @@ -244,5 +249,4 @@ private void releaseLicense() throws DrmSessionException { offlineLicenseHelper.releaseLicense(offlineLicenseKeySetId); offlineLicenseKeySetId = null; } - } diff --git a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DebugRenderersFactory.java b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DebugRenderersFactory.java index 01b6ebb190a..eb2341a74a8 100644 --- a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DebugRenderersFactory.java +++ b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DebugRenderersFactory.java @@ -253,9 +253,15 @@ protected void onProcessedOutputBuffer(long presentationTimeUs) { bufferCount++; long expectedTimestampUs = dequeueTimestamp(); if (expectedTimestampUs != presentationTimeUs) { - throw new IllegalStateException("Expected to dequeue video buffer with presentation " - + "timestamp: " + expectedTimestampUs + ". Instead got: " + presentationTimeUs - + " (Processed buffers since last flush: " + bufferCount + ")."); + throw new IllegalStateException( + "Expected to dequeue video buffer with presentation " + + "timestamp: " + + expectedTimestampUs + + ". Instead got: " + + presentationTimeUs + + " (Processed buffers since last flush: " + + bufferCount + + ")."); } if (outputMediaFormatChanged) { @@ -315,7 +321,5 @@ private long dequeueTimestamp() { minimumInsertIndex = max(minimumInsertIndex, startIndex); return timestampsList[startIndex - 1]; } - } - } diff --git a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/EnumerateDecodersTest.java b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/EnumerateDecodersTest.java index 67a6a93357f..efadf417370 100644 --- a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/EnumerateDecodersTest.java +++ b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/EnumerateDecodersTest.java @@ -15,7 +15,6 @@ */ package com.google.android.exoplayer2.playbacktests.gts; - import android.media.MediaCodecInfo.AudioCapabilities; import android.media.MediaCodecInfo.CodecCapabilities; import android.media.MediaCodecInfo.CodecProfileLevel; diff --git a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/LogcatMetricsLogger.java b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/LogcatMetricsLogger.java index ad24c61062d..5148de832bd 100644 --- a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/LogcatMetricsLogger.java +++ b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/LogcatMetricsLogger.java @@ -48,5 +48,4 @@ public void logMetric(String key, boolean value) { public void close() { // Do nothing. } - } diff --git a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/MetricsLogger.java b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/MetricsLogger.java index d4bf0a0b83e..05aac2fcccf 100644 --- a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/MetricsLogger.java +++ b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/MetricsLogger.java @@ -57,8 +57,6 @@ interface Factory { */ void logMetric(String key, boolean value); - /** - * Closes the logger. - */ + /** Closes the logger. */ void close(); } diff --git a/robolectricutils/src/main/java/com/google/android/exoplayer2/robolectric/TestPlayerRunHelper.java b/robolectricutils/src/main/java/com/google/android/exoplayer2/robolectric/TestPlayerRunHelper.java index 918d2330f9f..a58af6b55b5 100644 --- a/robolectricutils/src/main/java/com/google/android/exoplayer2/robolectric/TestPlayerRunHelper.java +++ b/robolectricutils/src/main/java/com/google/android/exoplayer2/robolectric/TestPlayerRunHelper.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.robolectric; import static com.google.android.exoplayer2.robolectric.RobolectricUtil.runMainLooperUntil; -import static com.google.common.truth.Truth.assertThat; +import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import android.os.Looper; import com.google.android.exoplayer2.ExoPlaybackException; @@ -25,7 +25,6 @@ import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.Timeline; -import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.ConditionVariable; import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.video.VideoListener; @@ -44,7 +43,9 @@ private TestPlayerRunHelper() {} /** * Runs tasks of the main {@link Looper} until {@link Player#getPlaybackState()} matches the - * expected state. + * expected state or a playback error occurs. + * + *

    If a playback error occurs it will be thrown wrapped in an {@link IllegalStateException}. * * @param player The {@link Player}. * @param expectedState The expected {@link Player.State}. @@ -54,27 +55,18 @@ private TestPlayerRunHelper() {} public static void runUntilPlaybackState(Player player, @Player.State int expectedState) throws TimeoutException { verifyMainTestThread(player); - if (player.getPlaybackState() == expectedState) { - return; + runMainLooperUntil( + () -> player.getPlaybackState() == expectedState || player.getPlayerError() != null); + if (player.getPlayerError() != null) { + throw new IllegalStateException(player.getPlayerError()); } - AtomicBoolean receivedExpectedState = new AtomicBoolean(false); - Player.Listener listener = - new Player.Listener() { - @Override - public void onPlaybackStateChanged(int state) { - if (state == expectedState) { - receivedExpectedState.set(true); - } - } - }; - player.addListener(listener); - runMainLooperUntil(receivedExpectedState::get); - player.removeListener(listener); } /** * Runs tasks of the main {@link Looper} until {@link Player#getPlayWhenReady()} matches the - * expected value. + * expected value or a playback error occurs. + * + *

    If a playback error occurs it will be thrown wrapped in an {@link IllegalStateException}. * * @param player The {@link Player}. * @param expectedPlayWhenReady The expected value for {@link Player#getPlayWhenReady()}. @@ -84,27 +76,19 @@ public void onPlaybackStateChanged(int state) { public static void runUntilPlayWhenReady(Player player, boolean expectedPlayWhenReady) throws TimeoutException { verifyMainTestThread(player); - if (player.getPlayWhenReady() == expectedPlayWhenReady) { - return; + runMainLooperUntil( + () -> + player.getPlayWhenReady() == expectedPlayWhenReady || player.getPlayerError() != null); + if (player.getPlayerError() != null) { + throw new IllegalStateException(player.getPlayerError()); } - AtomicBoolean receivedExpectedPlayWhenReady = new AtomicBoolean(false); - Player.Listener listener = - new Player.Listener() { - @Override - public void onPlayWhenReadyChanged(boolean playWhenReady, int reason) { - if (playWhenReady == expectedPlayWhenReady) { - receivedExpectedPlayWhenReady.set(true); - } - player.removeListener(this); - } - }; - player.addListener(listener); - runMainLooperUntil(receivedExpectedPlayWhenReady::get); } /** * Runs tasks of the main {@link Looper} until {@link Player#getCurrentTimeline()} matches the - * expected timeline. + * expected timeline or a playback error occurs. + * + *

    If a playback error occurs it will be thrown wrapped in an {@link IllegalStateException}. * * @param player The {@link Player}. * @param expectedTimeline The expected {@link Timeline}. @@ -114,26 +98,19 @@ public void onPlayWhenReadyChanged(boolean playWhenReady, int reason) { public static void runUntilTimelineChanged(Player player, Timeline expectedTimeline) throws TimeoutException { verifyMainTestThread(player); - if (expectedTimeline.equals(player.getCurrentTimeline())) { - return; + runMainLooperUntil( + () -> + expectedTimeline.equals(player.getCurrentTimeline()) + || player.getPlayerError() != null); + if (player.getPlayerError() != null) { + throw new IllegalStateException(player.getPlayerError()); } - AtomicBoolean receivedExpectedTimeline = new AtomicBoolean(false); - Player.Listener listener = - new Player.Listener() { - @Override - public void onTimelineChanged(Timeline timeline, int reason) { - if (expectedTimeline.equals(timeline)) { - receivedExpectedTimeline.set(true); - } - player.removeListener(this); - } - }; - player.addListener(listener); - runMainLooperUntil(receivedExpectedTimeline::get); } /** - * Runs tasks of the main {@link Looper} until a timeline change occurred. + * Runs tasks of the main {@link Looper} until a timeline change 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 {@link Timeline}. @@ -142,24 +119,29 @@ public void onTimelineChanged(Timeline timeline, int reason) { */ public static Timeline runUntilTimelineChanged(Player player) throws TimeoutException { verifyMainTestThread(player); - AtomicReference receivedTimeline = new AtomicReference<>(); + AtomicReference<@NullableType Timeline> receivedTimeline = new AtomicReference<>(); Player.Listener listener = new Player.Listener() { @Override public void onTimelineChanged(Timeline timeline, int reason) { receivedTimeline.set(timeline); - player.removeListener(this); } }; player.addListener(listener); - runMainLooperUntil(() -> receivedTimeline.get() != null); - return receivedTimeline.get(); + runMainLooperUntil(() -> receivedTimeline.get() != null || player.getPlayerError() != null); + player.removeListener(listener); + if (player.getPlayerError() != null) { + throw new IllegalStateException(player.getPlayerError()); + } + return checkNotNull(receivedTimeline.get()); } /** - * Runs tasks of the main {@link Looper} until a {@link - * Player.Listener#onPositionDiscontinuity(Player.PositionInfo, Player.PositionInfo, int)} - * callback with the specified {@link Player.DiscontinuityReason} occurred. + * Runs tasks of the main {@link Looper} until {@link + * Player.Listener#onPositionDiscontinuity(Player.PositionInfo, Player.PositionInfo, int)} is + * called with the specified {@link Player.DiscontinuityReason} or a playback error occurs. + * + *

    If a playback error occurs it will be thrown wrapped in an {@link IllegalStateException}. * * @param player The {@link Player}. * @param expectedReason The expected {@link Player.DiscontinuityReason}. @@ -177,42 +159,37 @@ public void onPositionDiscontinuity( Player.PositionInfo oldPosition, Player.PositionInfo newPosition, int reason) { if (reason == expectedReason) { receivedCallback.set(true); - player.removeListener(this); } } }; player.addListener(listener); - runMainLooperUntil(receivedCallback::get); + runMainLooperUntil(() -> receivedCallback.get() || player.getPlayerError() != null); + player.removeListener(listener); + if (player.getPlayerError() != null) { + throw new IllegalStateException(player.getPlayerError()); + } } /** - * Runs tasks of the main {@link Looper} until a player error occurred. + * Runs tasks of the main {@link Looper} until a player error occurs. * * @param player The {@link Player}. * @return The raised {@link ExoPlaybackException}. * @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is * exceeded. */ - public static ExoPlaybackException runUntilError(Player player) throws TimeoutException { + public static ExoPlaybackException runUntilError(ExoPlayer player) throws TimeoutException { verifyMainTestThread(player); - AtomicReference receivedError = new AtomicReference<>(); - Player.Listener listener = - new Player.Listener() { - @Override - public void onPlayerError(ExoPlaybackException error) { - receivedError.set(error); - player.removeListener(this); - } - }; - player.addListener(listener); - runMainLooperUntil(() -> receivedError.get() != null); - return receivedError.get(); + runMainLooperUntil(() -> player.getPlayerError() != null); + return checkNotNull(player.getPlayerError()); } /** - * Runs tasks of the main {@link Looper} until a {@link - * ExoPlayer.AudioOffloadListener#onExperimentalOffloadSchedulingEnabledChanged} callback - * occurred. + * 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. @@ -233,14 +210,21 @@ public void onExperimentalOffloadSchedulingEnabledChanged( } }; player.addAudioOffloadListener(listener); - runMainLooperUntil(() -> offloadSchedulingEnabledReceiver.get() != null); - return Assertions.checkNotNull(offloadSchedulingEnabledReceiver.get()); + 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 a {@link - * ExoPlayer.AudioOffloadListener#onExperimentalSleepingForOffloadChanged(boolean)} callback - * occurred. + * Runs tasks of the main {@link Looper} until {@link + * ExoPlayer.AudioOffloadListener#onExperimentalSleepingForOffloadChanged(boolean)} 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}. * @param expectedSleepForOffload The expected sleep of offload state. @@ -261,18 +245,17 @@ public void onExperimentalSleepingForOffloadChanged(boolean sleepingForOffload) } }; player.addAudioOffloadListener(listener); - runMainLooperUntil( - () -> { // Make sure progress is being made, see [internal: b/170387438#comment2] - assertThat(player.getPlayerError()).isNull(); - assertThat(player.getPlayWhenReady()).isTrue(); - assertThat(player.getPlaybackState()).isAnyOf(Player.STATE_BUFFERING, Player.STATE_READY); - return receiverCallback.get(); - }); + runMainLooperUntil(() -> receiverCallback.get() || player.getPlayerError() != null); + if (player.getPlayerError() != null) { + throw new IllegalStateException(player.getPlayerError()); + } } /** * Runs tasks of the main {@link Looper} until the {@link VideoListener#onRenderedFirstFrame} - * callback has been called. + * callback 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}. * @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is @@ -286,16 +269,21 @@ public static void runUntilRenderedFirstFrame(SimpleExoPlayer player) throws Tim @Override public void onRenderedFirstFrame() { receivedCallback.set(true); - player.removeListener(this); } }; player.addListener(listener); - runMainLooperUntil(receivedCallback::get); + runMainLooperUntil(() -> receivedCallback.get() || player.getPlayerError() != null); + player.removeListener(listener); + if (player.getPlayerError() != null) { + throw new IllegalStateException(player.getPlayerError()); + } } /** * Calls {@link Player#play()}, runs tasks of the main {@link Looper} until the {@code player} - * reaches the specified position and then pauses the {@code player}. + * reaches the specified position or a playback error occurs, and then pauses the {@code player}. + * + *

    If a playback error occurs it will be thrown wrapped in an {@link IllegalStateException}. * * @param player The {@link Player}. * @param windowIndex The window. @@ -332,12 +320,17 @@ public static void playUntilPosition(ExoPlayer player, int windowIndex, long pos .setPosition(windowIndex, positionMs) .send(); player.play(); - runMainLooperUntil(messageHandled::get); + runMainLooperUntil(() -> messageHandled.get() || player.getPlayerError() != null); + if (player.getPlayerError() != null) { + throw new IllegalStateException(player.getPlayerError()); + } } /** * Calls {@link Player#play()}, runs tasks of the main {@link Looper} until the {@code player} - * reaches the specified window and then pauses the {@code player}. + * reaches the specified window or a playback error occurs, and then pauses the {@code player}. + * + *

    If a playback error occurs it will be thrown wrapped in an {@link IllegalStateException}. * * @param player The {@link Player}. * @param windowIndex The window. diff --git a/settings.gradle b/settings.gradle index 946b5b78de8..ee651f1908b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -11,7 +11,8 @@ // 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. -gradle.ext.exoplayerRoot = settingsDir +gradle.ext.exoplayerRoot = rootDir +gradle.ext.exoplayerModulePrefix = '' def modulePrefix = ':' if (gradle.ext.has('exoplayerModulePrefix')) { @@ -19,14 +20,15 @@ if (gradle.ext.has('exoplayerModulePrefix')) { } include modulePrefix + 'demo' -include modulePrefix + 'demo-cast' -include modulePrefix + 'demo-gl' -include modulePrefix + 'demo-surface' -include modulePrefix + 'playbacktests' project(modulePrefix + 'demo').projectDir = new File(rootDir, 'demos/main') +include modulePrefix + 'demo-cast' project(modulePrefix + 'demo-cast').projectDir = new File(rootDir, 'demos/cast') +include modulePrefix + 'demo-gl' project(modulePrefix + 'demo-gl').projectDir = new File(rootDir, 'demos/gl') +include modulePrefix + 'demo-surface' project(modulePrefix + 'demo-surface').projectDir = new File(rootDir, 'demos/surface') + +include modulePrefix + 'playbacktests' project(modulePrefix + 'playbacktests').projectDir = new File(rootDir, 'playbacktests') apply from: 'core_settings.gradle' diff --git a/testdata/src/test/assets/extractordumps/jpeg/non-motion-photo-shortened.jpg.0.dump b/testdata/src/test/assets/extractordumps/jpeg/non-motion-photo-shortened.jpg.0.dump index bb201ef2ef5..02c10855b51 100644 --- a/testdata/src/test/assets/extractordumps/jpeg/non-motion-photo-shortened.jpg.0.dump +++ b/testdata/src/test/assets/extractordumps/jpeg/non-motion-photo-shortened.jpg.0.dump @@ -7,5 +7,6 @@ track 1024: total output bytes = 0 sample count = 0 format 0: + containerMimeType = image/jpeg metadata = entries=[] tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/jpeg/non-motion-photo-shortened.jpg.unknown_length.dump b/testdata/src/test/assets/extractordumps/jpeg/non-motion-photo-shortened.jpg.unknown_length.dump index bb201ef2ef5..02c10855b51 100644 --- a/testdata/src/test/assets/extractordumps/jpeg/non-motion-photo-shortened.jpg.unknown_length.dump +++ b/testdata/src/test/assets/extractordumps/jpeg/non-motion-photo-shortened.jpg.unknown_length.dump @@ -7,5 +7,6 @@ track 1024: total output bytes = 0 sample count = 0 format 0: + containerMimeType = image/jpeg metadata = entries=[] tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-jfif-segment-shortened.jpg.0.dump b/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-jfif-segment-shortened.jpg.0.dump index 80ac03b1257..d9d6e116b66 100644 --- a/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-jfif-segment-shortened.jpg.0.dump +++ b/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-jfif-segment-shortened.jpg.0.dump @@ -28,5 +28,6 @@ track 1024: total output bytes = 0 sample count = 0 format 0: + containerMimeType = image/jpeg metadata = entries=[Motion photo metadata: photoStartPosition=0, photoSize=6377, photoPresentationTimestampUs=1232840, videoStartPosition=6377, videoSize=4686] tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-jfif-segment-shortened.jpg.1.dump b/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-jfif-segment-shortened.jpg.1.dump index 80ac03b1257..d9d6e116b66 100644 --- a/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-jfif-segment-shortened.jpg.1.dump +++ b/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-jfif-segment-shortened.jpg.1.dump @@ -28,5 +28,6 @@ track 1024: total output bytes = 0 sample count = 0 format 0: + containerMimeType = image/jpeg metadata = entries=[Motion photo metadata: photoStartPosition=0, photoSize=6377, photoPresentationTimestampUs=1232840, videoStartPosition=6377, videoSize=4686] tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-jfif-segment-shortened.jpg.2.dump b/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-jfif-segment-shortened.jpg.2.dump index 80ac03b1257..d9d6e116b66 100644 --- a/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-jfif-segment-shortened.jpg.2.dump +++ b/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-jfif-segment-shortened.jpg.2.dump @@ -28,5 +28,6 @@ track 1024: total output bytes = 0 sample count = 0 format 0: + containerMimeType = image/jpeg metadata = entries=[Motion photo metadata: photoStartPosition=0, photoSize=6377, photoPresentationTimestampUs=1232840, videoStartPosition=6377, videoSize=4686] tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-jfif-segment-shortened.jpg.3.dump b/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-jfif-segment-shortened.jpg.3.dump index 80ac03b1257..d9d6e116b66 100644 --- a/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-jfif-segment-shortened.jpg.3.dump +++ b/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-jfif-segment-shortened.jpg.3.dump @@ -28,5 +28,6 @@ track 1024: total output bytes = 0 sample count = 0 format 0: + containerMimeType = image/jpeg metadata = entries=[Motion photo metadata: photoStartPosition=0, photoSize=6377, photoPresentationTimestampUs=1232840, videoStartPosition=6377, videoSize=4686] tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-jfif-segment-shortened.jpg.unknown_length.dump b/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-jfif-segment-shortened.jpg.unknown_length.dump index bb201ef2ef5..02c10855b51 100644 --- a/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-jfif-segment-shortened.jpg.unknown_length.dump +++ b/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-jfif-segment-shortened.jpg.unknown_length.dump @@ -7,5 +7,6 @@ track 1024: total output bytes = 0 sample count = 0 format 0: + containerMimeType = image/jpeg metadata = entries=[] tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-shortened.jpg.0.dump b/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-shortened.jpg.0.dump index 7e398127fa2..fc2adcadd7f 100644 --- a/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-shortened.jpg.0.dump +++ b/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-shortened.jpg.0.dump @@ -8,5 +8,6 @@ track 1024: total output bytes = 0 sample count = 0 format 0: + containerMimeType = image/jpeg metadata = entries=[Motion photo metadata: photoStartPosition=0, photoSize=131582, photoPresentationTimestampUs=0, videoStartPosition=131582, videoSize=8730] tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-shortened.jpg.unknown_length.dump b/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-shortened.jpg.unknown_length.dump index bb201ef2ef5..02c10855b51 100644 --- a/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-shortened.jpg.unknown_length.dump +++ b/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-shortened.jpg.unknown_length.dump @@ -7,5 +7,6 @@ track 1024: total output bytes = 0 sample count = 0 format 0: + containerMimeType = image/jpeg metadata = entries=[] tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-video-removed-shortened.jpg.0.dump b/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-video-removed-shortened.jpg.0.dump index bb201ef2ef5..02c10855b51 100644 --- a/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-video-removed-shortened.jpg.0.dump +++ b/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-video-removed-shortened.jpg.0.dump @@ -7,5 +7,6 @@ track 1024: total output bytes = 0 sample count = 0 format 0: + containerMimeType = image/jpeg metadata = entries=[] tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-video-removed-shortened.jpg.unknown_length.dump b/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-video-removed-shortened.jpg.unknown_length.dump index bb201ef2ef5..02c10855b51 100644 --- a/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-video-removed-shortened.jpg.unknown_length.dump +++ b/testdata/src/test/assets/extractordumps/jpeg/pixel-motion-photo-video-removed-shortened.jpg.unknown_length.dump @@ -7,5 +7,6 @@ track 1024: total output bytes = 0 sample count = 0 format 0: + containerMimeType = image/jpeg metadata = entries=[] tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/jpeg/ss-motion-photo-shortened.jpg.0.dump b/testdata/src/test/assets/extractordumps/jpeg/ss-motion-photo-shortened.jpg.0.dump index df80dc226ab..cd7232f583f 100644 --- a/testdata/src/test/assets/extractordumps/jpeg/ss-motion-photo-shortened.jpg.0.dump +++ b/testdata/src/test/assets/extractordumps/jpeg/ss-motion-photo-shortened.jpg.0.dump @@ -8,5 +8,6 @@ track 1024: total output bytes = 0 sample count = 0 format 0: + containerMimeType = image/jpeg metadata = entries=[Motion photo metadata: photoStartPosition=0, photoSize=20345, photoPresentationTimestampUs=-9223372036854775807, videoStartPosition=20345, videoSize=2582] tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/jpeg/ss-motion-photo-shortened.jpg.unknown_length.dump b/testdata/src/test/assets/extractordumps/jpeg/ss-motion-photo-shortened.jpg.unknown_length.dump index bb201ef2ef5..02c10855b51 100644 --- a/testdata/src/test/assets/extractordumps/jpeg/ss-motion-photo-shortened.jpg.unknown_length.dump +++ b/testdata/src/test/assets/extractordumps/jpeg/ss-motion-photo-shortened.jpg.unknown_length.dump @@ -7,5 +7,6 @@ track 1024: total output bytes = 0 sample count = 0 format 0: + containerMimeType = image/jpeg metadata = entries=[] tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_with_color_info.mp4.0.dump b/testdata/src/test/assets/extractordumps/mp4/sample_with_color_info.mp4.0.dump new file mode 100644 index 00000000000..5fd303aed3a --- /dev/null +++ b/testdata/src/test/assets/extractordumps/mp4/sample_with_color_info.mp4.0.dump @@ -0,0 +1,138 @@ +seekMap: + isSeekable = true + duration = 298333 + getPosition(0) = [[timeUs=0, position=36]] + getPosition(1) = [[timeUs=0, position=36]] + getPosition(149166) = [[timeUs=0, position=36]] + getPosition(298333) = [[timeUs=0, position=36]] +numberOfTracks = 2 +track 0: + total output bytes = 122447 + sample count = 9 + format 0: + id = 1 + sampleMimeType = video/dolby-vision + codecs = hev1.08.04 + maxInputSize = 40550 + width = 1920 + height = 1080 + frameRate = 30.167633 + rotationDegrees = 90 + colorInfo: + colorSpace = 6 + colorRange = 2 + colorTransfer = 7 + hdrStaticInfo = length 0, hash 0 + initializationData: + data = length 526, hash 7B3FC433 + sample 0: + time = 0 + flags = 1 + data = length 40520, hash 6B3C7ED3 + sample 1: + time = 133333 + flags = 0 + data = length 11652, hash 24B95831 + sample 2: + time = 66666 + flags = 0 + data = length 9546, hash A8965647 + sample 3: + time = 33333 + flags = 0 + data = length 7587, hash 624A0ECE + sample 4: + time = 100000 + flags = 0 + data = length 8584, hash 8F104D88 + sample 5: + time = 266666 + flags = 0 + data = length 18275, hash E7639088 + sample 6: + time = 200000 + flags = 0 + data = length 12112, hash 7CCEBA45 + sample 7: + time = 166666 + flags = 0 + data = length 7180, hash 4E965EBB + sample 8: + time = 233333 + flags = 536870912 + data = length 6991, hash 84F4EA41 +track 1: + total output bytes = 5993 + sample count = 15 + format 0: + id = 2 + sampleMimeType = audio/mp4a-latm + codecs = mp4a.40.2 + maxInputSize = 568 + channelCount = 2 + sampleRate = 44100 + encoderPadding = 2204 + language = und + initializationData: + data = length 2, hash 5FF + sample 0: + time = 0 + flags = 1 + data = length 6, hash 6D3881D1 + sample 1: + time = 23219 + flags = 1 + data = length 272, hash E2040CE0 + sample 2: + time = 46439 + flags = 1 + data = length 476, hash E09EC12F + sample 3: + time = 69659 + flags = 1 + data = length 445, hash D23AB210 + sample 4: + time = 92879 + flags = 1 + data = length 487, hash F68FF5DD + sample 5: + time = 116099 + flags = 1 + data = length 446, hash 62477362 + sample 6: + time = 139319 + flags = 1 + data = length 429, hash BA59B5B5 + sample 7: + time = 162539 + flags = 1 + data = length 431, hash 1A0A41B3 + sample 8: + time = 185759 + flags = 1 + data = length 538, hash 9F604E03 + sample 9: + time = 208979 + flags = 1 + data = length 485, hash 94C855CD + sample 10: + time = 232199 + flags = 1 + data = length 460, hash F6AEAF79 + sample 11: + time = 255419 + flags = 1 + data = length 444, hash F513A8A9 + sample 12: + time = 278639 + flags = 1 + data = length 436, hash 2E976590 + sample 13: + time = 301859 + flags = 1 + data = length 451, hash 45B8B663 + sample 14: + time = 325079 + flags = 536870913 + data = length 187, hash 833755BD +tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_with_color_info.mp4.1.dump b/testdata/src/test/assets/extractordumps/mp4/sample_with_color_info.mp4.1.dump new file mode 100644 index 00000000000..fa9e2af42e9 --- /dev/null +++ b/testdata/src/test/assets/extractordumps/mp4/sample_with_color_info.mp4.1.dump @@ -0,0 +1,122 @@ +seekMap: + isSeekable = true + duration = 298333 + getPosition(0) = [[timeUs=0, position=36]] + getPosition(1) = [[timeUs=0, position=36]] + getPosition(149166) = [[timeUs=0, position=36]] + getPosition(298333) = [[timeUs=0, position=36]] +numberOfTracks = 2 +track 0: + total output bytes = 122447 + sample count = 9 + format 0: + id = 1 + sampleMimeType = video/dolby-vision + codecs = hev1.08.04 + maxInputSize = 40550 + width = 1920 + height = 1080 + frameRate = 30.167633 + rotationDegrees = 90 + colorInfo: + colorSpace = 6 + colorRange = 2 + colorTransfer = 7 + hdrStaticInfo = length 0, hash 0 + initializationData: + data = length 526, hash 7B3FC433 + sample 0: + time = 0 + flags = 1 + data = length 40520, hash 6B3C7ED3 + sample 1: + time = 133333 + flags = 0 + data = length 11652, hash 24B95831 + sample 2: + time = 66666 + flags = 0 + data = length 9546, hash A8965647 + sample 3: + time = 33333 + flags = 0 + data = length 7587, hash 624A0ECE + sample 4: + time = 100000 + flags = 0 + data = length 8584, hash 8F104D88 + sample 5: + time = 266666 + flags = 0 + data = length 18275, hash E7639088 + sample 6: + time = 200000 + flags = 0 + data = length 12112, hash 7CCEBA45 + sample 7: + time = 166666 + flags = 0 + data = length 7180, hash 4E965EBB + sample 8: + time = 233333 + flags = 536870912 + data = length 6991, hash 84F4EA41 +track 1: + total output bytes = 4794 + sample count = 11 + format 0: + id = 2 + sampleMimeType = audio/mp4a-latm + codecs = mp4a.40.2 + maxInputSize = 568 + channelCount = 2 + sampleRate = 44100 + encoderPadding = 2204 + language = und + initializationData: + data = length 2, hash 5FF + sample 0: + time = 92879 + flags = 1 + data = length 487, hash F68FF5DD + sample 1: + time = 116099 + flags = 1 + data = length 446, hash 62477362 + sample 2: + time = 139319 + flags = 1 + data = length 429, hash BA59B5B5 + sample 3: + time = 162539 + flags = 1 + data = length 431, hash 1A0A41B3 + sample 4: + time = 185759 + flags = 1 + data = length 538, hash 9F604E03 + sample 5: + time = 208979 + flags = 1 + data = length 485, hash 94C855CD + sample 6: + time = 232199 + flags = 1 + data = length 460, hash F6AEAF79 + sample 7: + time = 255419 + flags = 1 + data = length 444, hash F513A8A9 + sample 8: + time = 278639 + flags = 1 + data = length 436, hash 2E976590 + sample 9: + time = 301859 + flags = 1 + data = length 451, hash 45B8B663 + sample 10: + time = 325079 + flags = 536870913 + data = length 187, hash 833755BD +tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_with_color_info.mp4.2.dump b/testdata/src/test/assets/extractordumps/mp4/sample_with_color_info.mp4.2.dump new file mode 100644 index 00000000000..8b91ab1a5b6 --- /dev/null +++ b/testdata/src/test/assets/extractordumps/mp4/sample_with_color_info.mp4.2.dump @@ -0,0 +1,106 @@ +seekMap: + isSeekable = true + duration = 298333 + getPosition(0) = [[timeUs=0, position=36]] + getPosition(1) = [[timeUs=0, position=36]] + getPosition(149166) = [[timeUs=0, position=36]] + getPosition(298333) = [[timeUs=0, position=36]] +numberOfTracks = 2 +track 0: + total output bytes = 122447 + sample count = 9 + format 0: + id = 1 + sampleMimeType = video/dolby-vision + codecs = hev1.08.04 + maxInputSize = 40550 + width = 1920 + height = 1080 + frameRate = 30.167633 + rotationDegrees = 90 + colorInfo: + colorSpace = 6 + colorRange = 2 + colorTransfer = 7 + hdrStaticInfo = length 0, hash 0 + initializationData: + data = length 526, hash 7B3FC433 + sample 0: + time = 0 + flags = 1 + data = length 40520, hash 6B3C7ED3 + sample 1: + time = 133333 + flags = 0 + data = length 11652, hash 24B95831 + sample 2: + time = 66666 + flags = 0 + data = length 9546, hash A8965647 + sample 3: + time = 33333 + flags = 0 + data = length 7587, hash 624A0ECE + sample 4: + time = 100000 + flags = 0 + data = length 8584, hash 8F104D88 + sample 5: + time = 266666 + flags = 0 + data = length 18275, hash E7639088 + sample 6: + time = 200000 + flags = 0 + data = length 12112, hash 7CCEBA45 + sample 7: + time = 166666 + flags = 0 + data = length 7180, hash 4E965EBB + sample 8: + time = 233333 + flags = 536870912 + data = length 6991, hash 84F4EA41 +track 1: + total output bytes = 3001 + sample count = 7 + format 0: + id = 2 + sampleMimeType = audio/mp4a-latm + codecs = mp4a.40.2 + maxInputSize = 568 + channelCount = 2 + sampleRate = 44100 + encoderPadding = 2204 + language = und + initializationData: + data = length 2, hash 5FF + sample 0: + time = 185759 + flags = 1 + data = length 538, hash 9F604E03 + sample 1: + time = 208979 + flags = 1 + data = length 485, hash 94C855CD + sample 2: + time = 232199 + flags = 1 + data = length 460, hash F6AEAF79 + sample 3: + time = 255419 + flags = 1 + data = length 444, hash F513A8A9 + sample 4: + time = 278639 + flags = 1 + data = length 436, hash 2E976590 + sample 5: + time = 301859 + flags = 1 + data = length 451, hash 45B8B663 + sample 6: + time = 325079 + flags = 536870913 + data = length 187, hash 833755BD +tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_with_color_info.mp4.3.dump b/testdata/src/test/assets/extractordumps/mp4/sample_with_color_info.mp4.3.dump new file mode 100644 index 00000000000..22b236d5726 --- /dev/null +++ b/testdata/src/test/assets/extractordumps/mp4/sample_with_color_info.mp4.3.dump @@ -0,0 +1,90 @@ +seekMap: + isSeekable = true + duration = 298333 + getPosition(0) = [[timeUs=0, position=36]] + getPosition(1) = [[timeUs=0, position=36]] + getPosition(149166) = [[timeUs=0, position=36]] + getPosition(298333) = [[timeUs=0, position=36]] +numberOfTracks = 2 +track 0: + total output bytes = 122447 + sample count = 9 + format 0: + id = 1 + sampleMimeType = video/dolby-vision + codecs = hev1.08.04 + maxInputSize = 40550 + width = 1920 + height = 1080 + frameRate = 30.167633 + rotationDegrees = 90 + colorInfo: + colorSpace = 6 + colorRange = 2 + colorTransfer = 7 + hdrStaticInfo = length 0, hash 0 + initializationData: + data = length 526, hash 7B3FC433 + sample 0: + time = 0 + flags = 1 + data = length 40520, hash 6B3C7ED3 + sample 1: + time = 133333 + flags = 0 + data = length 11652, hash 24B95831 + sample 2: + time = 66666 + flags = 0 + data = length 9546, hash A8965647 + sample 3: + time = 33333 + flags = 0 + data = length 7587, hash 624A0ECE + sample 4: + time = 100000 + flags = 0 + data = length 8584, hash 8F104D88 + sample 5: + time = 266666 + flags = 0 + data = length 18275, hash E7639088 + sample 6: + time = 200000 + flags = 0 + data = length 12112, hash 7CCEBA45 + sample 7: + time = 166666 + flags = 0 + data = length 7180, hash 4E965EBB + sample 8: + time = 233333 + flags = 536870912 + data = length 6991, hash 84F4EA41 +track 1: + total output bytes = 1074 + sample count = 3 + format 0: + id = 2 + sampleMimeType = audio/mp4a-latm + codecs = mp4a.40.2 + maxInputSize = 568 + channelCount = 2 + sampleRate = 44100 + encoderPadding = 2204 + language = und + initializationData: + data = length 2, hash 5FF + sample 0: + time = 278639 + flags = 1 + data = length 436, hash 2E976590 + sample 1: + time = 301859 + flags = 1 + data = length 451, hash 45B8B663 + sample 2: + time = 325079 + flags = 536870913 + data = length 187, hash 833755BD +tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_with_color_info.mp4.unknown_length.dump b/testdata/src/test/assets/extractordumps/mp4/sample_with_color_info.mp4.unknown_length.dump new file mode 100644 index 00000000000..5fd303aed3a --- /dev/null +++ b/testdata/src/test/assets/extractordumps/mp4/sample_with_color_info.mp4.unknown_length.dump @@ -0,0 +1,138 @@ +seekMap: + isSeekable = true + duration = 298333 + getPosition(0) = [[timeUs=0, position=36]] + getPosition(1) = [[timeUs=0, position=36]] + getPosition(149166) = [[timeUs=0, position=36]] + getPosition(298333) = [[timeUs=0, position=36]] +numberOfTracks = 2 +track 0: + total output bytes = 122447 + sample count = 9 + format 0: + id = 1 + sampleMimeType = video/dolby-vision + codecs = hev1.08.04 + maxInputSize = 40550 + width = 1920 + height = 1080 + frameRate = 30.167633 + rotationDegrees = 90 + colorInfo: + colorSpace = 6 + colorRange = 2 + colorTransfer = 7 + hdrStaticInfo = length 0, hash 0 + initializationData: + data = length 526, hash 7B3FC433 + sample 0: + time = 0 + flags = 1 + data = length 40520, hash 6B3C7ED3 + sample 1: + time = 133333 + flags = 0 + data = length 11652, hash 24B95831 + sample 2: + time = 66666 + flags = 0 + data = length 9546, hash A8965647 + sample 3: + time = 33333 + flags = 0 + data = length 7587, hash 624A0ECE + sample 4: + time = 100000 + flags = 0 + data = length 8584, hash 8F104D88 + sample 5: + time = 266666 + flags = 0 + data = length 18275, hash E7639088 + sample 6: + time = 200000 + flags = 0 + data = length 12112, hash 7CCEBA45 + sample 7: + time = 166666 + flags = 0 + data = length 7180, hash 4E965EBB + sample 8: + time = 233333 + flags = 536870912 + data = length 6991, hash 84F4EA41 +track 1: + total output bytes = 5993 + sample count = 15 + format 0: + id = 2 + sampleMimeType = audio/mp4a-latm + codecs = mp4a.40.2 + maxInputSize = 568 + channelCount = 2 + sampleRate = 44100 + encoderPadding = 2204 + language = und + initializationData: + data = length 2, hash 5FF + sample 0: + time = 0 + flags = 1 + data = length 6, hash 6D3881D1 + sample 1: + time = 23219 + flags = 1 + data = length 272, hash E2040CE0 + sample 2: + time = 46439 + flags = 1 + data = length 476, hash E09EC12F + sample 3: + time = 69659 + flags = 1 + data = length 445, hash D23AB210 + sample 4: + time = 92879 + flags = 1 + data = length 487, hash F68FF5DD + sample 5: + time = 116099 + flags = 1 + data = length 446, hash 62477362 + sample 6: + time = 139319 + flags = 1 + data = length 429, hash BA59B5B5 + sample 7: + time = 162539 + flags = 1 + data = length 431, hash 1A0A41B3 + sample 8: + time = 185759 + flags = 1 + data = length 538, hash 9F604E03 + sample 9: + time = 208979 + flags = 1 + data = length 485, hash 94C855CD + sample 10: + time = 232199 + flags = 1 + data = length 460, hash F6AEAF79 + sample 11: + time = 255419 + flags = 1 + data = length 444, hash F513A8A9 + sample 12: + time = 278639 + flags = 1 + data = length 436, hash 2E976590 + sample 13: + time = 301859 + flags = 1 + data = length 451, hash 45B8B663 + sample 14: + time = 325079 + flags = 536870913 + data = length 187, hash 833755BD +tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/ts/sample_h262_mpeg_audio.ts.1.dump b/testdata/src/test/assets/extractordumps/ts/sample_h262_mpeg_audio.ts.1.dump index 489763bbf8d..8e996b6f31e 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_h262_mpeg_audio.ts.1.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_h262_mpeg_audio.ts.1.dump @@ -17,11 +17,11 @@ track 256: initializationData: data = length 22, hash CE183139 sample 0: - time = 55610 + time = 33366 flags = 1 data = length 20711, hash 34341E8 sample 1: - time = 88977 + time = 66733 flags = 0 data = length 18112, hash EC44B35B track 257: @@ -35,19 +35,19 @@ track 257: sampleRate = 44100 language = und sample 0: - time = 44699 + time = 22455 flags = 1 data = length 1253, hash 727FD1C6 sample 1: - time = 70821 + time = 48577 flags = 1 data = length 1254, hash 73FB07B8 sample 2: - time = 96944 + time = 74700 flags = 1 data = length 1254, hash 73FB07B8 sample 3: - time = 123066 + time = 100822 flags = 1 data = length 1254, hash 73FB07B8 tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/ts/sample_h262_mpeg_audio.ts.2.dump b/testdata/src/test/assets/extractordumps/ts/sample_h262_mpeg_audio.ts.2.dump index a7ef1ecf4b3..8e996b6f31e 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_h262_mpeg_audio.ts.2.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_h262_mpeg_audio.ts.2.dump @@ -17,11 +17,11 @@ track 256: initializationData: data = length 22, hash CE183139 sample 0: - time = 77854 + time = 33366 flags = 1 data = length 20711, hash 34341E8 sample 1: - time = 111221 + time = 66733 flags = 0 data = length 18112, hash EC44B35B track 257: @@ -35,19 +35,19 @@ track 257: sampleRate = 44100 language = und sample 0: - time = 66943 + time = 22455 flags = 1 data = length 1253, hash 727FD1C6 sample 1: - time = 93065 + time = 48577 flags = 1 data = length 1254, hash 73FB07B8 sample 2: - time = 119188 + time = 74700 flags = 1 data = length 1254, hash 73FB07B8 sample 3: - time = 145310 + time = 100822 flags = 1 data = length 1254, hash 73FB07B8 tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/ts/sample_h262_mpeg_audio.ts.3.dump b/testdata/src/test/assets/extractordumps/ts/sample_h262_mpeg_audio.ts.3.dump index fffd040d68d..f0fd81369fe 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_h262_mpeg_audio.ts.3.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_h262_mpeg_audio.ts.3.dump @@ -27,11 +27,11 @@ track 257: sampleRate = 44100 language = und sample 0: - time = 66733 + time = 74700 flags = 1 data = length 1254, hash 73FB07B8 sample 1: - time = 92855 + time = 100822 flags = 1 data = length 1254, hash 73FB07B8 tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/ts/sample_h263.ts.1.dump b/testdata/src/test/assets/extractordumps/ts/sample_h263.ts.1.dump index a83a484f64b..e67426081b4 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_h263.ts.1.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_h263.ts.1.dump @@ -17,75 +17,75 @@ track 256: initializationData: data = length 47, hash 7696BF67 sample 0: - time = 320000 + time = 240000 flags = 0 data = length 212, hash 835B0727 sample 1: - time = 360000 + time = 280000 flags = 0 data = length 212, hash E9AF0AB7 sample 2: - time = 400000 + time = 320000 flags = 0 data = length 212, hash E9517D06 sample 3: - time = 440000 + time = 360000 flags = 0 data = length 212, hash 4FA58096 sample 4: - time = 480000 + time = 400000 flags = 0 data = length 212, hash 4F47F2E5 sample 5: - time = 520000 + time = 440000 flags = 0 data = length 212, hash B59BF675 sample 6: - time = 560000 + time = 480000 flags = 1 data = length 11769, hash 3ED9DF06 sample 7: - time = 600000 + time = 520000 flags = 0 data = length 230, hash 2AF3505D sample 8: - time = 640000 + time = 560000 flags = 0 data = length 222, hash F4E7436D sample 9: - time = 680000 + time = 600000 flags = 0 data = length 222, hash F0F812FD sample 10: - time = 720000 + time = 640000 flags = 0 data = length 222, hash 18472E8C sample 11: - time = 760000 + time = 680000 flags = 0 data = length 222, hash 1457FE1C sample 12: - time = 800000 + time = 720000 flags = 0 data = length 222, hash 3BA719AB sample 13: - time = 840000 + time = 760000 flags = 0 data = length 222, hash 37B7E93B sample 14: - time = 880000 + time = 800000 flags = 0 data = length 222, hash 5F0704CA sample 15: - time = 920000 + time = 840000 flags = 0 data = length 222, hash 5B17D45A sample 16: - time = 960000 + time = 880000 flags = 0 data = length 222, hash 8266EFE9 sample 17: - time = 1000000 + time = 920000 flags = 0 data = length 222, hash 7E77BF79 tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/ts/sample_h264_mpeg_audio.ts.1.dump b/testdata/src/test/assets/extractordumps/ts/sample_h264_mpeg_audio.ts.1.dump index 295fa07e94b..605daaf8dd6 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_h264_mpeg_audio.ts.1.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_h264_mpeg_audio.ts.1.dump @@ -19,11 +19,11 @@ track 256: data = length 29, hash 4C2CAE9C data = length 9, hash D971CD89 sample 0: - time = 88977 + time = 66733 flags = 1 data = length 12394, hash A39F5311 sample 1: - time = 122344 + time = 100100 flags = 0 data = length 813, hash 99F7B4FA track 257: @@ -37,19 +37,19 @@ track 257: sampleRate = 44100 language = und sample 0: - time = 88977 + time = 66733 flags = 1 data = length 1253, hash 727FD1C6 sample 1: - time = 115099 + time = 92855 flags = 1 data = length 1254, hash 73FB07B8 sample 2: - time = 141221 + time = 118977 flags = 1 data = length 1254, hash 73FB07B8 sample 3: - time = 167343 + time = 145099 flags = 1 data = length 1254, hash 73FB07B8 tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/ts/sample_h264_mpeg_audio.ts.2.dump b/testdata/src/test/assets/extractordumps/ts/sample_h264_mpeg_audio.ts.2.dump index 8bf63a39018..605daaf8dd6 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_h264_mpeg_audio.ts.2.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_h264_mpeg_audio.ts.2.dump @@ -19,11 +19,11 @@ track 256: data = length 29, hash 4C2CAE9C data = length 9, hash D971CD89 sample 0: - time = 111221 + time = 66733 flags = 1 data = length 12394, hash A39F5311 sample 1: - time = 144588 + time = 100100 flags = 0 data = length 813, hash 99F7B4FA track 257: @@ -37,19 +37,19 @@ track 257: sampleRate = 44100 language = und sample 0: - time = 111221 + time = 66733 flags = 1 data = length 1253, hash 727FD1C6 sample 1: - time = 137343 + time = 92855 flags = 1 data = length 1254, hash 73FB07B8 sample 2: - time = 163465 + time = 118977 flags = 1 data = length 1254, hash 73FB07B8 sample 3: - time = 189587 + time = 145099 flags = 1 data = length 1254, hash 73FB07B8 tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/ts/sample_h264_no_access_unit_delimiters.ts.1.dump b/testdata/src/test/assets/extractordumps/ts/sample_h264_no_access_unit_delimiters.ts.1.dump index b53c6224892..dbc51ba77d6 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_h264_no_access_unit_delimiters.ts.1.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_h264_no_access_unit_delimiters.ts.1.dump @@ -19,19 +19,19 @@ track 256: data = length 29, hash 4C2CAE9C data = length 9, hash D971CD89 sample 0: - time = 88977 + time = 66733 flags = 0 data = length 734, hash AF0D9485 sample 1: - time = 88977 + time = 66733 flags = 1 data = length 10938, hash 68420875 sample 2: - time = 155710 + time = 133466 flags = 0 data = length 6, hash 34E6CF79 sample 3: - time = 155710 + time = 133466 flags = 0 data = length 518, hash 546C177 tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/ts/sample_h264_no_access_unit_delimiters.ts.2.dump b/testdata/src/test/assets/extractordumps/ts/sample_h264_no_access_unit_delimiters.ts.2.dump index 89899bb4e14..dbc51ba77d6 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_h264_no_access_unit_delimiters.ts.2.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_h264_no_access_unit_delimiters.ts.2.dump @@ -19,19 +19,19 @@ track 256: data = length 29, hash 4C2CAE9C data = length 9, hash D971CD89 sample 0: - time = 111221 + time = 66733 flags = 0 data = length 734, hash AF0D9485 sample 1: - time = 111221 + time = 66733 flags = 1 data = length 10938, hash 68420875 sample 2: - time = 177954 + time = 133466 flags = 0 data = length 6, hash 34E6CF79 sample 3: - time = 177954 + time = 133466 flags = 0 data = length 518, hash 546C177 tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/ts/sample_scte35.ts.1.dump b/testdata/src/test/assets/extractordumps/ts/sample_scte35.ts.1.dump index 7e7eb9ad0cc..b9564a3ffc2 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_scte35.ts.1.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_scte35.ts.1.dump @@ -17,11 +17,11 @@ track 256: initializationData: data = length 22, hash CE183139 sample 0: - time = 55610 + time = 33366 flags = 1 data = length 20711, hash 34341E8 sample 1: - time = 88977 + time = 66733 flags = 0 data = length 18112, hash EC44B35B track 257: @@ -35,19 +35,19 @@ track 257: sampleRate = 44100 language = und sample 0: - time = 44699 + time = 22455 flags = 1 data = length 1253, hash 727FD1C6 sample 1: - time = 70821 + time = 48577 flags = 1 data = length 1254, hash 73FB07B8 sample 2: - time = 96944 + time = 74700 flags = 1 data = length 1254, hash 73FB07B8 sample 3: - time = 123066 + time = 100822 flags = 1 data = length 1254, hash 73FB07B8 track 600: @@ -55,17 +55,17 @@ track 600: sample count = 3 format 0: sampleMimeType = application/x-scte35 - subsampleOffsetUs = -1377756 + subsampleOffsetUs = -1400000 sample 0: - time = 55610 + time = 33366 flags = 1 data = length 35, hash A892AAAF sample 1: - time = 55610 + time = 33366 flags = 1 data = length 35, hash A892AAAF sample 2: - time = 55610 + time = 33366 flags = 1 data = length 35, hash DFA3EF74 tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/ts/sample_scte35.ts.2.dump b/testdata/src/test/assets/extractordumps/ts/sample_scte35.ts.2.dump index 2db85e42e09..b9564a3ffc2 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_scte35.ts.2.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_scte35.ts.2.dump @@ -17,11 +17,11 @@ track 256: initializationData: data = length 22, hash CE183139 sample 0: - time = 77854 + time = 33366 flags = 1 data = length 20711, hash 34341E8 sample 1: - time = 111221 + time = 66733 flags = 0 data = length 18112, hash EC44B35B track 257: @@ -35,19 +35,19 @@ track 257: sampleRate = 44100 language = und sample 0: - time = 66943 + time = 22455 flags = 1 data = length 1253, hash 727FD1C6 sample 1: - time = 93065 + time = 48577 flags = 1 data = length 1254, hash 73FB07B8 sample 2: - time = 119188 + time = 74700 flags = 1 data = length 1254, hash 73FB07B8 sample 3: - time = 145310 + time = 100822 flags = 1 data = length 1254, hash 73FB07B8 track 600: @@ -55,17 +55,17 @@ track 600: sample count = 3 format 0: sampleMimeType = application/x-scte35 - subsampleOffsetUs = -1355512 + subsampleOffsetUs = -1400000 sample 0: - time = 77854 + time = 33366 flags = 1 data = length 35, hash A892AAAF sample 1: - time = 77854 + time = 33366 flags = 1 data = length 35, hash A892AAAF sample 2: - time = 77854 + time = 33366 flags = 1 data = length 35, hash DFA3EF74 tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/ts/sample_scte35.ts.3.dump b/testdata/src/test/assets/extractordumps/ts/sample_scte35.ts.3.dump index cc1c346b49a..e96f346e298 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_scte35.ts.3.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_scte35.ts.3.dump @@ -27,11 +27,11 @@ track 257: sampleRate = 44100 language = und sample 0: - time = 66733 + time = 74700 flags = 1 data = length 1254, hash 73FB07B8 sample 1: - time = 92855 + time = 100822 flags = 1 data = length 1254, hash 73FB07B8 track 600: @@ -39,5 +39,5 @@ track 600: sample count = 0 format 0: sampleMimeType = application/x-scte35 - subsampleOffsetUs = -1355512 + subsampleOffsetUs = -1400000 tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/ts/sample_with_junk.1.dump b/testdata/src/test/assets/extractordumps/ts/sample_with_junk.1.dump index c1b7f37bf3d..f61ecb193a5 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_with_junk.1.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_with_junk.1.dump @@ -17,11 +17,11 @@ track 256: initializationData: data = length 22, hash CE183139 sample 0: - time = 55610 + time = 33366 flags = 1 data = length 20711, hash 34341E8 sample 1: - time = 88977 + time = 66733 flags = 0 data = length 18112, hash EC44B35B track 257: @@ -35,19 +35,19 @@ track 257: sampleRate = 44100 language = und sample 0: - time = 44699 + time = 22455 flags = 1 data = length 1253, hash 727FD1C6 sample 1: - time = 70821 + time = 48577 flags = 1 data = length 1254, hash 73FB07B8 sample 2: - time = 96944 + time = 74700 flags = 1 data = length 1254, hash 73FB07B8 sample 3: - time = 123066 + time = 100822 flags = 1 data = length 1254, hash 73FB07B8 tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/ts/sample_with_junk.2.dump b/testdata/src/test/assets/extractordumps/ts/sample_with_junk.2.dump index 4c0bb6d4abe..f61ecb193a5 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_with_junk.2.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_with_junk.2.dump @@ -17,11 +17,11 @@ track 256: initializationData: data = length 22, hash CE183139 sample 0: - time = 77854 + time = 33366 flags = 1 data = length 20711, hash 34341E8 sample 1: - time = 111221 + time = 66733 flags = 0 data = length 18112, hash EC44B35B track 257: @@ -35,19 +35,19 @@ track 257: sampleRate = 44100 language = und sample 0: - time = 66943 + time = 22455 flags = 1 data = length 1253, hash 727FD1C6 sample 1: - time = 93065 + time = 48577 flags = 1 data = length 1254, hash 73FB07B8 sample 2: - time = 119188 + time = 74700 flags = 1 data = length 1254, hash 73FB07B8 sample 3: - time = 145310 + time = 100822 flags = 1 data = length 1254, hash 73FB07B8 tracksEnded = true diff --git a/testdata/src/test/assets/extractordumps/ts/sample_with_junk.3.dump b/testdata/src/test/assets/extractordumps/ts/sample_with_junk.3.dump index 3bdb0839aea..417481edc32 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_with_junk.3.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_with_junk.3.dump @@ -27,11 +27,11 @@ track 257: sampleRate = 44100 language = und sample 0: - time = 66733 + time = 74700 flags = 1 data = length 1254, hash 73FB07B8 sample 1: - time = 92855 + time = 100822 flags = 1 data = length 1254, hash 73FB07B8 tracksEnded = true diff --git a/testdata/src/test/assets/media/mp4/sample_with_color_info.mp4 b/testdata/src/test/assets/media/mp4/sample_with_color_info.mp4 new file mode 100644 index 00000000000..62d259b81b6 Binary files /dev/null and b/testdata/src/test/assets/media/mp4/sample_with_color_info.mp4 differ diff --git a/testdata/src/test/assets/media/mpd/sample_mpd_availabilityTimeOffset_baseUrl b/testdata/src/test/assets/media/mpd/sample_mpd_availabilityTimeOffset_baseUrl index 188b2778a05..365416825c4 100644 --- a/testdata/src/test/assets/media/mpd/sample_mpd_availabilityTimeOffset_baseUrl +++ b/testdata/src/test/assets/media/mpd/sample_mpd_availabilityTimeOffset_baseUrl @@ -2,31 +2,49 @@ + http://video.com/baseUrl - http://video.com/baseUrl + http://video.com/baseUrl/period - http://video.com/baseUrl + http://video.com/baseUrl/adaptationSet1 - http://video.com/baseUrl + http://video.com/baseUrl/representation2 - http://video.com/baseUrl + http://video-foo.com/baseUrl/adaptationSet3 - http://video.com/baseUrl + /baseUrl/representation3 diff --git a/testdata/src/test/assets/media/mpd/sample_mpd_multiple_baseUrls b/testdata/src/test/assets/media/mpd/sample_mpd_multiple_baseUrls new file mode 100644 index 00000000000..228e64a03b9 --- /dev/null +++ b/testdata/src/test/assets/media/mpd/sample_mpd_multiple_baseUrls @@ -0,0 +1,32 @@ + + + http://video.com/baseUrl/a/ + http://video.com/baseUrl/b/ + http://video.com/baseUrl/c/ + + media/ + files/ + + audio + + + + + video + http://video.com/baseUrl/d/alternative/ + + + + + http://video.com/baseUrl/e/text/ + + + + + diff --git a/testdata/src/test/assets/media/mpd/sample_mpd_vod_location_fallback b/testdata/src/test/assets/media/mpd/sample_mpd_vod_location_fallback new file mode 100644 index 00000000000..32207dde454 --- /dev/null +++ b/testdata/src/test/assets/media/mpd/sample_mpd_vod_location_fallback @@ -0,0 +1,41 @@ + + + http://video.com/baseUrl/a/ + http://video.com/baseUrl/b/ + http://video.com/baseUrl/b/ + http://video.com/baseUrl/d/ + + + + video/ + + + + + + + + + + + + + audio/ + + + + + + + + + + + diff --git a/testdata/src/test/assets/media/rtsp/h264-dump.json b/testdata/src/test/assets/media/rtsp/h264-dump.json new file mode 100644 index 00000000000..6b2e10a770a --- /dev/null +++ b/testdata/src/test/assets/media/rtsp/h264-dump.json @@ -0,0 +1,9 @@ +{ + "trackName": "track1", + "firstSequenceNumber": 0, + "firstTimestamp": 0, + "transmitIntervalMs": 30, + "mediaDescription": "m=video 0 RTP/AVP 96\r\nc=IN IP4 0.0.0.0\r\nb=AS:500\r\na=rtpmap:96 H264/90000\r\na=fmtp:96 packetization-mode=1;profile-level-id=4dE01E;sprop-parameter-sets=Z01AHpZ2BQHtgKBAAAOpgACvyA0YAgQAgRe98HhEI3A=,aN48gA==\r\na=control:track1\r\n", + "packets": [ + ] +} diff --git a/testdata/src/test/assets/media/rtsp/mp4a-latm-dump.json b/testdata/src/test/assets/media/rtsp/mp4a-latm-dump.json new file mode 100644 index 00000000000..a7ee934a832 --- /dev/null +++ b/testdata/src/test/assets/media/rtsp/mp4a-latm-dump.json @@ -0,0 +1,9 @@ +{ + "trackName": "track3", + "firstSequenceNumber": 0, + "firstTimestamp": 0, + "transmitIntervalMs": 30, + "mediaDescription": "m=audio 0 RTP/AVP 97\r\nc=IN IP4 0.0.0.0\r\nb=AS:61\r\na=rtpmap:97 MP4A-LATM/44100/2\r\na=fmtp:97 profile-level-id=15;object=2;cpresent=0;config=400024203FC0\r\na=control:track3\r\n", + "packets": [ + ] +} diff --git a/testdata/src/test/assets/media/ssa/empty_style_line b/testdata/src/test/assets/media/ssa/empty_style_line new file mode 100644 index 00000000000..67ddc926356 --- /dev/null +++ b/testdata/src/test/assets/media/ssa/empty_style_line @@ -0,0 +1,13 @@ +[Script Info] +Title: SSA/ASS Test +Script Type: V4.00+ +PlayResX: 1280 +PlayResY: 720 + +[V4+ Styles] +Format: Name +Style: Empty + +[Events] +Format: Start ,End ,Style,Text +Dialogue: 0:00:01.00,0:00:03.00,Empty,First line. diff --git a/testdata/src/test/assets/media/ttml/rubies.xml b/testdata/src/test/assets/media/ttml/rubies.xml index e149f16dfda..4a655512c2b 100644 --- a/testdata/src/test/assets/media/ttml/rubies.xml +++ b/testdata/src/test/assets/media/ttml/rubies.xml @@ -7,6 +7,8 @@